{"id":345584,"date":"2023-02-17T15:01:24","date_gmt":"2023-02-17T15:01:24","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=345584"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=345584","title":{"rendered":"<span>VueEnt \u2014 \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u0444\u043e\u0440\u043c\u044b \u043d\u0430 Vue \u0438 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/614\/e31\/421\/614e3142179af9ded63f41cb8686d1b3.png\" width=\"583\" height=\"399\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/614\/e31\/421\/614e3142179af9ded63f41cb8686d1b3.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u043f\u043e\u043b\u0442\u043e\u0440\u0430 \u0433\u043e\u0434\u0430 \u043d\u0430\u0437\u0430\u0434 \u0432\u044b\u0448\u043b\u0430 \u043c\u043e\u044f <a href=\"https:\/\/habr.com\/ru\/post\/574044\/\" rel=\"noopener noreferrer nofollow\">\u0441\u0442\u0430\u0442\u044c\u044f<\/a> \u043f\u0440\u043e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 <a href=\"https:\/\/vueent.github.io\/v9s\" rel=\"noopener noreferrer nofollow\">v9s<\/a>. \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u043a\u0440\u0438\u0442\u0438\u043a\u0435 \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445, \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0441\u0435\u0440\u044c\u0435\u0437\u043d\u043e \u043f\u0435\u0440\u0435\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443, \u0443\u0436\u0435 \u0433\u043e\u0434 \u043a\u0430\u043a \u0432\u044b\u0448\u043b\u0430 \u0432\u0442\u043e\u0440\u0430\u044f \u0431\u043e\u043b\u0435\u0435 \u0434\u0440\u0443\u0436\u0435\u043b\u044e\u0431\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f. \u0412 \u0442\u0435\u043a\u0441\u0442\u0435 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0431\u044b\u043b\u043e \u0441\u043a\u0430\u0437\u0430\u043d\u043e \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0442\u044c \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0438 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0444\u043e\u0440\u043c \u043d\u0430 <a href=\"https:\/\/vuejs.org\/\" rel=\"noopener noreferrer nofollow\">Vue<\/a>, \u0430 \u0435\u0449\u0435 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0438\u043d\u0434\u0438\u043a\u0430\u0446\u0438\u044e \u043a \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c \u0447\u0430\u0441\u0442\u044f\u043c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445. \u041f\u043e\u0441\u043b\u0435 \u0441\u0435\u0440\u0438\u0438 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u043e\u0432 \u0441\u043b\u043e\u0436\u0438\u043b\u0441\u044f \u043e\u0431\u0449\u0438\u0439 \u043a\u043e\u043d\u0446\u0435\u043f\u0442 \u043d\u043e\u0432\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438 \u043d\u0435\u0441\u043a\u0440\u043e\u043c\u043d\u043e\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 <code>VueEnt<\/code>, \u043d\u0430\u043c\u0435\u043a\u0430\u044e\u0449\u0435\u0435 \u043d\u0430 \u0441\u0444\u0435\u0440\u0443 \u0435\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f. \u0418\u0442\u0430\u043a, \u0435\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u044e\u0442 \u0442\u0435 \u0436\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043d\u0430 Vue, \u0447\u0442\u043e \u0438\u0437\u043b\u043e\u0436\u0435\u043d\u044b \u0432 \u043c\u043e\u0435\u0439 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435 \u0432\u044b\u0448\u0435, \u0442\u043e \u0437\u0430\u0432\u0430\u0440\u0438\u0442\u0435 \u0447\u0430\u0439\u043a\u0443 \u0438 \u043f\u0440\u0438\u0433\u043e\u0442\u043e\u0432\u044c\u0442\u0435 \u0431\u0443\u0442\u0435\u0440\u0431\u0440\u043e\u0434\u044b, \u0432\u0435\u0434\u044c, \u043d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u043e\u0431\u0437\u043e\u0440\u043d\u044b\u0439 \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438, \u0432 \u0434\u0432\u0443\u0445 \u0441\u043b\u043e\u0432\u0430\u0445 \u0432\u0441\u0435 \u043d\u0435 \u043e\u043f\u0438\u0441\u0430\u0442\u044c.<\/p>\n<p>\u0418\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0440\u0430\u0437\u0431\u0438\u0442\u044c \u0442\u0435\u043a\u0441\u0442 \u043d\u0430 \u0442\u0440\u0438 \u0447\u0430\u0441\u0442\u0438, \u043d\u043e \u0432\u044b\u0445\u043e\u0434\u0438\u0442 \u0442\u0430\u043a, \u0447\u0442\u043e \u0441\u0430\u043c\u0430\u044f \u0432\u0430\u0436\u043d\u0430\u044f \u0438 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u2014 \u0441\u0430\u043c\u0430\u044f \u043e\u0431\u044a\u0435\u043c\u043d\u0430\u044f, \u0431\u0435\u0437 \u043d\u0435\u0435 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0432\u044b\u0433\u043b\u044f\u0434\u044f\u0442 \u043d\u0435\u0437\u043d\u0430\u0447\u0438\u043c\u044b\u043c\u0438 \u043f\u0440\u0438\u0434\u0430\u0442\u043a\u0430\u043c\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u0430\u043c\u044b\u043c \u043d\u0435\u0442\u0435\u0440\u043f\u0435\u043b\u0438\u0432\u044b\u043c \u043c\u043e\u0433\u0443 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0438\u0442\u044c \u043f\u0440\u043e\u0439\u0442\u0438 \u0432 \u043a\u043e\u043d\u0435\u0446 \u043a <a href=\"#%D1%81%D1%81%D1%8B%D0%BB%D0%BA%D0%B8\" rel=\"noopener noreferrer nofollow\">\u0441\u0441\u044b\u043b\u043a\u0430\u043c<\/a>, \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0443 \u0441\u0435\u0431\u044f \u043d\u0430 \u041f\u041a \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0438 <em>\u043f\u043e\u0449\u0443\u043f\u0430\u0442\u044c<\/em> \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u0443\u044e \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0443\u044e.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/4c8\/c47\/288\/4c8c4728885409cab284f66f1686897b.png\" width=\"630\" height=\"775\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/4c8\/c47\/288\/4c8c4728885409cab284f66f1686897b.png\"\/><figcaption><\/figcaption><\/figure>\n<h3>\u0421\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435<\/h3>\n<ol>\n<li>\n<p><a href=\"#%D1%86%D0%B5%D0%BB%D1%8C-%D0%BF%D1%83%D0%B1%D0%BB%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8\" rel=\"noopener noreferrer nofollow\">\u0426\u0435\u043b\u044c \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D0%BE%D1%87%D0%B5%D0%BD%D1%8C-%D1%81%D0%B6%D0%B0%D1%82%D0%BE%D0%B5-%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5-%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B0\" rel=\"noopener noreferrer nofollow\">\u041e\u0447\u0435\u043d\u044c \u0441\u0436\u0430\u0442\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/a> <\/p>\n<ol>\n<li>\n<p><a href=\"#%D0%BE%D1%81%D0%BD%D0%BE%D0%B2%D0%BD%D0%B0%D1%8F-%D1%86%D0%B5%D0%BB%D1%8C-%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B0\" rel=\"noopener noreferrer nofollow\">\u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0446\u0435\u043b\u044c \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D0%BD%D0%B5-%D1%8F%D0%B2%D0%BB%D1%8F%D1%8E%D1%82%D1%81%D1%8F-%D1%86%D0%B5%D0%BB%D1%8F%D0%BC%D0%B8\" rel=\"noopener noreferrer nofollow\">\u041d\u0435 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0446\u0435\u043b\u044f\u043c\u0438<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D1%81%D0%BF%D0%B8%D1%81%D0%BE%D0%BA-%D0%BF%D0%B0%D0%BA%D0%B5%D1%82%D0%BE%D0%B2-%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B0\" rel=\"noopener noreferrer nofollow\">\u0421\u043f\u0438\u0441\u043e\u043a \u043f\u0430\u043a\u0435\u0442\u043e\u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/a> <\/p>\n<ol>\n<li>\n<p><a href=\"#reactive\" rel=\"noopener noreferrer nofollow\">Reactive<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#core\" rel=\"noopener noreferrer nofollow\">Core<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#mix-models\" rel=\"noopener noreferrer nofollow\">Mix Models<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#store\" rel=\"noopener noreferrer nofollow\">Store<\/a><\/p>\n<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<\/li>\n<li>\n<p><a href=\"#%D0%B1%D1%8B%D1%81%D1%82%D1%80%D1%8B%D0%B9-%D1%81%D1%82%D0%B0%D1%80%D1%82\" rel=\"noopener noreferrer nofollow\">\u0411\u044b\u0441\u0442\u0440\u044b\u0439 \u0441\u0442\u0430\u0440\u0442<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D0%B1%D0%BE%D0%BB%D0%B5%D0%B5-%D0%B4%D0%B5%D1%82%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9-%D0%BE%D0%B1%D0%B7%D0%BE%D1%80-%D0%BF%D0%B0%D0%BA%D0%B5%D1%82%D0%BE%D0%B2-%D1%81-%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D0%B0%D0%BC%D0%B8\" rel=\"noopener noreferrer nofollow\">\u0411\u043e\u043b\u0435\u0435 \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u044b\u0439 \u043e\u0431\u0437\u043e\u0440 \u043f\u0430\u043a\u0435\u0442\u043e\u0432 \u0441 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u043c\u0438<\/a> <\/p>\n<ol>\n<li>\n<p><a href=\"#reactive-1\" rel=\"noopener noreferrer nofollow\">Reactive<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#core-1\" rel=\"noopener noreferrer nofollow\">Core<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#mix-models-1\" rel=\"noopener noreferrer nofollow\">Mix Models<\/a> <\/p>\n<ol>\n<li>\n<p><a href=\"#%D0%BF%D0%BE%D1%87%D0%B5%D0%BC%D1%83-%D0%BC%D0%B8%D0%BA%D1%81%D0%B8%D0%BD%D1%8B\" rel=\"noopener noreferrer nofollow\">\u041f\u043e\u0447\u0435\u043c\u0443 \u043c\u0438\u043a\u0441\u0438\u043d\u044b?<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B-%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D1%8F-%D0%B8-%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F\" rel=\"noopener noreferrer nofollow\">\u041f\u0440\u0438\u043c\u0435\u0440\u044b \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D0%BF%D1%80%D0%BE%D1%81%D1%82%D0%BE%D0%B9-%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80\" rel=\"noopener noreferrer nofollow\">\u041f\u0440\u043e\u0441\u0442\u043e\u0439 \u043f\u0440\u0438\u043c\u0435\u0440<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D0%BE%D1%82%D0%BA%D0%B0%D1%82-%D1%81%D0%BE%D1%81%D1%82%D0%BE%D1%8F%D0%BD%D0%B8%D1%8F\" rel=\"noopener noreferrer nofollow\">\u041e\u0442\u043a\u0430\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D1%81%D0%BE%D1%85%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5\" rel=\"noopener noreferrer nofollow\">\u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D0%B2%D0%B0%D0%BB%D0%B8%D0%B4%D0%B0%D1%86%D0%B8%D1%8F\" rel=\"noopener noreferrer nofollow\">\u0412\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D0%B4%D0%BE%D0%BF%D0%BE%D0%BB%D0%BD%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5-%D0%BF%D0%BE%D0%BB%D0%B5\" rel=\"noopener noreferrer nofollow\">\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u043f\u043e\u043b\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D1%81%D0%BB%D0%BE%D0%B6%D0%BD%D0%B0%D1%8F-%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C\" rel=\"noopener noreferrer nofollow\">\u0421\u043b\u043e\u0436\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c<\/a><\/p>\n<\/li>\n<\/ol>\n<\/li>\n<li>\n<p><a href=\"#store-1\" rel=\"noopener noreferrer nofollow\">Store<\/a> <\/p>\n<ol>\n<li>\n<p><a href=\"#%D0%BF%D1%80%D0%BE%D1%81%D1%82%D0%B0%D1%8F-%D0%BA%D0%BE%D0%BB%D0%BB%D0%B5%D0%BA%D1%86%D0%B8%D1%8F\" rel=\"noopener noreferrer nofollow\">\u041f\u0440\u043e\u0441\u0442\u0430\u044f \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D0%BA%D0%BE%D0%BB%D0%BB%D0%B5%D0%BA%D1%86%D0%B8%D1%8F-%D1%81-%D0%B4%D0%BE%D1%81%D1%82%D1%83%D0%BF%D0%BE%D0%BC-%D0%BA%D0%BE-%D0%B2%D0%BD%D0%B5%D1%88%D0%BD%D0%B5%D0%BC%D1%83-%D1%85%D1%80%D0%B0%D0%BD%D0%B8%D0%BB%D0%B8%D1%89%D1%83\" rel=\"noopener noreferrer nofollow\">\u041a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f \u0441 \u0434\u043e\u0441\u0442\u0443\u043f\u043e\u043c \u043a\u043e \u0432\u043d\u0435\u0448\u043d\u0435\u043c\u0443 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0443<\/a><\/p>\n<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<\/li>\n<li>\n<p><a href=\"#%D0%B8%D0%B7%D0%B2%D0%B5%D1%81%D1%82%D0%BD%D1%8B%D0%B5-%D0%BE%D0%B3%D1%80%D0%B0%D0%BD%D0%B8%D1%87%D0%B5%D0%BD%D0%B8%D1%8F\" rel=\"noopener noreferrer nofollow\">\u0418\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D0%B7%D0%B0%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D0%B5\" rel=\"noopener noreferrer nofollow\">\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D1%81%D1%81%D1%8B%D0%BB%D0%BA%D0%B8\" rel=\"noopener noreferrer nofollow\">\u0421\u0441\u044b\u043b\u043a\u0438<\/a><\/p>\n<\/li>\n<\/ol>\n<h3>\u0426\u0435\u043b\u044c \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438<\/h3>\n<p>\u0426\u0435\u043b\u044c\u044e \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0438\u043c\u0435\u044e\u0449\u0435\u0433\u043e\u0441\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f, \u043d\u043e \u0438 \u0432\u044b\u044f\u0441\u043d\u0435\u043d\u0438\u0435 \u043d\u0430\u043b\u0438\u0447\u0438\u044f, \u043b\u0438\u0431\u043e \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u044f \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0430 \u043a \u043f\u0440\u043e\u0435\u043a\u0442\u0443 \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432. \u0414\u0435\u043b\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0441\u0430\u043c\u044b\u0435 \u0442\u0440\u0443\u0434\u043d\u044b\u0435 \u0447\u0430\u0441\u0442\u0438 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0432\u0441\u0435 \u0435\u0449\u0435 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442, \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0441\u043e\u043a\u0440\u0430\u0442\u0438\u043b\u043e\u0441\u044c \u0441 \u0434\u0432\u0443\u0445 \u0434\u043e \u043e\u0434\u043d\u043e\u0433\u043e (\u043c\u0435\u043d\u044f), \u043c\u043e\u0435 \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e \u0432\u0435\u0441\u044c\u043c\u0430 \u0441\u043a\u0440\u043e\u043c\u043d\u044b\u043c\u0438 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c\u0438 \u0440\u0430\u043c\u043a\u0430\u043c\u0438, \u0438 \u0442\u0440\u0430\u0442\u0438\u0442\u044c \u0435\u0433\u043e \u043d\u0430 \u043d\u0438\u043a\u043e\u043c\u0443 \u043d\u0435 \u043d\u0443\u0436\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0431\u0430\u043d\u0430\u043b\u044c\u043d\u043e \u0436\u0430\u043b\u043a\u043e. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u0435\u0441\u043b\u0438 \u043a\u0442\u043e-\u043b\u0438\u0431\u043e \u0437\u0430\u0445\u043e\u0447\u0435\u0442 \u043f\u043e\u043c\u043e\u0447\u044c \u043f\u0440\u0430\u0432\u043a\u0430\u043c\u0438, \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438, \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u043a\u0440\u0438\u0442\u0438\u043a\u043e\u0439 \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445 \u0438\u043b\u0438 \u043b\u044e\u0431\u044b\u043c \u0438\u043d\u044b\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c \u2014 \u0431\u0443\u0434\u0443 \u0440\u0430\u0434.<\/p>\n<h3>\u041e\u0447\u0435\u043d\u044c \u0441\u0436\u0430\u0442\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/h3>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/4da\/016\/4d9\/4da0164d98265764931a892087c5f480.png\" width=\"256\" height=\"256\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/4da\/016\/4d9\/4da0164d98265764931a892087c5f480.png\"\/><figcaption><\/figcaption><\/figure>\n<p><a href=\"https:\/\/vueent.github.io\/vueent\/\" rel=\"noopener noreferrer nofollow\">VueEnt<\/a> \u044d\u0442\u043e \u043d\u0430\u0431\u043e\u0440 \u0438\u0437 \u0447\u0435\u0442\u044b\u0440\u0435\u0445 \u043f\u0430\u043a\u0435\u0442\u043e\u0432, \u0442\u0440\u0438 \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b \u0434\u0440\u0443\u0433 \u043e\u0442 \u0434\u0440\u0443\u0433\u0430. \u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u043a\u0430\u043a Vue 3, \u0442\u0430\u043a \u0438 Vue 2.7, \u043b\u0438\u0431\u043e Vue 2.6 \u0441 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u043c <a href=\"https:\/\/github.com\/vuejs\/composition-api\" rel=\"noopener noreferrer nofollow\">@vue\/composition-api<\/a>.<\/p>\n<h4>\u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0446\u0435\u043b\u044c \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/h4>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0446\u0435\u043b\u044c\u044e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u044b\u0445 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Vue. \u0412\u0435\u0441\u044c \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d \u043d\u0430 <a href=\"https:\/\/www.typescriptlang.org\/\" rel=\"noopener noreferrer nofollow\">TypeScript<\/a>, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u0434\u043d\u043e\u0439 \u0438\u0437 \u0432\u0430\u0436\u043d\u044b\u0445 \u0446\u0435\u043b\u0435\u0439 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0443\u0434\u043e\u0431\u0441\u0442\u0432 \u0432 \u0432\u0438\u0434\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0430\u0432\u0442\u043e\u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0438 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c\u044b\u0445 \u0442\u0438\u043f\u043e\u0432. \u041e\u0442\u0447\u0430\u0441\u0442\u0438 \u0438\u0437-\u0437\u0430 \u044d\u0442\u043e\u0433\u043e, \u043e\u0442\u0447\u0430\u0441\u0442\u0438 \u0438\u0437 \u0444\u0438\u043b\u043e\u0441\u043e\u0444\u0441\u043a\u0438\u0445 \u043f\u043e\u0431\u0443\u0436\u0434\u0435\u043d\u0438\u0439, \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043d\u0438\u043a\u0430\u043a\u043e\u0439 \u043c\u0430\u0433\u0438\u0438. \u0421 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b, \u044d\u0442\u043e \u043f\u043e\u0440\u043e\u0436\u0434\u0430\u0435\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u043d\u043e\u0433\u043e\u0441\u043b\u043e\u0432\u043d\u043e\u0441\u0442\u044c, \u043d\u043e \u0441 \u0434\u0440\u0443\u0433\u043e\u0439, \u0432\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u0430\u043a, \u043a\u0430\u043a \u043e\u0436\u0438\u0434\u0430\u0435\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a, \u0437\u0430 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u0435\u0432, \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0445 \u0441 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f\u043c\u0438 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 Vue.<\/p>\n<h4>\u041d\u0435 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0446\u0435\u043b\u044f\u043c\u0438<\/h4>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0435\u0449\u0435 \u043e\u0434\u043d\u043e\u0433\u043e \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 Vue \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0446\u0435\u043b\u044c\u044e VueEnt. \u0422\u0430\u043a\u0436\u0435 \u0446\u0435\u043b\u044c\u044e \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430\u0432\u044f\u0437\u044b\u0432\u0430\u043d\u0438\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0443 \u043a\u0430\u043a\u043e\u0439-\u043b\u0438\u0431\u043e \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b \u0438\u043b\u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u0441\u0435 \u043f\u0430\u043a\u0435\u0442\u044b \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b \u0434\u0440\u0443\u0433 \u043e\u0442 \u0434\u0440\u0443\u0433\u0430 \u0438 \u043c\u043e\u0433\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0438\u043b\u0438 \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u043e \u0436\u0435\u043b\u0430\u043d\u0438\u044e.<\/p>\n<h4>\u0421\u043f\u0438\u0441\u043e\u043a \u043f\u0430\u043a\u0435\u0442\u043e\u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/h4>\n<h3>Reactive<\/h3>\n<p>\u041f\u0430\u043a\u0435\u0442 <code>@vueent\/reactive<\/code> \u2014 \u044d\u0442\u043e \u043d\u0430\u0431\u043e\u0440 \u0434\u0435\u043a\u043e\u0440\u0430\u0442\u043e\u0440\u043e\u0432 TypeScript, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>ref<\/code>&#8212; \u0438 <code>computed<\/code>-\u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 Vue \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u043e\u043b\u0435\u0439 ES-\u043a\u043b\u0430\u0441\u0441\u043e\u0432.<\/p>\n<h3>Core<\/h3>\n<p>\u041f\u0430\u043a\u0435\u0442 <code>@vueent\/core<\/code>, \u043d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u2014 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u0442\u0430\u043a\u0438\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438, \u043a\u0430\u043a \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u044b \u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u044b, \u0432\u043e Vue-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435.<\/p>\n<h3>Mix Models<\/h3>\n<p>\u041f\u0430\u043a\u0435\u0442 <code>@vueent\/mix-models<\/code> \u2014 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0430\u044f \u043a\u043b\u0430\u0441\u0441\u044b \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u0434\u043b\u044f <a href=\"https:\/\/ru.wikipedia.org\/wiki\/NoSQL\" rel=\"noopener noreferrer nofollow\">NoSQL<\/a>-\u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u0441 \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f, \u043e\u0442\u043a\u0430\u0442\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f (<em>rollback<\/em>) \u0438 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438. \u0418\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u043e\u0442 \u043f\u0430\u043a\u0435\u0442 \u0441\u0430\u043c\u044b\u0439 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0430\u043c\u044b\u043c \u0431\u043e\u043b\u044c\u0448\u0438\u043c \u0438 \u0432\u0430\u0436\u043d\u044b\u043c \u0432\u043e \u0432\u0441\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435.<\/p>\n<h3>Store<\/h3>\n<p>\u042d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0430\u043a\u0435\u0442 <code>@vueent\/store<\/code> \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043a\u043b\u0430\u0441\u0441\u044b \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439 \u043c\u043e\u0434\u0435\u043b\u0435\u0439, \u0442\u043e \u0435\u0441\u0442\u044c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u0441\u0438\u043b\u044c\u043d\u043e \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u043d\u044b\u0439 \u0430\u043d\u0430\u043b\u043e\u0433 <a href=\"https:\/\/github.com\/emberjs\/data\" rel=\"noopener noreferrer nofollow\">ember-data<\/a>, \u043d\u043e \u0431\u0435\u0437 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0440\u0435\u043b\u044f\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u0441\u0432\u044f\u0437\u0435\u0439.<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435:<\/strong> \u0415\u0441\u043b\u0438 \u0432\u0430\u043c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u043c\u043e\u0434\u0435\u043b\u044f\u043c\u0438, \u0442\u043e \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u0441\u0440\u0430\u0437\u0443 \u0436\u0435 \u043f\u0440\u043e\u043b\u0438\u0441\u0442\u0430\u0442\u044c \u0434\u043e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0433\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0430, \u0442\u0430\u043a \u043a\u0430\u043a \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044e \u044d\u0442\u043e \u043d\u0438\u043a\u0430\u043a \u043d\u0435 \u043f\u043e\u043c\u0435\u0448\u0430\u0435\u0442.<\/p>\n<h3>\u0411\u044b\u0441\u0442\u0440\u044b\u0439 \u0441\u0442\u0430\u0440\u0442<\/h3>\n<p>\u0414\u043b\u044f \u0442\u0435\u0445, \u043a\u043e\u043c\u0443 \u043b\u0435\u043d\u044c \u0447\u0438\u0442\u0430\u0442\u044c \u0442\u0435\u043a\u0441\u0442, \u043d\u043e \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u043f\u043e\u0449\u0443\u043f\u0430\u0442\u044c \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 \u0440\u0430\u0431\u043e\u0447\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435, \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043b\u0435\u043d \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 <a href=\"https:\/\/github.com\/vueent\/vueent-quick-start\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u043e\u0435\u043a\u0442<\/a>:<\/p>\n<pre><code class=\"bash\">git clone https:\/\/github.com\/vueent\/vueent-quick-start.git cd vueent-quick-start npm i npm run dev<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0435\u043a\u0442 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u0441\u043f\u0438\u0441\u043a\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432, \u0433\u0434\u0435 \u0443 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0435\u0441\u0442\u044c \u0438\u043c\u044f, \u0444\u0430\u043c\u0438\u043b\u0438\u044f, \u0442\u0435\u043b\u0435\u0444\u043e\u043d \u0438 \u0432\u043e\u0437\u0440\u0430\u0441\u0442. \u0414\u0430\u043d\u043d\u044b\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u044e\u0442\u0441\u044f \u0432 <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/IndexedDB_API\/Using_IndexedDB\" rel=\"noopener noreferrer nofollow\">IndexedDB<\/a>. \u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043f\u043e\u044f\u0441\u043d\u044f\u044e\u0449\u0438\u0435 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438.<\/p>\n<p>\u0425\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u0442\u0430\u043a\u0436\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043d\u043e \u044d\u0442\u0430 \u0442\u0435\u043c\u0430 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043e\u0431\u0448\u0438\u0440\u043d\u0430 \u0438 \u0437\u0430\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u0435\u0442 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438.<\/p>\n<h3>\u0411\u043e\u043b\u0435\u0435 \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u044b\u0439 \u043e\u0431\u0437\u043e\u0440 \u043f\u0430\u043a\u0435\u0442\u043e\u0432 \u0441 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u043c\u0438<\/h3>\n<h4>Reactive<\/h4>\n<p>\u041a\u043e\u0433\u0434\u0430 \u044f \u0432\u043f\u0435\u0440\u0432\u044b\u0435 \u0443\u0432\u0438\u0434\u0435\u043b Vue Composition API, \u0442\u043e \u0441\u0440\u0430\u0437\u0443 \u0436\u0435 \u043f\u043e\u0434\u0443\u043c\u0430\u043b \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0442\u0435\u043f\u0435\u0440\u044c \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c \u0443\u0434\u043e\u0431\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432, \u043d\u043e \u0438 \u0437\u0430 \u0438\u0445 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u043c\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0432 \u043a\u0430\u043a\u0438\u0445-\u043d\u0438\u0431\u0443\u0434\u044c \u043a\u043b\u0430\u0441\u0441\u0430\u0445. \u041e\u0434\u043d\u0430\u043a\u043e \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u0432\u0438\u0434\u0435\u0442\u044c \u043e\u0431\u044b\u0447\u043d\u044b\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430, \u0430 \u043d\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b, \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u043e\u043b\u0435\u0439 \u043a\u043b\u0430\u0441\u0441\u043e\u0432, \u0432\u0435\u0434\u044c \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u044d\u0442\u043e \u043f\u043e\u043b\u0435 \u043a\u043b\u0430\u0441\u0441\u0430 \u043d\u0435 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e, \u0430 \u0437\u0430\u0432\u0442\u0440\u0430 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c\u0441\u044f. \u0415\u0441\u043b\u0438 \u0432\u044b \u043f\u0440\u043e\u0431\u043e\u0432\u0430\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>ref<\/code> \u0438 <code>computed<\/code> \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432 \u043a\u043b\u0430\u0441\u0441\u043e\u0432, \u0442\u043e \u043c\u043e\u0433\u043b\u0438 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u044d\u0442\u043e \u043d\u0435 \u0441\u043b\u0438\u0448\u043a\u043e\u043c-\u0442\u043e \u0443\u0434\u043e\u0431\u043d\u043e. \u0418\u0442\u0430\u043a, \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0439\u0442\u0435 \u0434\u0435\u043a\u043e\u0440\u0430\u0442\u043e\u0440\u044b <code>tracked<\/code> (\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 <code>ref<\/code>) \u0438 <code>calculated<\/code> (\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 <code>computed<\/code>):<\/p>\n<pre><code class=\"typescript\">import { tracked, calculated } from '@vueent\/reactive';  class MyClass {   @tracked public num = 2;   @tracked public factor = 3;    @calculated public get mul() {     console.log('calculate mul');      return this.num * this.factor;   } }  const my = new MyClass();  my.factor = 4;  console.log(my.mul); \/\/ \"calculate mul\", 8 - \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043a\u0430\u043a \u043e\u0436\u0438\u0434\u0430\u043b\u043e\u0441\u044c console.log(my.mul); \/\/ 8 - \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0433\u043e \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u043d\u0435\u0442, \u043a\u0430\u043a \u0438 \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u043e<\/code><\/pre>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435:<\/strong> \u041d\u0430\u0447\u0438\u043d\u0430\u044f \u0441 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 TypeScript, \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0434\u0435\u043a\u043e\u0440\u0430\u0442\u043e\u0440\u044b, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0430 \u0432 <code>tsconfig.json<\/code>:<\/p>\n<pre><code class=\"json\">\"moduleResolution\": \"node\", \"useDefineForClassFields\": false, \"experimentalDecorators\": true<\/code><\/pre>\n<p>\u041a\u0430\u043a \u0438 \u0431\u044b\u043b\u043e \u0441\u043a\u0430\u0437\u0430\u043d\u043e \u0432 \u0441\u0430\u043c\u043e\u043c \u043d\u0430\u0447\u0430\u043b\u0435, \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u043e\u0431\u0437\u043e\u0440\u043d\u0430\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0437\u0430 \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u044b\u043c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u043f\u0430\u043a\u0435\u0442\u0430 \u043f\u0440\u043e\u0448\u0443 \u043f\u0440\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u043f\u043e <a href=\"https:\/\/vueent.github.io\/vueent\/guide\/reactive.html\" rel=\"noopener noreferrer nofollow\">\u0441\u0441\u044b\u043b\u043a\u0435<\/a>.<\/p>\n<h4>Core<\/h4>\n<p>\u0418\u0434\u0435\u044f <code>@vueent\/core<\/code> \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u043d\u0430 Vue. \u0418\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438 \u043d\u0430\u043c \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e views \u0438\u043b\u0438 pages (\u0435\u0441\u043b\u0438 \u0440\u0435\u0447\u044c \u043f\u0440\u043e <a href=\"https:\/\/nuxtjs.org\/\" rel=\"noopener noreferrer nofollow\">Nuxt<\/a>) \u0434\u043b\u044f \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432-\u043c\u0430\u0440\u0448\u0440\u0443\u0442\u043e\u0432, \u0445\u043e\u0442\u044f \u0441\u0430\u043c \u043f\u043e \u0441\u0435\u0431\u0435 Vue \u0432\u043e\u043e\u0431\u0449\u0435 \u043d\u0435 \u043d\u0430\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442 \u043a\u0430\u043a\u0438\u0445-\u043b\u0438\u0431\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439 \u043d\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0444\u0430\u0439\u043b\u043e\u0432. \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0432\u0445\u043e\u0434\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u043e\u0439 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0430 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442. \u041d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u043f\u043e Vue \u044f \u043d\u0435 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u043b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 (\u043f\u043e\u043f\u0440\u0430\u0432\u044c\u0442\u0435, \u0435\u0441\u043b\u0438 \u044f \u0441\u043b\u0435\u043f), \u043d\u043e \u0442\u0430\u043c \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<blockquote>\n<p>Components allow us to split the UI into independent and reusable pieces, and think about each piece in isolation.<\/p>\n<\/blockquote>\n<blockquote>\n<p>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u043d\u0430\u043c \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043d\u0430 \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b\u0435 \u0438 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 \u0447\u0430\u0441\u0442\u0438 \u0438 \u0434\u0443\u043c\u0430\u0442\u044c \u043e \u043a\u0430\u0436\u0434\u043e\u0439 \u0438\u0437 \u043d\u0438\u0445 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e.<\/p>\n<\/blockquote>\n<p>\u0422\u043e \u0435\u0441\u0442\u044c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u044f\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u043d\u0435 \u0447\u0442\u043e \u0438\u043d\u043e\u0435, \u043a\u0430\u043a <em>\u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435<\/em>, \u0433\u043e\u0432\u043e\u0440\u044f \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043c\u0438 \u0442\u043e\u0433\u043e \u0436\u0435 <a href=\"https:\/\/ru.wikipedia.org\/wiki\/Model-View-ViewModel\" rel=\"noopener noreferrer nofollow\">MVVM<\/a>. \u0415\u0441\u043b\u0438 \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u043a\u0430\u043a \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435, \u0442\u043e \u043e\u043d \u043d\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0432 \u0441\u0435\u0431\u044f \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0443, \u0445\u043e\u0442\u044f \u0438\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u043e \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0447\u0430\u0441\u0442\u043e \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u043d\u0430 Vue \u0438 <a href=\"https:\/\/reactjs.org\/\" rel=\"noopener noreferrer nofollow\">React<\/a>. \u0414\u043b\u044f \u0438\u043d\u043a\u0430\u043f\u0441\u0443\u043b\u044f\u0446\u0438\u0438 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0438 \u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0434\u0430\u043d\u043d\u044b\u043c \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441\u044b, \u0430 \u0434\u043b\u044f \u043e\u0442\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0441\u043b\u043e\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043e\u0442 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u044b (\u0445\u043e\u0442\u044f, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043d\u0435 \u0441\u0430\u043c\u043e\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0435\u0435). \u0418\u043c\u0435\u043d\u043d\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u044b \u0441 \u043b\u0435\u043d\u0438\u0432\u043e\u0439 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u0430\u043a\u0435\u0442 <code>@vueent\/core<\/code>. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0440\u0435\u0444\u0435\u0440\u0435\u043d\u0441\u043d\u044b\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u043c\u043e\u0436\u043d\u043e \u0432\u0437\u044f\u0442\u044c <a href=\"https:\/\/angular.io\/\" rel=\"noopener noreferrer nofollow\">Angular<\/a> \u0438\u043b\u0438 <a href=\"https:\/\/emberjs.com\/\" rel=\"noopener noreferrer nofollow\">Ember<\/a>. \u0422\u0430\u043a\u0436\u0435 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u044d\u0442\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430 \u043d\u0430\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u043d\u0430 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044e \u0437\u0434\u0435\u0441\u044c, <a href=\"https:\/\/habr.com\/ru\/company\/simbirsoft\/blog\/556270\/\" rel=\"noopener noreferrer nofollow\">\u043d\u0430 \u0445\u0430\u0431\u0440\u0435<\/a>, \u043d\u0435\u043f\u043b\u043e\u0445\u043e \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0449\u0443\u044e \u043a\u043e\u043d\u0446\u0435\u043f\u0442.<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u044b \u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043f\u0435\u0440\u0432\u0430 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c <em>\u044f\u0434\u0440\u043e<\/em>:<\/p>\n<pre><code class=\"typescript\">\/\/ file: .\/vueent.ts import { initVueent } from '@vueent\/core';  export const {   useVueent,   registerService,   registerController,   useService,   useController,   injectService,   injectController } = initVueent();<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043a\u043b\u0438\u043a\u043e\u0432:<\/p>\n<pre><code class=\"typescript\">\/\/ file: .\/services\/clicker.ts import { Service } from '@vueent\/core'; import { tracked } from '@vueent\/reactive';  import { registerService } from '@\/vueent';  export default class ClickerService extends Service {   @tracked private _counter = 0; \/\/ \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e    public get counter() {     return this._counter;   }    public increment() {     ++this._counter;   } }  registerService(ClickerService); \/\/ \u043d\u0443\u0436\u043d\u043e \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u0440\u0441\u0438\u0441<\/code><\/pre>\n<p>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0439 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u043c\u0443 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0443 \u0438 \u043c\u0435\u0442\u043e\u0434\u0443, \u0438\u0437\u043c\u0435\u043d\u044f\u044e\u0449\u0435\u043c\u0443 \u0435\u0433\u043e:<\/p>\n<pre><code class=\"typescript\">\/\/ file: .\/app.ts import { Controller } from '@vueent\/core';  import { registerController, injectService as service } from '@\/vueent'; import ClickerService from '@\/services\/clicker';  export default class AppController extends Controller {   \/\/ \u043b\u0435\u043d\u0438\u0432\u0430\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u0435\u0440\u0432\u0438\u0441\u0430   @service(ClickerService) private readonly clicker!: ClickerService;    public readonly date: number;    public get counter() {     return this.clicker.counter; \/\/ \u0432\u043e\u0437\u0432\u0440\u0430\u0442 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0441\u0435\u0440\u0432\u0438\u0441\u0430   }    constructor(date: number) {     super();     this.date = date;   }    public init() {     console.log('onBeforeMount');   }    public reset() {     console.log('onBeforeUnmount');   }    public destroy() {     console.log('onUnmounted'); \/\/ \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043d\u0430\u0431\u043b\u044e\u0434\u0430\u0442\u0435\u043b\u0435\u0439 (watchers), \u0442\u0430\u0439\u043c\u0435\u0440\u043e\u0432 \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435   }    public increment() {     this.clicker.increment();   } }  registerController(AppController); \/\/ \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u0442\u0430\u043a\u0436\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c<\/code><\/pre>\n<p>\u041d\u0430\u043a\u043e\u043d\u0435\u0446, \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"xml\">&lt;!-- file: app.vue:template --> &lt;template> &lt;div>   &lt;div>Started at: {{ timestamp }}&lt;\/div>   &lt;div>Button clicks: {{ counter }}&lt;\/div>   &lt;div>     &lt;button type=\"button\" @click=\"increment\">Increment&lt;\/button>   &lt;\/div> &lt;\/div> &lt;\/template><\/code><\/pre>\n<pre><code class=\"typescript\">\/\/ file: app.vue:script import { defineComponent, computed } from 'vue';  import { useController } from '@\/vueent';  import AppController from '.\/app';  function setup() {   \/\/ \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 \u0441 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438.   const controller = useController(AppController, new Date().getTime());    const increment = () => controller.increment();   const counter = computed(() => controller.counter);    return {     timestamp: controller.date, \/\/ \u043d\u0435\u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435     counter, \/\/ \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u043c\u043e\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e     increment   }; }  export default defineComponent({ setup });<\/code><\/pre>\n<p>\u041f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u043f\u0440\u0438\u043c\u0435\u0440 \u0441\u0438\u043d\u0442\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439, \u043d\u043e \u043e\u043d \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u043d\u0443\u044e \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443: \u0434\u0430\u043d\u043d\u044b\u0435 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u043c <code>ClickerService<\/code>, \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 <code>AppController<\/code>, \u0438 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u043b\u0438\u0448\u044c \u0437\u0430 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433 \u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u0432\u0441\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u043d \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0438\u0437 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 \u0438 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0437\u043d\u0430\u0435\u0442 \u043e \u0442\u043e\u043c, \u043e\u0442\u043a\u0443\u0434\u0430 \u044d\u0442\u0438 \u043e\u043d\u0438 \u0431\u0435\u0440\u0443\u0442\u0441\u044f \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435. \u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u0438 \u0437\u0430\u043c\u0435\u043d\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0431\u0435\u0437 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445, \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043b\u0438\u0448\u044c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442.<\/p>\n<p>\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0443\u044e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e \u043f\u043e \u0434\u0430\u043d\u043d\u043e\u043c\u0443 \u043f\u0430\u043a\u0435\u0442\u0443 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u043f\u043e <a href=\"https:\/\/vueent.github.io\/vueent\/guide\/core.html\" rel=\"noopener noreferrer nofollow\">\u0441\u0441\u044b\u043b\u043a\u0435<\/a>.<\/p>\n<h4>Mix Models<\/h4>\n<p>\u0427\u0442\u043e \u0436, \u043f\u0440\u0438\u0448\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u0441\u0430\u043c\u043e\u0439 \u043e\u0431\u044a\u0435\u043c\u043d\u043e\u0439 \u0438 \u0441\u0430\u043c\u043e\u0439, \u043d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u043f\u043e\u043b\u0435\u0437\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438. \u041a\u0430\u043a \u0431\u044b\u043b\u043e \u0441\u043a\u0430\u0437\u0430\u043d\u043e \u0432\u044b\u0448\u0435, \u043f\u0430\u043a\u0435\u0442 <code>@vueent\/mix-models<\/code> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0435 \u043c\u043e\u0434\u0435\u043b\u0438.<\/p>\n<p>\u041a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043d\u044f\u0442\u044c \u0438\u0437 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f, \u043a\u043b\u0430\u0441\u0441\u044b \u0441\u0442\u0440\u043e\u044f\u0442\u0441\u044f \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043c\u0438\u043a\u0441\u0438\u043d\u043e\u0432.<\/p>\n<h3>\u041f\u043e\u0447\u0435\u043c\u0443 \u043c\u0438\u043a\u0441\u0438\u043d\u044b?<\/h3>\n<p>\u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435, \u043c\u0438\u043a\u0441\u0438\u043d\u044b \u2014 \u044d\u0442\u043e \u043a\u043e\u043c\u043f\u0440\u043e\u043c\u0438\u0441\u0441. \u041c\u043e\u0436\u043d\u043e \u0432\u0437\u044f\u0442\u044c, \u0443\u0441\u043b\u043e\u0432\u043d\u043e, \u0447\u0435\u0442\u044b\u0440\u0435 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u043d\u0443\u0436\u043d\u043e\u0433\u043e \u0432\u0438\u0434\u0430:<\/p>\n<ol>\n<li>\n<p>\u041d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0432 \u043f\u0430\u0440\u0430\u0434\u0438\u0433\u043c\u0435 \u041e\u041e\u041f<\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0439<\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u043e\u0432<\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u0438\u043a\u0441\u0438\u043d\u043e\u0432<\/p>\n<\/li>\n<\/ol>\n<p>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0441 \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0440\u043e\u0432\u043d\u043e \u043e\u0434\u043d\u0430: \u0438\u0435\u0440\u0430\u0440\u0445\u0438\u044f \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u0438\u0447\u043d\u0430. \u0415\u0441\u043b\u0438 \u043e\u0442 \u0431\u0430\u0437\u043e\u0432\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438 \u0443\u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439, \u0441\u043a\u0430\u0436\u0435\u043c, \u043e\u0442\u043a\u0430\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f (<em>rollback<\/em>), \u0430 \u043f\u043e\u0442\u043e\u043c \u043e\u0442 \u043d\u0435\u0433\u043e \u2014 \u043a\u043b\u0430\u0441\u0441, \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435, \u0442\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438, \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435, \u043d\u043e \u043d\u0435 \u043e\u0442\u043a\u0430\u0442, \u0443\u0436\u0435 \u043d\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u043c. \u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435, \u043d\u043e \u043d\u0435 \u043e\u0442\u043a\u0430\u0442, \u0430 \u043f\u043e\u0442\u043e\u043c \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0442\u043e\u0440\u043d\u044b\u0439 \u0440\u043e\u0441\u0442 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0445 \u043a\u043b\u0430\u0441\u0441\u043e\u0432, \u0447\u0442\u043e \u0432\u0440\u044f\u0434 \u043b\u0438 \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442 \u0436\u0438\u0437\u043d\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438. \u041f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<pre><code class=\"typescript\">class BaseModel {}  class RollbackModel extends BaseModel {}  class SaveModel extends RollbackModel {}  class ValidateModel extends SaveModel {}  \/\/ \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u0441\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u043d\u0435 \u043d\u0443\u0436\u043d\u044b. class MyModel extends ValidateModel {}<\/code><\/pre>\n<p>\u0423 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e \u0438\u043d\u043e\u0433\u043e \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440\u0430: \u043e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u0441 \u043d\u0443\u043b\u044f, \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0443 \u0440\u0430\u0437\u043d\u044b\u0445 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u043e\u0432 \u043c\u043e\u0434\u0435\u043b\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0431\u0449\u0435\u0433\u043e \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u0430, \u0438 \u0432\u0441\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0431\u0443\u0434\u0443\u0442 \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f, \u0432\u044b\u0437\u044b\u0432\u0430\u044f \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0440\u043e\u0441\u0442 \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u044f \u043f\u0430\u043c\u044f\u0442\u0438. \u041f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<pre><code class=\"typescript\">interface A {   n: number; }  \/\/ \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u0441 \u0447\u0438\u0441\u043b\u043e\u0432\u044b\u043c \u043f\u043e\u043b\u0435\u043c n function a(): A {   return { n: 0 }; }  \/\/ \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 \u0441 \u043f\u043e\u043b\u0435\u043c digits \u0438 \u043c\u0435\u0442\u043e\u0434\u043e\u043c print function b() {   return {     digits: 2,     print() {       console.log(((this as unknown) as A).n.toFixed(this.digits));     }   }; }  \/\/ \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 \u0441 \u043c\u0435\u0442\u043e\u0434\u043e\u043c add, \u0441\u0443\u043c\u043c\u0438\u0440\u0443\u044e\u0449\u0438\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 n \u0438 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 op function c() {   return {     add(op: number): void {       ((this as unknown) as A).n += op;     }   }; }  \/\/ \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0438\u0442\u043e\u0433\u043e\u0432\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u043c\u043e\u0434\u0435\u043b\u0438 const my = { ...a(), ...b(), ...c() };  my.add(2.2222); my.print(); \/\/ 2.22  \/\/ \u043d\u043e\u0432\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442, \u0432\u0441\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0442\u0430\u043a\u0436\u0435 \u0434\u0443\u0431\u043b\u0438\u0440\u0443\u044e\u0442\u0441\u044f const my2 = { ...a(), ...b(), ...c() };<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u0442\u044c, \u0447\u0442\u043e JS \u2014 \u044d\u0442\u043e \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u043d\u043e-\u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u044f\u0437\u044b\u043a, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u043e\u0431\u043e\u0439\u0442\u0438 \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u043e\u0432, \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u044f \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u043d\u0435 \u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043c\u043e\u0434\u0435\u043b\u0438, \u0430 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f.<\/p>\n<pre><code class=\"typescript\">interface Creator&lt;T extends A> {   new (...args: any[]): T;   (...args: any[]): T; }  interface A {   n: number; }  \/\/ \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u043f\u0443\u0441\u0442\u043e\u0439 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f \u0438 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u0434\u043b\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0441 \u043f\u043e\u043b\u0435\u043c n function a() {   const proto = {};    return {     setup: function(this: A) {       Object.setPrototypeOf(this, proto);       this.n = 0;        return this;     } as Creator&lt;A>,     proto   }; }  interface B {   digits: number;   print(): void; }  \/\/ \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u043a \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u0443 \u043c\u0435\u0442\u043e\u0434 print \u0438 \u043f\u043e\u0434\u043c\u0435\u0448\u0438\u0432\u0430\u0435\u0442 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e-\u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u043e\u043b\u044f digits. function b&lt;T extends A>({ proto, setup }: { proto: any; setup: Creator&lt;T> }) {   proto.print = function(this: T &amp; B) {     console.log(this.n.toFixed(this.digits));   };    return {     setup: function(this: T &amp; B, ...args: any[]) {       setup.call(this, ...args);        this.digits = 2;        return this;     } as Creator&lt;T &amp; B>,     proto   }; }  interface C {   add(op: number): void; }  \/\/ \u043f\u043e\u0434\u043c\u0435\u0448\u0438\u0432\u0430\u0435\u0442 \u0432 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f \u043c\u0435\u0442\u043e\u0434 add function c&lt;T extends A>({ proto, setup }: { proto: any; setup: Creator&lt;T> }) {   proto.add = function(this: T &amp; C, op: number) {     this.n += op;   };    return { proto, setup: setup as Creator&lt;T &amp; C> }; }   const ABC = c(b(a())).setup; \/\/ \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u043d\u0443\u0436\u043d\u044b\u0439 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f \u0438 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 const abc = new ABC(); \/\/ \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440  abc.add(2.2222); abc.print(); \/\/ 2.22  const AB = b(a()).setup; const ab = new AB();  ab.n = 2; ab.print(); \/\/ 2.00  const AC = c(a()).setup; const ac = new AC();  ac.add(2.2222); console.log(ac.n); \/\/ 2.2222<\/code><\/pre>\n<p>\u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043d\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442, \u043c\u044f\u0433\u043a\u043e \u0433\u043e\u0432\u043e\u0440\u044f, \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0447\u0438\u0441\u0442\u043e. \u0412\u043f\u0440\u043e\u0447\u0435\u043c, \u043d\u0430 \u0437\u0430\u0440\u0435 JS \u0438\u043d\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 \u0438 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u043b\u043e, \u043d\u043e \u043c\u044b \u0443\u0436\u0435 \u0434\u0430\u0432\u043d\u043e \u043d\u0435 \u043d\u0430 \u0437\u0430\u0440\u0435 JS, \u0442\u0430\u043a \u0447\u0442\u043e \u043c\u043e\u0436\u0435\u043c \u0441\u0435\u0431\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u0438\u043a\u0441\u0438\u043d\u044b. \u0417\u0430 \u0447\u0443\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u044b\u043c\u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u043c\u0438, \u043c\u043e\u0436\u043d\u043e \u0442\u0430\u043a\u0436\u0435 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c\u0441\u044f \u043a <a href=\"https:\/\/vueent.github.io\/vueent\/guide\/mix-models.html\" rel=\"noopener noreferrer nofollow\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/a>.<\/p>\n<p>\u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u043e\u0431\u043e\u0431\u0449\u0435\u043d\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b \u0438 \u043c\u0438\u043a\u0441\u0438\u043d\u044b \u2014 \u043d\u0435 \u0441\u0430\u043c\u0430\u044f \u043f\u0440\u0438\u044f\u0442\u043d\u0430\u044f \u0441\u043c\u0435\u0441\u044c, \u043d\u043e \u044d\u0442\u043e \u043a\u043e\u043c\u043f\u0440\u043e\u043c\u0438\u0441\u0441 \u043c\u0435\u0436\u0434\u0443 \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u043e\u043c \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0438 \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e \u0440\u0430\u0431\u043e\u0442\u044b \u0438\u0442\u043e\u0433\u043e\u0432\u043e\u0433\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430.<\/p>\n<h3>\u041f\u0440\u0438\u043c\u0435\u0440\u044b \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f<\/h3>\n<p>\u041d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u0445 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u043c\u043e\u0434\u0435\u043b\u0438, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043a\u043e\u043c\u043f\u043b\u0435\u043a\u0442\u043d\u044b\u0445 \u043c\u0438\u043a\u0441\u0438\u043d\u043e\u0432.<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435:<\/strong> \u0422\u0430\u043a \u043a\u0430\u043a, \u043f\u043e\u0432\u0442\u043e\u0440\u044e\u0441\u044c, \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u043e\u0431\u0437\u043e\u0440\u043d\u0430\u044f, \u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044e \u0441\u0435\u0431\u0435 \u0437\u0434\u0435\u0441\u044c \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0442\u044c\u0441\u044f \u043b\u0438\u0448\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u043d\u0435 \u0441 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0441\u043b\u043e\u0436\u043d\u044b\u043c\u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u043c\u0438, \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u0443\u044e\u0449\u0438\u043c\u0438 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043f\u0430\u043a\u0435\u0442\u0430. \u0411\u043e\u043b\u044c\u0448\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432 \u0440\u0430\u0437\u043d\u043e\u0439 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0441\u0440\u0435\u0434\u0438 <a href=\"https:\/\/github.com\/vueent\/vueent\/tree\/main\/packages\/mix-models\/tests\/__mocks__\" rel=\"noopener noreferrer nofollow\">\u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u043c\u043e\u0434\u0435\u043b\u0435\u0439<\/a>. \u0415\u0441\u043b\u0438 \u043f\u0440\u043e\u0435\u043a\u0442 \u0437\u0430\u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0435\u0442 \u0430\u0443\u0434\u0438\u0442\u043e\u0440\u0438\u044e, \u0442\u043e \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430\u043c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043c\u043e\u0434\u0435\u043b\u0435\u0439, \u043c\u0435\u0442\u043e\u0434\u0430\u043c \u0438 \u0442\u0440\u044e\u043a\u0430\u043c, \u0432\u0440\u043e\u0434\u0435 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u044b\u0445 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0434\u0430\u043d\u043d\u044b\u0445, \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u0432\u044f\u0442\u0438\u0442\u044c \u0441\u0435\u0440\u0438\u044e \u043c\u0435\u043d\u0435\u0435 \u043e\u0431\u044a\u0435\u043c\u043d\u044b\u0445 \u0442\u0435\u043a\u0441\u0442\u043e\u0432, \u0437\u0430\u043f\u043e\u043b\u043d\u0438\u0432 \u0442\u0435\u043c \u0441\u0430\u043c\u044b\u043c \u043f\u0440\u043e\u0431\u0435\u043b\u044b \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438.<\/p>\n<h3>\u041f\u0440\u043e\u0441\u0442\u043e\u0439 \u043f\u0440\u0438\u043c\u0435\u0440<\/h3>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u0442\u043e\u0438\u0442 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0441\u0430\u043c\u044b\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u043c\u043e\u0434\u0435\u043b\u0438 \u0431\u0435\u0437 \u043c\u0438\u043a\u0441\u0438\u043d\u043e\u0432:<\/p>\n<pre><code class=\"typescript\">import type { Base } from '@vueent\/mix-models'; import { BaseModel } from '@vueent\/mix-models';  \/\/ \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 export interface Data {   id: number;   name: string; }  \/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044f\u044e\u0449\u0430\u044f \u0431\u0430\u0437\u043e\u0432\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 export function makeInitialData(): Data {   return { id: 0, name: '' }; }  \/\/ \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 DataModel, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u0434\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043c\u0438\u043a\u0441\u0438\u043d\u043e\u0432, \/\/ \u0442\u0430\u043a \u043a\u0430\u043a BaseModel \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0431\u043e\u0431\u0449\u0435\u043d\u043d\u044b\u043c \u043a\u043b\u0430\u0441\u0441\u043e\u043c class DataModel extends BaseModel&lt;Data> {}  \/\/ \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 \u0442\u0438\u043f \u043c\u043e\u0434\u0435\u043b\u0438 export type ModelType = Base&lt;Data>;  \/\/ \u043a\u043b\u0430\u0441\u0441 \u043c\u043e\u0434\u0435\u043b\u0438 export class Model extends DataModel {   \/**    * @param initialData - \u0441\u0442\u0430\u0440\u0442\u043e\u0432\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445    * @param react - \u0434\u0435\u043b\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u043c\u0438 \u0438\u043b\u0438 \u043d\u0435\u0442    *\/   constructor(initialData?: Data, react = true) {     \/\/ \u043f\u0435\u0440\u0432\u044b\u0439 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 - \u043a\u0430\u043a\u043e\u0435 \u043f\u043e\u043b\u0435 \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u044b\u043c \u043a\u043b\u044e\u0447\u043e\u043c \u043c\u043e\u0434\u0435\u043b\u0438,     \/\/ \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0441\u043e\u0441\u0442\u0430\u0432\u043d\u044b\u0445 \u043a\u043b\u044e\u0447\u0435\u0439 \u043d\u0435\u0442, \u043c\u043e\u0436\u043d\u043e \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0435\u0433\u043e \u043f\u0443\u0441\u0442\u044b\u043c, \u043f\u0435\u0440\u0435\u0434\u0430\u0432 \u043f\u0443\u0441\u0442\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443     super('id', initialData ?? makeInitialData(), react);   } }  \/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u043f\u043e\u0440\u043e\u0436\u0434\u0430\u044e\u0449\u0430\u044f \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b \u043c\u043e\u0434\u0435\u043b\u0438, \u043d\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0449\u0430\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 \u0442\u0438\u043f export function create(initialData?: Data, react = true): ModelType {   return new Model(initialData, react); }<\/code><\/pre>\n<p>\u0422\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u0430\u043c\u0430\u044f \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c. \u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438 \u0438\u0437 \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0441\u0442\u0430\u043d\u0443\u0442 \u043f\u043e\u043d\u044f\u0442\u043d\u044b \u043f\u043e\u0441\u043b\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0438\u044f \u0447\u0443\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u043e\u0433\u043e \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430.<\/p>\n<h3>\u041e\u0442\u043a\u0430\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f<\/h3>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043c\u0438\u043a\u0441\u0438\u043d \u043e\u0442\u043a\u0430\u0442\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f:<\/p>\n<pre><code class=\"typescript\">import type { Base, Rollback, RollbackPrivate } from '@vueent\/mix-models'; import { BaseModel, mixRollback, mix } from '@vueent\/mix-models';  \/\/ \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 export interface Data {   id: number;   name: string; }  \/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044f\u044e\u0449\u0430\u044f \u0431\u0430\u0437\u043e\u0432\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 export function makeInitialData(): Data {   return { id: 0, name: '' }; }  \/\/ \u043c\u0430\u0441\u043a\u0430, \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0449\u0430\u044f - \u043a\u0430\u043a\u0438\u0435 \u043f\u043e\u043b\u044f \u043e\u0442\u043a\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 rollback \/\/ \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043f\u043e\u043b\u0435 name \u0431\u0443\u0434\u0435\u0442 \u0441\u0431\u0440\u043e\u0448\u0435\u043d\u043e, \u0430 \u043f\u043e\u043b\u0435 id - \u043d\u0435\u0442 \/\/ \u043c\u0430\u0441\u043a\u0443 \u043c\u043e\u0436\u043d\u043e \u043d\u0435 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0432\u043e\u0432\u0441\u0435, \u0442\u043e\u0433\u0434\u0430 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0435\u043d\u043e \u0446\u0435\u043b\u0438\u043a\u043e\u043c export const rollbackMask = {   name: true } as const;  \/\/ \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 DataModel, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u0434\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043c\u0438\u043a\u0441\u0438\u043d\u043e\u0432, \/\/ \u0442\u0430\u043a \u043a\u0430\u043a BaseModel \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0431\u043e\u0431\u0449\u0435\u043d\u043d\u044b\u043c \u043a\u043b\u0430\u0441\u0441\u043e\u043c class DataModel extends BaseModel&lt;Data> {}  \/\/ \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 \u0442\u0438\u043f \u043c\u043e\u0434\u0435\u043b\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435 \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0432 \u0441\u0435\u0431\u044f \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0435 \u043f\u043e\u043b\u044f \/\/ \u0438 \u043c\u0435\u0442\u043e\u0434\u044b \u043c\u0438\u043a\u0441\u0438\u043d\u0430 \u043e\u0442\u043a\u0430\u0442\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f export type ModelType = Base&lt;Data> &amp; Rollback;  \/\/ \u0442\u0430\u043a \u043a\u0430\u043a TypeScript \u043d\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u044c \u0442\u0438\u043f \u043f\u0440\u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \/\/ \u043c\u0438\u043a\u0441\u0438\u043d\u043e\u0432, \u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u044f\u0432\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0442\u0438\u043f\u044b \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \/\/ \u043a\u043b\u0430\u0441\u0441\u0430, \u0438\u043d\u0430\u0447\u0435 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0435 \u0438 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u043c\u0438\u043a\u0441\u0438\u043d\u043e\u0432 \/\/ \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043b\u0430\u0441\u0441\u0430 export interface Model extends DataModel, RollbackPrivate&lt;Data> {}  \/\/ \u043a\u043b\u0430\u0441\u0441 \u043c\u043e\u0434\u0435\u043b\u0438 export class Model extends mix&lt;Data, typeof DataModel>(DataModel, mixRollback(rollbackMask)) {   \/**    * @param initialData - \u0441\u0442\u0430\u0440\u0442\u043e\u0432\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445    * @param react - \u0434\u0435\u043b\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u043c\u0438 \u0438\u043b\u0438 \u043d\u0435\u0442    *\/   constructor(initialData?: Data, react = true) {     \/\/ \u043f\u0435\u0440\u0432\u044b\u0439 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 - \u043a\u0430\u043a\u043e\u0435 \u043f\u043e\u043b\u0435 \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u044b\u043c \u043a\u043b\u044e\u0447\u043e\u043c \u043c\u043e\u0434\u0435\u043b\u0438,     \/\/ \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0441\u043e\u0441\u0442\u0430\u0432\u043d\u044b\u0445 \u043a\u043b\u044e\u0447\u0435\u0439 \u043d\u0435\u0442, \u043c\u043e\u0436\u043d\u043e \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0435\u0433\u043e \u043f\u0443\u0441\u0442\u044b\u043c, \u043f\u0435\u0440\u0435\u0434\u0430\u0432 \u043f\u0443\u0441\u0442\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443     super('id', initialData ?? makeInitialData(), react);   } }  \/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u043f\u043e\u0440\u043e\u0436\u0434\u0430\u044e\u0449\u0430\u044f \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b \u043c\u043e\u0434\u0435\u043b\u0438, \u043d\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0449\u0430\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 \u0442\u0438\u043f export function create(initialData?: Data, react = true): ModelType {   return new Model(initialData, react); }<\/code><\/pre>\n<p>\u041d\u0435 \u0442\u0440\u0443\u0434\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e, \u0443\u0431\u0440\u0430\u0432 \u0442\u0438\u043f\u044b, \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043a\u0443\u0434\u0430 \u043a\u0430\u043a \u0431\u043e\u043b\u0435\u0435 \u043a\u043e\u0440\u043e\u0442\u043a\u0438\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442:<\/p>\n<pre><code class=\"javascript\">import { BaseModel, mixRollback, mix } from '@vueent\/mix-models';  export function makeInitialData(): Data {   return { id: 0, name: '' }; }  export const rollbackMask = {   name: true };  export class Model extends mix(BaseModel, mixRollback(rollbackMask)) {   \/**    * @param {Record&lt;string, unknown>=} initialData - \u0441\u0442\u0430\u0440\u0442\u043e\u0432\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445    * @param {boolean=} react - \u0434\u0435\u043b\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u043c\u0438 \u0438\u043b\u0438 \u043d\u0435\u0442    *\/   constructor(initialData = undefined, react = true) {     super('id', initialData ?? makeInitialData(), react);   } }<\/code><\/pre>\n<p>\u041f\u0440\u0430\u0432\u0434\u0430, \u0432 \u0442\u0430\u043a\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u0442\u0435\u0440\u044f\u044e\u0442\u0441\u044f \u0432\u0441\u0435 \u043f\u043b\u044e\u0448\u043a\u0438 TypeScript, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u0435\u0440\u043d\u0435\u043c\u0441\u044f \u043a \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0443 \u0441 \u0442\u0438\u043f\u0430\u043c\u0438. \u0414\u0435\u043b\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e TypeScript \u043d\u0435 \u0443\u043c\u0435\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u044c \u0442\u0438\u043f \u0434\u043b\u044f \u043c\u0438\u043a\u0441\u0438\u043d\u043e\u0432, \u0435\u0441\u043b\u0438 \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0431\u043e\u0431\u0449\u0435\u043d\u043d\u044b\u043c. \u0418\u043c\u0435\u043d\u043d\u043e \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u044f\u0432\u043d\u043e \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <code>Model<\/code> \u0432\u0440\u0443\u0447\u043d\u0443\u044e. \u0422\u0430\u043a\u0436\u0435 \u0432 \u043c\u0438\u043a\u0441\u0438\u043d\u0430\u0445 \u043d\u0435\u043b\u044c\u0437\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b \u0434\u043e\u0441\u0442\u0443\u043f\u0430 (<code>private<\/code>, <code>protected<\/code>, <code>public<\/code>), \u0438, \u0447\u0442\u043e\u0431\u044b \u0432\u0441\u0435 \u043f\u043e\u043b\u044f \u0438 \u043c\u0435\u0442\u043e\u0434\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0441\u043d\u0430\u0440\u0443\u0436\u0438 \u043c\u043e\u0434\u0435\u043b\u0438, \u0431\u044b\u043b\u0438 \u0441\u043a\u0440\u044b\u0442\u044b, \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043c\u043e\u0434\u0435\u043b\u0438 \u0432 \u0432\u0438\u0434\u0435 <code>ModelType<\/code>. \u0412\u044b\u0445\u043e\u0434\u0438\u0442, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u0434\u0432\u0435 \u0446\u0435\u043f\u043e\u0447\u043a\u0438 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u043b\u044f \u0442\u0438\u043f\u043e\u0432, \u043e\u0434\u043d\u0430 \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043c\u043e\u0434\u0435\u043b\u0438, \u0430 \u0432\u0442\u043e\u0440\u0430\u044f \u2014 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0439. \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043d\u0430\u043b\u0438\u0447\u0438\u044e \u0440\u0443\u0447\u043d\u043e\u0433\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 Model, \u044f\u0437\u044b\u043a\u043e\u0432\u043e\u0439 \u0441\u0435\u0440\u0432\u0435\u0440 TypeScript \u043f\u043e\u0434\u0441\u043a\u0430\u0436\u0435\u0442 \u2014 \u043a\u0430\u043a\u0438\u0435 \u043f\u043e\u043b\u044f \u0435\u0441\u0442\u044c \u0432 \u043a\u043b\u0430\u0441\u0441\u0435, \u0435\u0441\u043b\u0438 \u043c\u044b \u0437\u0430\u0445\u043e\u0442\u0438\u043c \u0441 \u043d\u0438\u043c\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043f\u0440\u0438 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u0441\u0430\u043c\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u043c\u043e\u0434\u0435\u043b\u0438, \u0441\u043a\u0430\u0436\u0435\u043c, \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043c\u0435\u0442\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 rollback \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u044b\u0439 \u043a\u043b\u044e\u0447 \u0440\u0430\u0432\u0435\u043d \u043d\u0443\u043b\u044e:<\/p>\n<pre><code class=\"typescript\">\/\/ \u043e\u0431\u044a\u044f\u0432\u043b\u044f\u0435\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0439 \u0432 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u043e\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 interface ConditionalRollback {   conditionalRollback(): void; }  export type ModelType = Base&lt;Data> &amp; Rollback &amp; ConditionalRollback;  export interface Model extends DataModel, RollbackPrivate&lt;Data> {}  export class Model extends mix&lt;Data, typeof DataModel>(DataModel, mixRollback(rollbackMask)) {   constructor(initialData?: Data, react = true) {     super('id', initialData ?? makeInitialData(), react);   }    public conditionalRollback(): void {     \/\/ \u043f\u043e\u043b\u0435 pk \u0438\u043c\u0435\u0435\u0442 \u0442\u0438\u043f unknown \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0442\u043e\u0433\u043e \u043f\u043e\u043b\u044f, \u0447\u0442\u043e \u0431\u044b\u043b\u043e     \/\/ \u0443\u043a\u0430\u0437\u0430\u043d\u043e \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430 \u0432 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0435     if (!this.pk) this.rollback();   } }<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u0438\u0441\u0430\u0442\u044c \u0438 \u0441\u0432\u043e\u0438 \u043c\u0438\u043a\u0441\u0438\u043d\u044b, \u043d\u043e \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0438\u0435 \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u0432\u044b\u0445\u043e\u0434\u0438\u0442 \u0437\u0430 \u0440\u0430\u043c\u043a\u0438 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438.<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435:<\/strong> \u0414\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0442\u043e\u0433\u043e \u0438\u043b\u0438 \u0438\u043d\u043e\u0433\u043e \u043c\u0438\u043a\u0441\u0438\u043d\u0430 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0432\u044b\u0437\u043e\u0432\u0430 \u043c\u0435\u0442\u043e\u0434\u0430 \u043c\u043e\u0434\u0435\u043b\u0438 <code>hasMixin(mixin: Function): boolean<\/code>, \u043f\u0435\u0440\u0435\u0434\u0430\u0432 \u0435\u043c\u0443 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043c\u0438\u043a\u0441\u0438\u043d\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>mixRollback<\/code>.<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0430\u0440\u043e\u0447\u043a\u0443 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u043e\u0432 \u0438 \u043f\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043d\u0438\u043c\u0438<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"typescript\">import { create } from '@\/models\/simple';  const m1 = create(); const m2 = create({ id: 2, name: 'Jane' });  \/\/ \u0432\u0441\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u043f\u043e\u043b\u0435 data \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 \u043c\u043e\u0434\u0435\u043b\u0438 m1.data.id = 1; m1.data.name = 'John';  \/\/ \u0444\u043b\u0430\u0433 dirty \u0443 m1 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0432 true, \u0442\u0430\u043a \u043a\u0430\u043a \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0431\u044b\u043b\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u044b console.log(m1.dirty, JSON.stringify(m1.data)); \/\/ true {\"id\":1,\"name\":\"John\"} \/\/ \u0444\u043b\u0430\u0433 dirty \u0443 m2 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0432 false, \u0442\u0430\u043a \u043a\u0430\u043a \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0435 \u043c\u0435\u043d\u044f\u043b\u043e\u0441\u044c console.log(m2.dirty, JSON.stringify(m2.data)); \/\/ false {\"id\":2,\"name\":\"Jane\"}  \/\/ \u0432\u044b\u0437\u043e\u0432 rollback \u0441\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u0442 \u0444\u043b\u0430\u0433 dirty m1.rollback(); m2.rollback();  console.log(m1.dirty, JSON.stringify(m1.data)); \/\/ false {\"id\":1,\"name\":\"\"} console.log(m2.dirty, JSON.stringify(m2.data)); \/\/ false {\"id\":2,\"name\":\"Jane\"}  \/\/ \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0441\u0431\u043e\u0440\u0449\u0438\u043a \u043c\u0443\u0441\u043e\u0440\u0430 \u043c\u043e\u0433 \u043e\u0441\u0432\u043e\u0431\u043e\u0434\u0438\u0442\u044c \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430, \/\/ \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b \u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u043d\u0443\u0436\u043d\u043e \u044f\u0432\u043d\u043e \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0443\u043d\u0438\u0447\u0442\u043e\u0436\u0430\u0442\u044c, \u043a\u043e\u0433\u0434\u0430 \u043e\u043d\u0438 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u043d\u0443\u0436\u043d\u044b \/\/ \u043f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043d\u0438\u043c\u0438 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0443\u0436\u0435 \u043d\u0435\u043b\u044c\u0437\u044f m1.destroy(); m2.destroy();  \/\/ \u0444\u043b\u0430\u0433 instanceDestroyed \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0443\u0434\u0430\u043b\u0435\u043d console.log(m1.instanceDestroyed); \/\/ true console.log(m2.instanceDestroyed); \/\/ true <\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435:<\/strong> \u0411\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0444\u043b\u0430\u0433\u043e\u0432 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u0445 <a href=\"https:\/\/vueent.github.io\/vueent\/guide\/base-model.html\" rel=\"noopener noreferrer nofollow\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/a>.<\/p>\n<h3>\u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0448\u0430 \u043c\u043e\u0434\u0435\u043b\u044c \u0443\u043c\u0435\u0435\u0442 \u0434\u0435\u043b\u0430\u0442\u044c \u043e\u0442\u043a\u0430\u0442 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f, \u043d\u043e \u0431\u0435\u0437 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f, \u044d\u0442\u043e \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u0441\u043c\u044b\u0441\u043b\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u043c\u0438\u043a\u0441\u0438\u043d\u0430:<\/p>\n<pre><code class=\"typescript\">import type {   Base,   Rollback,   RollbackPrivate,   Save,   SavePrivate,   SaveOptions,   CreateFunc,   UpdateFunc,   DestroyFunc } from '@vueent\/mix-models'; import { BaseModel, mixRollback, mixSave, mix } from '@vueent\/mix-models';  \/\/ \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 export interface Data {   id: number;   name: string; }  \/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044f\u044e\u0449\u0430\u044f \u0431\u0430\u0437\u043e\u0432\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 export function makeInitialData(): Data {   return { id: 0, name: '' }; }  \/\/ \u043c\u0430\u0441\u043a\u0430, \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0449\u0430\u044f - \u043a\u0430\u043a\u0438\u0435 \u043f\u043e\u043b\u044f \u043e\u0442\u043a\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 rollback \/\/ \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043f\u043e\u043b\u0435 name \u0431\u0443\u0434\u0435\u0442 \u0441\u0431\u0440\u043e\u0448\u0435\u043d\u043e, \u0430 \u043f\u043e\u043b\u0435 id - \u043d\u0435\u0442 \/\/ \u043c\u0430\u0441\u043a\u0443 \u043c\u043e\u0436\u043d\u043e \u043d\u0435 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0432\u043e\u0432\u0441\u0435, \u0442\u043e\u0433\u0434\u0430 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0435\u043d\u043e \u0446\u0435\u043b\u0438\u043a\u043e\u043c export const rollbackMask = {   name: true } as const;  \/\/ \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 DataModel, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u0434\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043c\u0438\u043a\u0441\u0438\u043d\u043e\u0432, \/\/ \u0442\u0430\u043a \u043a\u0430\u043a BaseModel \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0431\u043e\u0431\u0449\u0435\u043d\u043d\u044b\u043c \u043a\u043b\u0430\u0441\u0441\u043e\u043c class DataModel extends BaseModel&lt;Data> {}  \/\/ \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 \u0442\u0438\u043f \u043c\u043e\u0434\u0435\u043b\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435 \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0432 \u0441\u0435\u0431\u044f \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0435 \u043f\u043e\u043b\u044f \u0438 \u043c\u0435\u0442\u043e\u0434\u044b \u043c\u0438\u043a\u0441\u0438\u043d\u043e\u0432 export type ModelType = Base&lt;Data> &amp; Rollback &amp; Save;  \/\/ \u0442\u0430\u043a \u043a\u0430\u043a TypeScript \u043d\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u044c \u0442\u0438\u043f \u043f\u0440\u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \/\/ \u043c\u0438\u043a\u0441\u0438\u043d\u043e\u0432, \u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u044f\u0432\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0442\u0438\u043f\u044b \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \/\/ \u043a\u043b\u0430\u0441\u0441\u0430, \u0438\u043d\u0430\u0447\u0435 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0435 \u0438 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u043c\u0438\u043a\u0441\u0438\u043d\u043e\u0432 \/\/ \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043b\u0430\u0441\u0441\u0430 export interface Model extends DataModel, RollbackPrivate&lt;Data>, SavePrivate&lt;Data> {}  \/\/ \u043a\u043b\u0430\u0441\u0441 \u043c\u043e\u0434\u0435\u043b\u0438 export class Model extends mix&lt;Data, typeof DataModel>(DataModel, mixRollback(rollbackMask), mixSave()) {   \/**    * @param initialData - \u0441\u0442\u0430\u0440\u0442\u043e\u0432\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445    * @param react - \u0434\u0435\u043b\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u043c\u0438 \u0438\u043b\u0438 \u043d\u0435\u0442    * @param saveOptions - \u043e\u0431\u044a\u0435\u043a\u0442 \u0441 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f, \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0438\u0437 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430    *\/   constructor(initialData?: Data, react = true, saveOptions?: SaveOptions&lt;Data>) {     \/\/ \u043f\u0435\u0440\u0432\u044b\u0439 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 - \u043a\u0430\u043a\u043e\u0435 \u043f\u043e\u043b\u0435 \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u044b\u043c \u043a\u043b\u044e\u0447\u043e\u043c \u043c\u043e\u0434\u0435\u043b\u0438,     \/\/ \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0441\u043e\u0441\u0442\u0430\u0432\u043d\u044b\u0445 \u043a\u043b\u044e\u0447\u0435\u0439 \u043d\u0435\u0442, \u043c\u043e\u0436\u043d\u043e \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0435\u0433\u043e \u043f\u0443\u0441\u0442\u044b\u043c, \u043f\u0435\u0440\u0435\u0434\u0430\u0432 \u043f\u0443\u0441\u0442\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443     super('id', initialData ?? makeInitialData(), react, saveOptions);      \/\/ \u0435\u0441\u043b\u0438 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0437\u0430\u0434\u0430\u043d \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430, \u0442\u043e \u0441\u0447\u0438\u0442\u0430\u0435\u043c,     \/\/ \u0447\u0442\u043e \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d \u043e\u0431\u044a\u0435\u043a\u0442 \u0438\u0437 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430. \u042d\u0442\u043e\u0442 \u0448\u0430\u0433 \u043d\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d,     \/\/ \u0442\u0430\u043a \u043a\u0430\u043a \u0441\u0442\u043e\u044f\u043b\u0430 \u0437\u0430\u0434\u0430\u0447\u0430 \u0434\u0430\u0442\u044c \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u0441\u0432\u043e\u0431\u043e\u0434\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0443     if (this.pk) this._flags.new = false;   } }  \/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u043f\u043e\u0440\u043e\u0436\u0434\u0430\u044e\u0449\u0430\u044f \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b \u043c\u043e\u0434\u0435\u043b\u0438, \u043d\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0449\u0430\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 \u0442\u0438\u043f export function create(   initialData?: Data,   react = true,   params: {     create?: CreateFunc&lt;Data>;     update?: UpdateFunc&lt;Data>;     destroy?: DestroyFunc&lt;Data>;   } = {} ): ModelType {   const saveOptions: SaveOptions&lt;Data> = { mixinType: 'save', ...params };    return new Model(initialData, react, saveOptions); }<\/code><\/pre>\n<p>\u041a\u043b\u0430\u0441\u0441 \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u043c\u0435\u0442\u043e\u0434 <code>save<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435. \u041a\u0430\u043a \u0432\u044b, \u043d\u0430\u0432\u0435\u0440\u043d\u043e\u0435, \u0437\u0430\u043c\u0435\u0442\u0438\u043b\u0438, \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0449\u0438\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f, \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0438\u0437 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 (\u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 <code>saveOptions<\/code>) \u043d\u0435 \u043f\u0440\u043e\u043f\u0438\u0441\u0430\u043d\u044b \u0432 \u0441\u0430\u043c\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438. \u042d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u043d\u043e \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u0432\u044f\u0437\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441 \u043c\u043e\u0434\u0435\u043b\u0438  \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u043c, \u0431\u0443\u0434\u044c \u043e\u043d\u043e \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u043c, \u043b\u0438\u0431\u043e \u0443\u0434\u0430\u043b\u0435\u043d\u043d\u044b\u043c. \u041f\u043e \u0437\u0430\u0434\u0443\u043c\u043a\u0435, \u044d\u0442\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0435\u0439 \u0438\u0437 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 <code>Store<\/code>, \u043d\u043e \u043e \u043d\u0435\u043c \u0440\u0435\u0447\u044c \u043f\u043e\u0439\u0434\u0435\u0442 \u043d\u0438\u0436\u0435, \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u043c \u0440\u0430\u0437\u0434\u0435\u043b\u0435, \u0430 \u043f\u043e\u043a\u0430 \u043f\u0435\u0440\u0435\u0434\u0430\u0434\u0438\u043c \u044d\u0442\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430:<\/p>\n<details class=\"spoiler\">\n<summary>\u0412\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u043c<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"typescript\">import type { Data } from '@\/models\/simple'; import { create } from '@\/models\/simple';  let counter = 0; \/\/ \u0441\u0447\u0435\u0442\u0447\u0438\u043a \u0434\u043b\u044f \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u044b\u0445 \u043a\u043b\u044e\u0447\u0435\u0439 const storage = new Map&lt;number, Data>(); \/\/ \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435, \u0438\u043c\u0438\u0442\u0430\u0446\u0438\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u0430  const saveOptions = {   \/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0435\u0433\u043e \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u044b\u043c \u043a\u043b\u044e\u0447\u043e\u043c   create: (data: Data): Data => {     const id = ++counter; \/\/ \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u044b\u0439 \u043a\u043b\u044e\u0447     const record = { ...data, id }; \/\/ \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043a\u043e\u043f\u0438\u044e \u043e\u0431\u044a\u0435\u043a\u0442\u0430      storage.set(id as number, record); \/\/ \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435      return record;   },   \/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435   update: (id: unknown, data: Data): Data => {     if (!storage.has(id as number)) throw new Error('resource not found');      const updated = { ...data }; \/\/ \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043a\u043e\u043f\u0438\u044e \u043e\u0431\u044a\u0435\u043a\u0442\u0430      storage.set(id as number, updated);      return updated;   },   \/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0443\u0434\u0430\u043b\u044f\u0435\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 \u0438\u0437 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430   destroy: (id: unknown): void => {     if (!storage.has(id as number)) throw new Error('resource not found');      storage.delete(id as number);   } };  \/\/ \u0437\u0430\u0434\u0430\u0435\u043c \u0441\u0442\u0430\u0440\u0442\u043e\u0432\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 storage.set(1, { id: 1, name: 'John' }); ++counter;  \/\/ \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0434\u043b\u044f m1 \u0431\u0435\u0440\u0435\u043c \u0438\u0437 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 const m1 = create({ ...storage.get(1)! }, true, saveOptions); const m2 = create(undefined, true, saveOptions);  console.log(m1.new, m1.pk, JSON.stringify(m1.data)); \/\/ false 1 {\"id\":1,\"name\":\"John\"} console.log(m2.new, m2.pk, JSON.stringify(m2.data)); \/\/ true 0 {\"id\":0,\"name\":\"\"}  m2.data.name = 'Jane';  console.log(m2.dirty); \/\/ true  \/\/ \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 (\u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435) \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0444\u043b\u0430\u0433\u0438 \/\/ saving \u0438 creating await m2.save();  \/\/ \u0444\u043b\u0430\u0433 dirty \u0441\u0431\u0440\u043e\u0441\u0438\u043b\u0441\u044f \u043f\u043e\u0441\u043b\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f console.log(m2.dirty); \/\/ false \/\/ \u0444\u043b\u0430\u0433 new \u0442\u0430\u043a\u0436\u0435 \u0441\u0431\u0440\u043e\u0448\u0435\u043d, \u0430 \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u044b\u0439 \u043a\u043b\u044e\u0447 \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 console.log(m2.new, m2.pk, JSON.stringify(m2.data)); \/\/ false 2 {\"id\":2,\"name\":\"Jane\"}  m1.data.name = 'John Doe';  console.log(m1.dirty); \/\/ true  \/\/ \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0430 \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0444\u043b\u0430\u0433\u0438 \/\/ saving \u0438 updating await m1.save();  \/\/ \u0444\u043b\u0430\u0433 dirty \u0441\u0431\u0440\u043e\u0448\u0435\u043d \u043f\u043e\u0441\u043b\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f console.log(m1.dirty); \/\/ false \/\/ \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u044b\u0439 \u043a\u043b\u044e\u0447 \u043d\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u0441\u044f, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u0431\u044a\u0435\u043a\u0442 \u0431\u044b\u043b \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d, \u0430 \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u043d console.log(m1.pk); \/\/ 1  \/\/ \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0444\u043b\u0430\u0433 deleted \u0432 true m2.delete();  \/\/ \u043e\u0431\u044a\u0435\u043a\u0442 \u043f\u043e\u043c\u0435\u0447\u0435\u043d \u043a\u0430\u043a \u0443\u0434\u0430\u043b\u0435\u043d\u043d\u044b\u0439 console.log(m2.deleted); \/\/ true \/\/ \u043d\u043e \u0442\u0430\u043a \u043a\u0430\u043a \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e, \u0430 \u043d\u0435 \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435, \/\/ \u0442\u043e \u0444\u043b\u0430\u0433 destroyed \u043d\u0435 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d console.log(m2.destroyed); \/\/ false  \/\/ \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043f\u0440\u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0438 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0444\u043b\u0430\u0433\u0438 \/\/ saving, destroying await m2.save();  \/\/ \u043e\u0431\u044a\u0435\u043a\u0442 \u043f\u043e\u043c\u0435\u0447\u0435\u043d, \u043a\u0430\u043a \u0443\u0434\u0430\u043b\u0435\u043d\u043d\u044b\u0439 \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435, \u0438\u043c \u0432\u0441\u0435 \u0435\u0449\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f, \/\/ \u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0443\u0436\u0435 \u043d\u0435\u043b\u044c\u0437\u044f console.log(m2.destroyed); \/\/ true \/\/ \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0432\u0441\u0435 \u0435\u0449\u0435 \u043d\u0435 \u0443\u0434\u0430\u043b\u0435\u043d console.log(m2.instanceDestroyed); \/\/ false  \/\/ \u043e\u0447\u0438\u0449\u0430\u0435\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u043c \u0441\u0431\u043e\u0440\u0449\u0438\u043a\u0443 \u043c\u0443\u0441\u043e\u0440\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0441\u0432\u043e\u044e \u0440\u0430\u0431\u043e\u0442\u0443 m1.destroy(); m2.destroy();  \/\/ \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b \u043e\u0447\u0438\u0449\u0435\u043d\u044b, \u0441\u0431\u043e\u0440\u0449\u0438\u043a \u043c\u0443\u0441\u043e\u0440\u0430 \u0434\u043e\u0432\u043e\u043b\u0435\u043d \u043d\u0430\u043c\u0438 console.log(m1.instanceDestroyed); \/\/ true console.log(m2.instanceDestroyed); \/\/ true <\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0412 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0432\u044b\u0448\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0435, \u043d\u043e \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0438 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u043c\u043c\u0438. \u0415\u0441\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u044b \u0438\u0437 \u043f\u0430\u043a\u0435\u0442\u0430 <code>@vueent\/core<\/code>, \u0442\u043e \u043e\u0441\u0432\u043e\u0431\u043e\u0436\u0434\u0435\u043d\u0438\u0435 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u043e\u0432 \u043b\u0443\u0447\u0448\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 <code>destroy<\/code>, \u043b\u0438\u0431\u043e \u0432 \u0445\u0443\u043a\u0435 <code>onUnmounted<\/code> Vue. \u0422\u0430\u043a\u0436\u0435 \u0443 \u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u0435\u0441\u0442\u044c \u0445\u0443\u043a\u0438 <code>beforeSave<\/code>, <code>afterSave<\/code>, <code>beforeCreate<\/code>, <code>afterCreate<\/code>, \u043d\u043e \u0438\u0445 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0438\u0435 \u0432\u044b\u0445\u043e\u0434\u0438\u0442 \u0437\u0430 \u0440\u0430\u043c\u043a\u0438 \u0434\u0430\u043d\u043d\u043e\u0439 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438, \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0445\u0443\u043a\u0430\u043c\u0438 \u043c\u043e\u0436\u043d\u043e \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438.<\/p>\n<h3>\u0412\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f<\/h3>\n<p>\u0427\u0442\u043e \u0436, \u043f\u043e\u0440\u0430 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442\u044c \u043a \u0441\u0430\u043c\u043e\u043c\u0443 \u0432\u043a\u0443\u0441\u043d\u043e\u043c\u0443 &#8212; \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438:<\/p>\n<pre><code class=\"typescript\">import type {   Base,   Rollback,   RollbackPrivate,   Save,   SavePrivate,   SaveOptions,   Validate,   ValidatePrivate,   ValidationBase,   ValidateOptions,   Options,   PatternAssert,   CreateFunc,   UpdateFunc,   DestroyFunc } from '@vueent\/mix-models'; import { BaseModel, mixRollback, mixSave, mixValidate, mix } from '@vueent\/mix-models';  \/\/ \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 export interface Data {   id: number;   name: string; }  \/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044f\u044e\u0449\u0430\u044f \u0431\u0430\u0437\u043e\u0432\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 export function makeInitialData(): Data {   return { id: 0, name: '' }; }  \/\/ \u043c\u0430\u0441\u043a\u0430, \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0449\u0430\u044f - \u043a\u0430\u043a\u0438\u0435 \u043f\u043e\u043b\u044f \u043e\u0442\u043a\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 rollback \/\/ \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043f\u043e\u043b\u0435 name \u0431\u0443\u0434\u0435\u0442 \u0441\u0431\u0440\u043e\u0448\u0435\u043d\u043e, \u0430 \u043f\u043e\u043b\u0435 id - \u043d\u0435\u0442 \/\/ \u043c\u0430\u0441\u043a\u0443 \u043c\u043e\u0436\u043d\u043e \u043d\u0435 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0432\u043e\u0432\u0441\u0435, \u0442\u043e\u0433\u0434\u0430 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0435\u043d\u043e \u0446\u0435\u043b\u0438\u043a\u043e\u043c export const rollbackMask = {   name: true } as const;  \/\/ \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438, \u043e\u043d\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c true \u0438\u043b\u0438 \u0441\u0442\u0440\u043e\u043a\u0443 \u0442\u0435\u043a\u0441\u0442\u043e\u043c \u043e\u0448\u0438\u0431\u043a\u0438 export const validations = {   \/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u0438\u043c\u044f \u043d\u0435 \u043f\u0443\u0441\u0442\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430, \u0438 \u0447\u0442\u043e \u0434\u043b\u0438\u043d\u0430 \u043d\u0435 \u043f\u0440\u0435\u0432\u044b\u0448\u0430\u0435\u0442 255 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432   name: (v: any) => {     if (!(v as string).length) return 'Enter name';     else if ((v as string).length > 255) return 'Unexpected name length';     else return true;   } } as const;  \/\/ \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 DataModel, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u0434\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043c\u0438\u043a\u0441\u0438\u043d\u043e\u0432, \/\/ \u0442\u0430\u043a \u043a\u0430\u043a BaseModel \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0431\u043e\u0431\u0449\u0435\u043d\u043d\u044b\u043c \u043a\u043b\u0430\u0441\u0441\u043e\u043c class DataModel extends BaseModel&lt;Data> {}  \/\/ \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0442\u0438\u043f \u0434\u043b\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0435\u0433\u043e \u0437\u0430 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043f\u0440\u0430\u0432\u0438\u043b \u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 export type Validations = PatternAssert&lt;typeof validations, Data>;  \/\/ \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 \u0442\u0438\u043f \u043c\u043e\u0434\u0435\u043b\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435 \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0432 \u0441\u0435\u0431\u044f \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0435 \u043f\u043e\u043b\u044f \u0438 \u043c\u0435\u0442\u043e\u0434\u044b \u043c\u0438\u043a\u0441\u0438\u043d\u043e\u0432 export type ModelType = Base&lt;Data> &amp; Rollback &amp; Save &amp; Validate&lt;Validations>;  \/\/ \u0442\u0430\u043a \u043a\u0430\u043a TypeScript \u043d\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u044c \u0442\u0438\u043f \u043f\u0440\u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \/\/ \u043c\u0438\u043a\u0441\u0438\u043d\u043e\u0432, \u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u044f\u0432\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0442\u0438\u043f\u044b \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \/\/ \u043a\u043b\u0430\u0441\u0441\u0430, \u0438\u043d\u0430\u0447\u0435 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0435 \u0438 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u043c\u0438\u043a\u0441\u0438\u043d\u043e\u0432 \/\/ \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043b\u0430\u0441\u0441\u0430 export interface Model extends DataModel, RollbackPrivate&lt;Data>, SavePrivate&lt;Data>, ValidatePrivate&lt;Validations> {}  \/\/ \u043a\u043b\u0430\u0441\u0441 \u043c\u043e\u0434\u0435\u043b\u0438 export class Model extends mix&lt;Data, typeof DataModel>(   DataModel,   mixRollback(rollbackMask),   mixSave(),   mixValidate(validations) ) {   \/**    * @param initialData - \u0441\u0442\u0430\u0440\u0442\u043e\u0432\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445    * @param react - \u0434\u0435\u043b\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u043c\u0438 \u0438\u043b\u0438 \u043d\u0435\u0442    * @param options - \u043d\u0430\u0431\u043e\u0440 \u043e\u043f\u0446\u0438\u0439 \u044d\u043a\u0437\u043c\u0435\u043f\u043b\u044f\u0440\u0430    *\/   constructor(initialData?: Data, react = true, ...options: Options[]) {     \/\/ \u043f\u0435\u0440\u0432\u044b\u0439 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 - \u043a\u0430\u043a\u043e\u0435 \u043f\u043e\u043b\u0435 \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u044b\u043c \u043a\u043b\u044e\u0447\u043e\u043c \u043c\u043e\u0434\u0435\u043b\u0438,     \/\/ \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0441\u043e\u0441\u0442\u0430\u0432\u043d\u044b\u0445 \u043a\u043b\u044e\u0447\u0435\u0439 \u043d\u0435\u0442, \u043c\u043e\u0436\u043d\u043e \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0435\u0433\u043e \u043f\u0443\u0441\u0442\u044b\u043c, \u043f\u0435\u0440\u0435\u0434\u0430\u0432 \u043f\u0443\u0441\u0442\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443     super('id', initialData ?? makeInitialData(), react, ...options);      \/\/ \u0435\u0441\u043b\u0438 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0437\u0430\u0434\u0430\u043d \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430, \u0442\u043e \u0441\u0447\u0438\u0442\u0430\u0435\u043c,     \/\/ \u0447\u0442\u043e \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d \u043e\u0431\u044a\u0435\u043a\u0442 \u0438\u0437 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430. \u042d\u0442\u043e\u0442 \u0448\u0430\u0433 \u043d\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d,     \/\/ \u0442\u0430\u043a \u043a\u0430\u043a \u0441\u0442\u043e\u044f\u043b\u0430 \u0437\u0430\u0434\u0430\u0447\u0430 \u0434\u0430\u0442\u044c \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u0441\u0432\u043e\u0431\u043e\u0434\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0443     if (this.pk) this._flags.new = false;   } }  \/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u043f\u043e\u0440\u043e\u0436\u0434\u0430\u044e\u0449\u0430\u044f \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b \u043c\u043e\u0434\u0435\u043b\u0438, \u043d\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0449\u0430\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 \u0442\u0438\u043f \/\/ \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043c\u043e\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u043c, \u043d\u043e \u0438 \u0434\u0440\u0443\u0433\u043e\u0439 \/\/ \u043d\u0430\u0431\u043e\u0440 \u043f\u0440\u0430\u0432\u0438\u043b \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439, \u043f\u0440\u0430\u0432\u0434\u0430, \u0432\u0441\u0435 \u0440\u0430\u0432\u043d\u043e \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \/\/ \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u043e\u0434\u0435\u043b\u0438 export function create(   initialData?: Data,   react = true,   params: {     validations?: ValidationBase;     create?: CreateFunc&lt;Data>;     update?: UpdateFunc&lt;Data>;     destroy?: DestroyFunc&lt;Data>;   } = {} ): ModelType {   const options: Array&lt;ValidateOptions | SaveOptions&lt;Data>> = [];    if (params.validations) options.push({ mixinType: 'validate', validations: params.validations });   if (params.create || params.update || params.destroy)     options.push({       mixinType: 'save',       create: params.create,       update: params.update,       destroy: params.destroy     });    return new Model(initialData, react, ...options); }<\/code><\/pre>\n<p>\u0414\u043b\u044f \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u043a \u043e\u0431\u044a\u0435\u043a\u0442\u0443 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u0435\u0441\u0442\u044c \u043f\u043e\u043b\u0435 \u0441 \u043a\u043e\u0440\u043e\u0442\u043a\u0438\u043c \u0438\u043c\u0435\u043d\u0435\u043c <code>v<\/code>, \u0442\u0438\u043f \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u044b\u0432\u0435\u0434\u0435\u043d\u043d\u043e\u043c\u0443 \u0442\u0438\u043f\u0443 <code>Validations<\/code> \u043d\u0430\u0448\u0435\u0439 \u043c\u043e\u0434\u0435\u043b\u0438. \u0412 \u0432\u0438\u0434\u0443 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0435\u0439 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0438\u043b\u0438 \u043c\u0430\u0441\u0441\u0438\u0432\u0430 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u043e\u0435 \u043f\u043e\u043b\u0435 <code>c<\/code> (<code>children<\/code>), \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440: <code>m1.v.c.name<\/code>. \u0417\u0434\u0435\u0441\u044c <code>name<\/code> \u2014 \u044d\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442, \u0441 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u043f\u043e\u043b\u0435\u0439 \u0438 \u043c\u0435\u0442\u043e\u0434\u043e\u0432, \u0432 \u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438: <code>invalid<\/code>, <code>dirty<\/code>, <code>message<\/code>, <code>dirtyMessage<\/code>, <code>touch()<\/code>, <code>anyChildDirty<\/code>, <code>anyChildInvalid<\/code> \u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u0434\u0440\u0443\u0433\u0438\u043c\u0438. \u0412\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f \u043c\u0430\u0441\u0441\u0438\u0432\u0430 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0430 \u043d\u0438\u0436\u0435 \u0432 \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435.<\/p>\n<details class=\"spoiler\">\n<summary>\u041c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u043f\u0440\u0430\u0432\u0438\u043b<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"typescript\">import { create } from '@\/models\/simple';  const m1 = create();  \/\/ \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u044b, \u043d\u043e \u0435\u0449\u0435 \u043d\u0435 \u0431\u044b\u043b\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u044b console.log(m1.v.dirty, m1.v.invalid, m1.v.anyChildInvalid); \/\/ false true true \/\/ \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0443\u0441\u0442\u044b\u043c console.log(m1.v.c.name.dirtyMessage); \/\/ \"\" \/\/ \u0430 \u0432\u043e\u0442 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u043b\u0435 message \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u043e\u0448\u0438\u0431\u043a\u0443, \/\/ \u0435\u0441\u043b\u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u043e \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u043d\u0430\u0440\u0443\u0448\u0435\u043d\u043e console.log(m1.v.c.name.message); \/\/ Enter a name  m1.data.name = 'Jane';  \/\/ \u0442\u0435\u043f\u0435\u0440\u044c \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u0443\u0441\u043f\u0435\u0448\u043d\u043e, \u043d\u043e \u0444\u043b\u0430\u0433 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 dirty \u0432\u0441\u0435 \u0435\u0449\u0435 false, \/\/ \u0442\u0430\u043a \u043a\u0430\u043a \u0435\u0433\u043e \u043d\u0443\u0436\u043d\u043e \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0441\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043c\u0435\u0442\u043e\u0434\u0430 touch() console.log(m1.v.dirty, m1.v.invalid); \/\/ false false  \/\/ \u0444\u0438\u043a\u0441\u0438\u0440\u0443\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044f name m1.v.c.name.touch();  console.log(m1.v.dirty, m1.v.invalid); \/\/ true false  \/\/ \u0432\u043d\u043e\u0432\u044c \u0434\u0435\u043b\u0430\u0435\u043c \u043f\u043e\u043b\u0435 \u043f\u0443\u0441\u0442\u044b\u043c, \u043d\u0430\u0440\u0443\u0448\u0430\u044f \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 m1.data.name = '';  \/\/ \u0442\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u0441\u044f, \u0442\u0430\u043a \u043a\u0430\u043a \u0444\u043b\u0430\u0433 dirty \u0441\u0431\u0440\u043e\u0448\u0435\u043d \/\/ \u044d\u0442\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u0434\u043b\u044f \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0439 (\u0438\u043b\u0438 \u0436\u0438\u0432\u043e\u0439) \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 console.log(m1.v.c.name.dirtyMessage); \/\/ Enter a name  \/\/ \u0441\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u043c \u0444\u043b\u0430\u0433\u0438 dirty m1.v.reset();  \/\/ \u0444\u043b\u0430\u0433\u0438 \u0441\u0431\u0440\u043e\u0448\u0435\u043d\u044b console.log(m1.v.dirty, m1.v.anyChildDirty); \/\/ false false \/\/ \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0435 \u0442\u0430\u043a\u0436\u0435 \u043d\u0435 \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u0441\u044f console.log(m1.v.c.name.dirtyMessage); \/\/ \"\" \/\/ \u0445\u043e\u0442\u044f \u0432\u0441\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u0435\u043d\u044b console.log(m1.v.c.name.message); \/\/ Enter a name \/\/ \u043d\u0430 \u043b\u044e\u0431\u043e\u043c \u0443\u0440\u043e\u0432\u043d\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c - \u0435\u0441\u0442\u044c \u043b\u0438 \u0432 \u043f\u043e\u0434\u0434\u0435\u0440\u0435\u0432\u0435 \u043d\u0430\u0440\u0443\u0448\u0435\u043d\u0438\u044f \u043f\u0440\u0430\u0432\u0438\u043b console.log(m1.v.anyChildInvalid); \/\/ true  m1.data.name = (() => new Array(256).fill('a').join(''))(); \/\/ \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0444\u043b\u0430\u0433\u0438 dirty \u0432\u043e \u0432\u0441\u0435\u043c \u0434\u0435\u0440\u0435\u0432\u0435 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 m1.v.touch();  \/\/ \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u043e console.log(m1.v.c.name.dirtyMessage); \/\/ Unexpected name length  \/\/ \u043e\u0447\u0438\u0449\u0430\u0435\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043c\u043e\u0434\u0435\u043b\u0438 m1.destroy(); <\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041e\u0434\u043d\u0438\u043c \u0438\u0437 \u0432\u0430\u0436\u043d\u0435\u0439\u0448\u0438\u0445, \u043d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u043a\u0430\u0447\u0435\u0441\u0442\u0432 <code>VueEnt<\/code> \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u043b\u043d\u0430\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 TypeScript, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0435\u0449\u0435 \u0434\u043e \u0441\u0431\u043e\u0440\u043a\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0432 IDE \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/bd1\/286\/a97\/bd1286a9776aa3b2ea4fc29b9d93a7ed.png\" alt=\"\u0421\u043f\u0438\u0441\u043e\u043a \u0441\u0432\u043e\u0439\u0441\u0442\u0432, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443 \u0434\u0430\u043d\u043d\u044b\u0445\" title=\"\u0421\u043f\u0438\u0441\u043e\u043a \u0441\u0432\u043e\u0439\u0441\u0442\u0432, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443 \u0434\u0430\u043d\u043d\u044b\u0445\" width=\"730\" height=\"68\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/bd1\/286\/a97\/bd1286a9776aa3b2ea4fc29b9d93a7ed.png\"\/><figcaption>\u0421\u043f\u0438\u0441\u043e\u043a \u0441\u0432\u043e\u0439\u0441\u0442\u0432, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443 \u0434\u0430\u043d\u043d\u044b\u0445<\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/57b\/af4\/e22\/57baf4e22db624e8baf7ba8753a9aab4.png\" alt=\"\u0421\u043f\u0438\u0441\u043e\u043a \u0441\u0432\u043e\u0439\u0441\u0442\u0432 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438\" title=\"\u0421\u043f\u0438\u0441\u043e\u043a \u0441\u0432\u043e\u0439\u0441\u0442\u0432 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438\" width=\"838\" height=\"228\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/57b\/af4\/e22\/57baf4e22db624e8baf7ba8753a9aab4.png\"\/><figcaption>\u0421\u043f\u0438\u0441\u043e\u043a \u0441\u0432\u043e\u0439\u0441\u0442\u0432 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438<\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/7bd\/3d0\/3f0\/7bd3d03f023fba5bda38605561976ffa.png\" alt=\"\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043f\u043e\u043f\u044b\u0442\u043a\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u043d\u0435\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u043c \u043f\u043e\u043b\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438\" title=\"\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043f\u043e\u043f\u044b\u0442\u043a\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u043d\u0435\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u043c \u043f\u043e\u043b\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438\" width=\"613\" height=\"104\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/7bd\/3d0\/3f0\/7bd3d03f023fba5bda38605561976ffa.png\"\/><figcaption>\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043f\u043e\u043f\u044b\u0442\u043a\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u043d\u0435\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u043c \u043f\u043e\u043b\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438<\/figcaption><\/figure>\n<h3>\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u043f\u043e\u043b\u0435<\/h3>\n<p>\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u043c \u043c\u043e\u0434\u0435\u043b\u044c \u0447\u0438\u0441\u043b\u043e\u0432\u044b\u043c \u043f\u043e\u043b\u0435\u043c <code>age<\/code>:<\/p>\n<pre><code class=\"typescript\">import type {   Base,   Rollback,   RollbackPrivate,   Save,   SavePrivate,   SaveOptions,   Validate,   ValidatePrivate,   ValidationBase,   ValidateOptions,   Options,   PatternAssert,   CreateFunc,   UpdateFunc,   DestroyFunc } from '@vueent\/mix-models'; import { BaseModel, mixRollback, mixSave, mixValidate, mix } from '@vueent\/mix-models';  \/\/ \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 export interface Data {   id: number;   name: string;   age: string; }  \/\/ \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0432\u043e\u0437\u0440\u0430\u0441\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 \u0432\u0438\u0434\u0435 \u0447\u0438\u0441\u043b\u0430, \u043d\u043e \u0434\u043b\u044f \u0444\u043e\u0440\u043c\u044b, \u043f\u043e\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043d\u0443\u0436\u043d\u043e \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0442\u044c \/\/ \u0447\u0430\u0441\u0442\u043e \u0443\u0434\u043e\u0431\u043d\u0435\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f export interface EncodedData {   id: number;   name: string;   age: number; }  \/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044f\u044e\u0449\u0430\u044f \u0431\u0430\u0437\u043e\u0432\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 export function makeInitialData(): Data {   return { id: 0, name: '', age: '' }; }  \/\/ \u043c\u0430\u0441\u043a\u0430, \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0449\u0430\u044f - \u043a\u0430\u043a\u0438\u0435 \u043f\u043e\u043b\u044f \u043e\u0442\u043a\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 rollback \/\/ \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043f\u043e\u043b\u0435 name \u0431\u0443\u0434\u0435\u0442 \u0441\u0431\u0440\u043e\u0448\u0435\u043d\u043e, \u0430 \u043f\u043e\u043b\u0435 id - \u043d\u0435\u0442 \/\/ \u043c\u0430\u0441\u043a\u0443 \u043c\u043e\u0436\u043d\u043e \u043d\u0435 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0432\u043e\u0432\u0441\u0435, \u0442\u043e\u0433\u0434\u0430 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0435\u043d\u043e \u0446\u0435\u043b\u0438\u043a\u043e\u043c export const rollbackMask = {   name: true,   age: true } as const;  \/\/ \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438, \u043e\u043d\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c true \u0438\u043b\u0438 \u0441\u0442\u0440\u043e\u043a\u0443 \u0442\u0435\u043a\u0441\u0442\u043e\u043c \u043e\u0448\u0438\u0431\u043a\u0438 export const validations = {   \/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u0438\u043c\u044f \u043d\u0435 \u043f\u0443\u0441\u0442\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430, \u0438 \u0447\u0442\u043e \u0434\u043b\u0438\u043d\u0430 \u043d\u0435 \u043f\u0440\u0435\u0432\u044b\u0448\u0430\u0435\u0442 255 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432   name: (v: any) => {     if (!(v as string).length) return 'Enter name';     else if ((v as string).length > 255) return 'Unexpected name length';     else return true;   },   \/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u0441\u0442\u0440\u043e\u043a\u0430 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0446\u0435\u043b\u043e\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u043e\u0439 \u0438 \u043d\u0435 \u043f\u0440\u0435\u0432\u044b\u0448\u0430\u0435\u0442 \u0442\u0440\u0435\u0445 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432   age: (v: any) => {     if (!(v as string).length) return 'Enter an age';     else if ((v as string).length > 3) return 'Unexpected age length';     else if (!\/^\\d+$\/.test(v)) return 'Age should be an integer';     else return true;   } } as const;  \/\/ \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 DataModel, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u0434\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043c\u0438\u043a\u0441\u0438\u043d\u043e\u0432, \/\/ \u0442\u0430\u043a \u043a\u0430\u043a BaseModel \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0431\u043e\u0431\u0449\u0435\u043d\u043d\u044b\u043c \u043a\u043b\u0430\u0441\u0441\u043e\u043c class DataModel extends BaseModel&lt;Data> {}  \/\/ \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0442\u0438\u043f \u0434\u043b\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0435\u0433\u043e \u0437\u0430 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043f\u0440\u0430\u0432\u0438\u043b \u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 export type Validations = PatternAssert&lt;typeof validations, Data>;  \/\/ \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 \u0442\u0438\u043f \u043c\u043e\u0434\u0435\u043b\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435 \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0432 \u0441\u0435\u0431\u044f \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0435 \u043f\u043e\u043b\u044f \u0438 \u043c\u0435\u0442\u043e\u0434\u044b \u043c\u0438\u043a\u0441\u0438\u043d\u043e\u0432 export type ModelType = Base&lt;Data> &amp; Rollback &amp; Save &amp; Validate&lt;Validations>;  \/\/ \u0442\u0430\u043a \u043a\u0430\u043a TypeScript \u043d\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u044c \u0442\u0438\u043f \u043f\u0440\u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \/\/ \u043c\u0438\u043a\u0441\u0438\u043d\u043e\u0432, \u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u044f\u0432\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0442\u0438\u043f\u044b \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \/\/ \u043a\u043b\u0430\u0441\u0441\u0430, \u0438\u043d\u0430\u0447\u0435 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0435 \u0438 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u043c\u0438\u043a\u0441\u0438\u043d\u043e\u0432 \/\/ \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043b\u0430\u0441\u0441\u0430 export interface Model extends DataModel, RollbackPrivate&lt;Data>, SavePrivate&lt;Data>, ValidatePrivate&lt;Validations> {}  \/\/ \u043a\u043b\u0430\u0441\u0441 \u043c\u043e\u0434\u0435\u043b\u0438 export class Model extends mix&lt;Data, typeof DataModel>(   DataModel,   mixRollback(rollbackMask),   mixSave(),   mixValidate(validations) ) {   \/**    * @param initialData - \u0441\u0442\u0430\u0440\u0442\u043e\u0432\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445    * @param react - \u0434\u0435\u043b\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u043c\u0438 \u0438\u043b\u0438 \u043d\u0435\u0442    * @param options - \u043d\u0430\u0431\u043e\u0440 \u043e\u043f\u0446\u0438\u0439 \u044d\u043a\u0437\u043c\u0435\u043f\u043b\u044f\u0440\u0430    *\/   constructor(initialData?: Data, react = true, ...options: Options[]) {     \/\/ \u043f\u0435\u0440\u0432\u044b\u0439 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 - \u043a\u0430\u043a\u043e\u0435 \u043f\u043e\u043b\u0435 \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u044b\u043c \u043a\u043b\u044e\u0447\u043e\u043c \u043c\u043e\u0434\u0435\u043b\u0438,     \/\/ \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0441\u043e\u0441\u0442\u0430\u0432\u043d\u044b\u0445 \u043a\u043b\u044e\u0447\u0435\u0439 \u043d\u0435\u0442, \u043c\u043e\u0436\u043d\u043e \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0435\u0433\u043e \u043f\u0443\u0441\u0442\u044b\u043c, \u043f\u0435\u0440\u0435\u0434\u0430\u0432 \u043f\u0443\u0441\u0442\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443     super('id', initialData ?? makeInitialData(), react, ...options);      \/\/ \u0435\u0441\u043b\u0438 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0437\u0430\u0434\u0430\u043d \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430, \u0442\u043e \u0441\u0447\u0438\u0442\u0430\u0435\u043c,     \/\/ \u0447\u0442\u043e \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d \u043e\u0431\u044a\u0435\u043a\u0442 \u0438\u0437 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430. \u042d\u0442\u043e\u0442 \u0448\u0430\u0433 \u043d\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d,     \/\/ \u0442\u0430\u043a \u043a\u0430\u043a \u0441\u0442\u043e\u044f\u043b\u0430 \u0437\u0430\u0434\u0430\u0447\u0430 \u0434\u0430\u0442\u044c \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u0441\u0432\u043e\u0431\u043e\u0434\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0443     if (this.pk) this._flags.new = false;   } }  \/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u043f\u043e\u0440\u043e\u0436\u0434\u0430\u044e\u0449\u0430\u044f \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b \u043c\u043e\u0434\u0435\u043b\u0438, \u043d\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0449\u0430\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 \u0442\u0438\u043f \/\/ \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043c\u043e\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u043c, \u043d\u043e \u0438 \u0434\u0440\u0443\u0433\u043e\u0439 \/\/ \u043d\u0430\u0431\u043e\u0440 \u043f\u0440\u0430\u0432\u0438\u043b \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439, \u043f\u0440\u0430\u0432\u0434\u0430, \u0432\u0441\u0435 \u0440\u0430\u0432\u043d\u043e \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \/\/ \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u043e\u0434\u0435\u043b\u0438 export function create(   initialData?: Data,   react = true,   params: {     validations?: ValidationBase;     create?: CreateFunc&lt;Data>;     update?: UpdateFunc&lt;Data>;     destroy?: DestroyFunc&lt;Data>;   } = {} ): ModelType {   const options: Array&lt;ValidateOptions | SaveOptions&lt;Data>> = [];    if (params.validations) options.push({ mixinType: 'validate', validations: params.validations });   if (params.create || params.update || params.destroy)     options.push({       mixinType: 'save',       create: params.create,       update: params.update,       destroy: params.destroy     });    return new Model(initialData, react, ...options); }<\/code><\/pre>\n<p>\u041d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0447\u0438\u0441\u043b\u043e\u0432\u044b\u0435 \u043f\u043e\u043b\u044f \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0432 \u0432\u0438\u0434\u0435 \u0447\u0438\u0441\u0435\u043b, \u043d\u043e \u0434\u043b\u044f \u0444\u043e\u0440\u043c \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u043f\u043e\u043b\u044f \u0441\u0442\u0440\u043e\u043a\u0430\u043c\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u043b\u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b <code>Data<\/code> \u0438 <code>EncodedData<\/code>.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u043c\u043f\u043b\u0435\u043a\u0441\u043d\u044b\u0439 \u0442\u0435\u0441\u0442 \u043c\u043e\u0434\u0435\u043b\u0438, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0438\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438\u0437\u043e \u0432\u0441\u0435\u0445 \u043c\u0438\u043a\u0441\u0438\u043d\u043e\u0432<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"typescript\">import type { Data, EncodedData } from '@\/models\/simple'; import { create } from '@\/models\/simple';  \/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 function normalize(data: Data): EncodedData {   return {     id: data.id,     name: data.name,     age: Number(data.age)   }; }  \/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u0435\u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0438\u0437 \u0444\u043e\u0440\u043c\u0430\u0442\u0430 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0432\u043e \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0439 function denormalize(encoded: EncodedData): Data {   return {     id: encoded.id,     name: encoded.name,     age: String(encoded.age)   }; }  let counter = 0; \/\/ \u0441\u0447\u0435\u0442\u0447\u0438\u043a \u0434\u043b\u044f \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u044b\u0445 \u043a\u043b\u044e\u0447\u0435\u0439 const storage = new Map&lt;number, EncodedData>(); \/\/ \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435, \u0438\u043c\u0438\u0442\u0430\u0446\u0438\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u0430  const params = {   \/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0435\u0433\u043e \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u044b\u043c \u043a\u043b\u044e\u0447\u043e\u043c   create: (data: Data): Data => {     const id = ++counter; \/\/ \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u044b\u0439 \u043a\u043b\u044e\u0447     const record = { ...data, id }; \/\/ \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043a\u043e\u043f\u0438\u044e \u043e\u0431\u044a\u0435\u043a\u0442\u0430      storage.set(id as number, normalize(record)); \/\/ \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435      return record;   },   \/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435   update: (id: unknown, data: Data): Data => {     if (!storage.has(id as number)) throw new Error('resource not found');      const updated = { ...data }; \/\/ \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043a\u043e\u043f\u0438\u044e \u043e\u0431\u044a\u0435\u043a\u0442\u0430      storage.set(id as number, normalize(updated));      return updated;   },   \/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0443\u0434\u0430\u043b\u044f\u0435\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 \u0438\u0437 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430   destroy: (id: unknown): void => {     if (!storage.has(id as number)) throw new Error('resource not found');      storage.delete(id as number);   } };  \/\/ \u0437\u0430\u0434\u0430\u0435\u043c \u0441\u0442\u0430\u0440\u0442\u043e\u0432\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 storage.set(1, { id: 1, name: 'John', age: 20 }); ++counter;  \/\/ \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0434\u043b\u044f m1 \u0431\u0435\u0440\u0435\u043c \u0438\u0437 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 const m1 = create(denormalize(storage.get(1)!), true, params); const m2 = create(undefined, true, params);  console.log(m1.new, m1.pk, JSON.stringify(m1.data)); \/\/ false 1 {\"id\":1,\"name\":\"John\",\"age\":\"20\"} console.log(m2.new, m2.pk, JSON.stringify(m2.data)); \/\/ true 0 {\"id\":0,\"name\":\"\",\"age\":\"\"}  m2.data.name = 'Jane'; m2.v.c.name.touch(); m2.data.age = 'twenty';  console.log(m2.dirty); \/\/ true \/\/ \u0438\u043c\u044f \u0431\u044b\u043b\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u043e, \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u0440\u043e\u0448\u043b\u0430 \u0443\u0441\u043f\u0435\u0448\u043d\u043e console.log(m2.v.c.name.dirty, m2.v.c.name.invalid); \/\/ true false \/\/ \u0432\u043e\u0437\u0432\u0440\u0430\u0442 \u0442\u043e\u0436\u0435 \u0431\u044b\u043b \u0438\u0437\u043c\u0435\u043d\u0435\u043d, \u043d\u043e \u0444\u043b\u0430\u0433 dirty \u0443 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u043d\u0435 \u0431\u044b\u043b console.log(m2.v.c.age.dirty, m2.v.c.age.invalid); \/\/ false true \/\/ \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043d\u0435 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 console.log(m2.v.invalid); \/\/ true  m2.data.age = '20';  \/\/ \u043e\u0448\u0438\u0431\u043a\u0430 \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0430, \u043d\u043e \u0444\u043b\u0430\u0433 \u0432\u0441\u0435 \u0435\u0449\u0435 \u043d\u0435 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d console.log(m2.v.c.age.dirty, m2.v.c.age.invalid); \/\/ false false \/\/ \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 console.log(m2.v.invalid); \/\/ false  m2.v.c.age.touch();  \/\/ \u0442\u0435\u043f\u0435\u0440\u044c \u0444\u043b\u0430\u0433 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d console.log(m2.v.c.age.dirty, m2.v.c.age.invalid); \/\/ true false  \/\/ \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 (\u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435) \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0444\u043b\u0430\u0433\u0438 \/\/ saving \u0438 creating await m2.save();  \/\/ \u0444\u043b\u0430\u0433 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043c\u043e\u0434\u0435\u043b\u0438 \u043f\u043e\u0441\u043b\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438, \/\/ \u0430 \u0442\u0430\u043a\u043e\u0439 \u0436\u0435 \u0444\u043b\u0430\u0433 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u043d\u0435, \u043d\u0443\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434 `v.reset()` \u0438\u043b\u0438 `rollback()` console.log(m2.dirty, m2.v.dirty); \/\/ false true  m2.v.reset();  \/\/ \u0442\u0435\u043f\u0435\u0440\u044c \u0432\u0441\u0435 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e console.log(m2.dirty, m2.v.dirty); \/\/ false false  \/\/ \u0444\u043b\u0430\u0433 new \u0442\u0430\u043a\u0436\u0435 \u0441\u0431\u0440\u043e\u0448\u0435\u043d, \u0430 \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u044b\u0439 \u043a\u043b\u044e\u0447 \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 console.log(m2.new, m2.pk, JSON.stringify(m2.data)); \/\/ false 2 {\"id\":2,\"name\":\"Jane\",\"age\":\"20\"}  \/\/ \u0438\u0437\u043c\u0435\u043d\u0438\u043c \u043f\u043e\u043b\u0435 name \u043f\u0435\u0440\u0432\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438 \u0438 \u0437\u0430\u0444\u0438\u043a\u0441\u0438\u0440\u0443\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u043e\u0431\u044a\u0435\u043a\u0442\u0435 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 m1.data.name = 'John Doe'; m1.v.c.name.touch();  console.log(JSON.stringify(m1.data)); \/\/ {\"id\":1,\"name\":\"John Doe\",\"age\":\"20\"}  \/\/ \u043e\u0431\u0430 \u0444\u043b\u0430\u0433\u0430 dirty \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b console.log(m1.dirty, m1.v.dirty); \/\/ true true  \/\/ \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043c \u043e\u0442\u043a\u0430\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f m1.rollback();  \/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u043e\u0442\u043a\u0430\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f console.log(m1.dirty, m1.v.dirty, JSON.stringify(m1.data)); \/\/ false false {\"id\":1,\"name\":\"John\",\"age\":\"20\"}  \/\/ \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0444\u043b\u0430\u0433 deleted \u0432 true m1.delete();  \/\/ \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043f\u0440\u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0438 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0444\u043b\u0430\u0433\u0438 \/\/ saving, destroying await m1.save();  \/\/ \u043e\u0431\u044a\u0435\u043a\u0442 \u043f\u043e\u043c\u0435\u0447\u0435\u043d, \u043a\u0430\u043a \u0443\u0434\u0430\u043b\u0435\u043d\u043d\u044b\u0439 \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435, \u0438\u043c \u0432\u0441\u0435 \u0435\u0449\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f, \/\/ \u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0443\u0436\u0435 \u043d\u0435\u043b\u044c\u0437\u044f console.log(m1.destroyed); \/\/ true  \/\/ \u043e\u0447\u0438\u0449\u0430\u0435\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u043c \u0441\u0431\u043e\u0440\u0449\u0438\u043a\u0443 \u043c\u0443\u0441\u043e\u0440\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0441\u0432\u043e\u044e \u0440\u0430\u0431\u043e\u0442\u0443 m1.destroy(); m2.destroy();  \/\/ \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b \u043e\u0447\u0438\u0449\u0435\u043d\u044b, \u0441\u0431\u043e\u0440\u0449\u0438\u043a \u043c\u0443\u0441\u043e\u0440\u0430 \u0434\u043e\u0432\u043e\u043b\u0435\u043d \u043d\u0430\u043c\u0438 console.log(m1.instanceDestroyed); \/\/ true console.log(m2.instanceDestroyed); \/\/ true <\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<h3>\u0421\u043b\u043e\u0436\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c<\/h3>\n<p>\u0412\u0441\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u044b, \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a \u043f\u0440\u0438\u043c\u0435\u0440\u0443 \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438, \u0434\u043b\u044f \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <a href=\"https:\/\/vueent.github.io\/v9s\/\" rel=\"noopener noreferrer nofollow\">v9s<\/a> \u0432\u0435\u0440\u0441\u0438\u0438 2 \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u043d\u043e \u0441 <a href=\"https:\/\/github.com\/vueent\/v9sx\" rel=\"noopener noreferrer nofollow\">v9sx<\/a>. \u0414\u043b\u044f \u0442\u0435\u0445, \u043a\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0435\u0442 \u043f\u043e\u043b\u043d\u043e\u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u043d \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043f\u043e <a href=\"https:\/\/github.com\/vueent\/vueent-example\" rel=\"noopener noreferrer nofollow\">\u0441\u0441\u044b\u043b\u043a\u0435<\/a>.<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"typescript\">\/\/ file: .\/utilities\/validators.ts \/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0434\u0435\u0441\u044f\u0442\u0438\u0437\u043d\u0430\u0447\u043d\u043e\u0433\u043e \u043d\u043e\u043c\u0435\u0440\u0430 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0430 \u0438 \u0438\u043c\u0435\u043d\u0438. export const phoneRegex = \/^(([0-9]){10})$\/; export const nameRegex = \/^[0-9a-zA-Z. \\\\-]+$\/;  export function phone(value: string): boolean {   return phoneRegex.test(value); }  export function name(value: string): boolean {   return nameRegex.test(value); } <\/code><\/pre>\n<pre><code class=\"typescript\">\/\/ file: .\/models\/human.ts import type {   Base,   Rollback,   RollbackPrivate,   Save,   SavePrivate,   SaveOptions,   Validate,   ValidatePrivate,   ValidationBase,   ValidateOptions,   Options,   PatternAssert,   CreateFunc,   UpdateFunc,   DestroyFunc } from '@vueent\/mix-models'; import { BaseModel, mixRollback, mixSave, mixValidate, mix } from '@vueent\/mix-models'; import { v9s, simplify } from 'v9s'; import { hex, email, integer } from 'v9sx';  import { phone, name } from '@\/utilities\/validators';  \/\/ \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u043e\u0434\u0435\u043b\u0438 export interface Credentials {   first: string;   second: string;   last: string; }  export interface Document {   \/\/ \u043f\u043e\u043b\u0435 fakeId \u0443\u0434\u043e\u0431\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0438 \u043a\u043b\u044e\u0447\u0430 \u0432 \u0448\u0430\u0431\u043b\u043e\u043d\u0430\u0445 Vue   \/\/ \u0432\u043d\u0443\u0442\u0440\u0438 \u0446\u0438\u043a\u043b\u0430 `v-for`. H\u043c\u044f \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043b\u044e\u0431\u044b\u043c, \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0443\u0441\u043b\u043e\u0432\u043d\u043e\u0441\u0442\u044c   fakeId: number;   id: string;   filename: string; }  export interface Value {   fakeId: number;   val: string; }  export interface Item {   fakeId: number;   values: Value[]; }  export interface Data {   id: string;   \/\/ \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u0430\u0441\u0441\u0438\u0432\u0430 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043d\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0432    \/\/ \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u043e\u043b\u044f \u043c\u043e\u0434\u0435\u043b\u0438 \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0443\u0434\u043e\u0431\u043d\u043e, \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c   \/\/ \u0432 \u043c\u0430\u0441\u0441\u0438\u0432 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432, \u043d\u043e \u0437\u0434\u0435\u0441\u044c \u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0438\u043c\u0435\u043d\u043d\u043e \u043c\u0430\u0441\u0441\u0438\u0432 \u0441\u0442\u0440\u043e\u043a   \/\/ \u0434\u043b\u044f \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u0430   phones: string[];   phone: string;   email: string;   age: string;   credentials: Credentials;   documents: Document[];   items: Item[]; }  \/\/ \u0442\u0430\u043a \u043a\u0430\u043a \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u043e\u0434\u0435\u043b\u0438 \/\/ \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435, \/\/ \u0442\u043e \u0432\u043d\u0435\u0448\u043d\u0435\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e export type EncodedCredentials = Credentials;  \/\/ \u0438\u0437-\u0437\u0430 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0440\u0430\u0437\u043d\u0438\u0446\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u043e\u0434\u043d\u043e\u043c \u043f\u043e\u043b\u0435, \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u043a\u0440\u0430\u0442\u0438\u0442\u044c \u0437\u0430\u043f\u0438\u0441\u044c export type EncodedDocument = Omit&lt;Document, 'fakeId'>;  export type EncodedValue = Omit&lt;Value, 'fakeId'>;  \/\/ \u0437\u0434\u0435\u0441\u044c \u0441\u043e\u043a\u0440\u0430\u0442\u0438\u0442\u044c \u043d\u0435 \u0432\u044b\u0439\u0434\u0435\u0442, \u0442\u0430\u043a \u043a\u0430\u043a \u0440\u0430\u0437\u043b\u0438\u0447\u0430\u044e\u0442\u0441\u044f \u0442\u0438\u043f\u044b \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0445 \u043f\u043e\u043b\u0435\u0439 export interface EncodedItem {   values: EncodedValue[]; }  export interface EncodedData {   id: string;   phones: string[];   phone: string;   email: string;   age: number;   credentials: EncodedCredentials;   documents: EncodedDocument[];   items: EncodedItem[]; }  export function makeInitialData(): Data {   return {     id: '',     phones: [],     phone: '',     email: '',     age: '',     credentials: {       first: '',       second: '',       last: ''     },     documents: [],     items: []   }; }  const rollbackMask = {   id: false,   phones: true,   phone: true,   email: true,   age: true,   \/\/ \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0434\u043b\u044f \u043f\u043e\u043b\u0435\u0439 \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u043c\u043e\u0433\u0443\u0442 \u0437\u0430\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438   credentials: {     first: true,     second: true,     last: true   },   documents: true,   items: true } as const;  \/\/ \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u0430\u044f \u043c\u0430\u0441\u043a\u0430, \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u0430 \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 \u043c\u0435\u0442\u043e\u0434\u0430 `rollback()` export const alternativeRollbackMask = {   id: false,   phones: true,   phone: true,   email: false,   age: true,   credentials: {     first: false,     second: false,     last: true   },   documents: {     \/\/ \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0438\u0442\u044c, \u0447\u0442\u043e \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u0435 \u043f\u043e\u043b\u0435 \u043c\u0430\u0441\u0441\u0438\u0432, \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f `$array: true`     $array: true,     \/\/ \u0434\u0430\u043b\u044c\u0448\u0435 \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c - \u043a\u0430\u043a\u0438\u0435 \u043f\u043e\u043b\u044f \u0434\u043e\u043b\u0436\u043d\u044b \u0438\u043b\u0438 \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0441\u0431\u0440\u043e\u0448\u0435\u043d\u044b     id: false,     filename: true   },   items: {     $array: true,     \/\/ \u043c\u043e\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432 \u043c\u0430\u0441\u0441\u0438\u0432\u0430, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u043e     $index: [0]     values: false   } } as const;  const validations = {   phones: {     \/\/ \u0447\u0435\u0440\u0435\u0437 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 $each \u0437\u0430\u0434\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u043e \u043a \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0443 \u043c\u0430\u0441\u0441\u0438\u0432\u0430     $each: simplify(v9s&lt;string>().minLength(1, 'Enter phone number').use(phone, 'Invalid phone format')),     \/\/ \u044d\u0442\u043e\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0437\u0430\u0434\u0430\u0435\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u043e \u0434\u043b\u044f \u0441\u0430\u043c\u043e\u0433\u043e \u043c\u0430\u0441\u0441\u0438\u0432\u0430 \u0438\u043b\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u0430     $self: simplify(v9s&lt;string>().minLength(1, 'Invalid phones'))   },   phone: simplify(v9s&lt;string>().minLength(1, 'Enter phone number').use(phone, 'Invalid phone format')),   email: simplify(     v9s&lt;string>()       .minLength(1, 'Enter E-mail')       .maxLength(255, 'Maximum E-mail length exceeded')       .use(email, 'Invalid E-mail format')   ),   age: simplify(     v9s&lt;string>()       .minLength(1, 'Enter age')       .use(integer, 'Age must be an integer value', Number)       .gte(0, 'Age cannot be negative')       .lte(150, 'Age cannot exceed 150 years')   ),   credentials: {     \/\/ \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 $sub \u0437\u0430\u0434\u0430\u0435\u0442\u0441\u044f \u043d\u0430\u0431\u043e\u0440 \u043f\u0440\u0430\u0432\u0438\u043b \u0434\u043b\u044f \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430     $sub: {       first: simplify(         v9s&lt;string>()           .minLength(1, 'Enter first name')           .maxLength(255, 'Maximum first name length exceeded')           .use(name, 'Remove invalid characters')       ),       second: simplify(         v9s&lt;string>()           .maxLength(255, 'Maximum second name length exceeded')           .use(name, 'Remove invalid characters')           .or(v9s&lt;string>().strictLength(0, 'Remove invalid characters'))       ),       last: simplify(         v9s&lt;string>()           .minLength(1, 'Enter last name')           .maxLength(255, 'Maximum last name length exceeded')           .use(name, 'Remove invalid characters')       )     }   },   documents: {     \/\/ \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0434\u043b\u044f $each \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0434\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 \u0441 \u043f\u043e\u043b\u044f\u043c\u0438     $each: {       id: simplify(         v9s&lt;string>()           .minLength(1, 'Enter document id')           .strictLength(32, 'Document id length must be equal to 32 characters')           .use(hex, 'Document id must be a hex string')       ),       filename: simplify(         v9s&lt;string>().minLength(1, 'Enter document filename').maxLength(1024, 'Maximun document filename length exceeded')       )     }   },   items: {     $each: {       values: {         $each: {           val: simplify(             v9s&lt;string>()               .minLength(1, 'Enter value')               .minLength(6, 'Value length must exceed 6 characters')               .maxLength(255, 'Maximum value length exceeded')           )         }       }     }   } } as const;  export type Validations = PatternAssert&lt;typeof validations, Data>;  class DataModel extends BaseModel&lt;Data> {}  export type ModelType = Base&lt;Data> &amp; Rollback &amp; Save &amp; Validate&lt;Validations>;  export interface Model extends DataModel, RollbackPrivate&lt;Data>, SavePrivate&lt;Data>, ValidatePrivate&lt;Validations> {}  export class Model extends mix&lt;Data, typeof DataModel>(   DataModel,   mixRollback(rollbackMask),   mixSave(),   mixValidate(validations) ) {   constructor(initialData?: Data, react = true, ...options: Options[]) {     super('id', initialData ?? makeInitialData(), react, ...options);      if (this.pk) this._flags.new = false;   }    \/\/ \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u0431\u0443\u0434\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u0431\u0440\u043e\u0448\u0435\u043d\u043e \u043f\u043e\u0441\u043b\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043c\u043e\u0434\u0435\u043b\u0438   afterSave(): void {     this.v.reset();   } }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0412 \u0441\u0432\u044f\u0437\u0438 \u0441 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f\u043c\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>watch<\/code> \u0432\u043e Vue 3 \u0438 Vue 2.7, \u043f\u0440\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u0438\u043b\u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0438\u0437 \u043c\u0430\u0441\u0441\u0438\u0432\u0430, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0437\u0430\u043c\u0435\u043d\u044f\u0442\u044c \u043c\u0430\u0441\u0441\u0438\u0432 \u0446\u0435\u043b\u0438\u043a\u043e\u043c, \u0432 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440 \u043d\u0435 \u0441\u043c\u043e\u0436\u0435\u0442 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043e\u0442\u0441\u043b\u0435\u0434\u0438\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f. \u041c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043b\u0438\u0431\u043e \u0430\u043d\u0430\u043b\u043e\u0433\u0438:<\/p>\n<pre><code class=\"typescript\">const splice = &lt;T = any>(arr: Array&lt;T>, start = 0, count = 1, ...items: T[]) => [   ...arr.slice(0, start),   ...items,   ...arr.slice(start + count) ];<\/code><\/pre>\n<p>\u0421\u0442\u043e\u0438\u0442 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043c\u0430\u0441\u043a\u0438 \u0434\u043b\u044f \u043e\u0442\u043a\u0430\u0442\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0438\u043c\u0435\u044e\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f, \u0432 \u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438, \u043d\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0437\u0430\u0434\u0430\u0442\u044c \u0440\u0430\u0437\u043d\u044b\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043e\u0442\u043a\u0430\u0442\u0430 \u0434\u043b\u044f \u0440\u0430\u0437\u043d\u044b\u0445 \u043d\u0430\u0431\u043e\u0440\u043e\u0432 \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432 \u043c\u0430\u0441\u0441\u0438\u0432\u0430, \u043d\u043e \u0442\u0430\u043a \u043a\u0430\u043a \u044d\u0442\u0430 \u0437\u0430\u0434\u0430\u0447\u0430 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0440\u0435\u0434\u043a\u043e \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435, \u0442\u043e \u043f\u043e\u043a\u0430 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u043d\u0435\u0442. \u0422\u0430\u043a\u0436\u0435 \u043d\u0435\u0442 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u043e\u0442\u043a\u0430\u0442\u0430 \u0438\u043b\u0438 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0438 \u043e\u0442\u043a\u0430\u0442\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432 \u0434\u043b\u044f \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u0432, \u0441\u043e\u0441\u0442\u043e\u044f\u0449\u0438\u0445 \u0438\u0437 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440: <code>string[]<\/code>).<\/p>\n<h4>Store<\/h4>\n<p><code>@vueent\/store<\/code> \u2014 \u044d\u0442\u043e \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0430\u043a\u0435\u0442, \u0442\u0430\u043a \u0447\u0442\u043e \u0435\u0433\u043e \u0441\u0442\u043e\u0438\u0442 \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c, \u0441\u043a\u043e\u0440\u0435\u0435, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0439 \u043a\u043e\u043d\u0446\u0435\u043f\u0442, \u043d\u0435\u0436\u0435\u043b\u0438 \u043f\u0440\u043e\u0434\u0443\u043c\u0430\u043d\u043d\u043e\u0435 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0435\u043d\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435, \u0432 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0445 \u0442\u0440\u0435\u0445 \u043f\u0430\u043a\u0435\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0443\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438\u0441\u044c \u043c\u043d\u043e\u044e \u0432 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445. \u0422\u0435\u043c, \u043a\u0442\u043e \u0437\u043d\u0430\u043a\u043e\u043c \u0441 <code>ember-data<\/code> \u043c\u043d\u043e\u0433\u043e\u0435 \u043f\u043e\u043a\u0430\u0436\u0435\u0442\u0441\u044f \u0437\u043d\u0430\u043a\u043e\u043c\u044b\u043c, \u0442\u0430\u043a \u0438 \u0437\u0430\u0434\u0443\u043c\u0430\u043d\u043e. \u0418\u0434\u0435\u044f \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b, \u043a\u0440\u043e\u043c\u0435 \u043c\u043e\u0434\u0435\u043b\u0438, \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0435\u0449\u0435 \u043a\u043b\u0430\u0441\u0441-\u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044e, \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u2014 \u043a\u0430\u043a \u0435\u0434\u0438\u043d\u0443\u044e \u0442\u043e\u0447\u043a\u0443 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u043c\u043e\u0434\u0435\u043b\u044f\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u0430. \u0412\u0441\u0435 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u044e\u0442\u0441\u044f \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 (store), \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043a\u0430\u043a \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c \u043a\u043b\u0430\u0441\u0441\u043e\u043c, \u0442\u0430\u043a \u0438 \u043e\u0434\u043d\u0438\u043c \u0438\u0437 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 <code>@vueent\/core<\/code>.<\/p>\n<h3>\u041f\u0440\u043e\u0441\u0442\u0430\u044f \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f<\/h3>\n<p>\u0412\u043e\u0437\u044c\u043c\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u0443\u044e \u043c\u043e\u0434\u0435\u043b\u044c \u0438\u0437 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0430 \u0438 \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0434\u043b\u044f \u043d\u0435\u0435 \u043a\u043b\u0430\u0441\u0441-\u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044e, \u0441\u043f\u0435\u0440\u0432\u0430 \u0432 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e\u043c \u0432\u0438\u0434\u0435:<\/p>\n<pre><code class=\"typescript\">\/\/ file: .\/collections\/simple.ts import { Collection } from '@vueent\/store';  import type { Data, EncodedData, ModelType } from '@\/models\/simple'; import { Model } from '@\/models\/simple'; import * as api from '@\/api\/simple'; \/\/ \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u0434\u043b\u044f \u0432\u044b\u0437\u043e\u0432\u0430 API \u043c\u043d\u0438\u043c\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430  \/\/ \u043f\u0440\u0438 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0438 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 \u043d\u0443\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0432\u0441\u0435 \u0442\u0435 \u0442\u0438\u043f\u044b, \u0447\u0442\u043e \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u044b \u043d\u0438\u0436\u0435 \/\/ \u0435\u0441\u043b\u0438 \u0443 \u043d\u0430\u0441 \u043d\u0435\u0442 EncodedData, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e Data export class SimpleCollection extends Collection&lt;Model, Data, EncodedData, ModelType> {   constructor() {     \/\/ \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u043c\u043e\u0434\u0435\u043b\u0438 \u0432 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440     super({ construct: Model });   } }<\/code><\/pre>\n<p>\u0415\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435, \u0447\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0430\u043a\u0430\u044f \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f \u2014 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b \u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u0438 \u0432\u044b\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0438\u0445. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 \u0438 \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u0444\u0443\u043d\u043a\u0446\u0438\u0439.<\/p>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043d\u0435 \u0437\u0430\u0434\u0430\u043d\u044b, \u0442\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 \u043b\u0438\u0448\u044c \u0434\u0432\u0430 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f:<\/p>\n<ol>\n<li>\n<p>\u041f\u043e\u0438\u0441\u043a \u0432 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u043c \u043a\u044d\u0448\u0435 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438<\/p>\n<\/li>\n<li>\n<p>\u0412\u044b\u0433\u0440\u0443\u0437\u043a\u0430 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430<\/p>\n<\/li>\n<li>\n<p>\u041e\u0447\u0438\u0441\u0442\u043a\u0430 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438<\/p>\n<\/li>\n<\/ol>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0431\u0430\u0437\u043e\u0432\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"typescript\">import { SimpleCollection } from '@\/collections\/simple';  \/\/ \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 const coll = new SimpleCollection();  \/\/ \u043a\u043b\u0430\u0441\u0441 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 \u0443\u0436\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043c\u0435\u0442\u043e\u0434 create, \u0442\u0430\u043a \u0447\u0442\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0432 \u043c\u043e\u0434\u0443\u043b\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043d\u0435 \u043d\u0443\u0436\u043d\u043e const m1 = coll.create();  \/\/ \u0437\u0430\u0434\u0430\u0434\u0438\u043c \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0438 \u0438\u043c\u044f m1.data.id = 1; m1.data.name = 'John'; m1.data.age = '25';  \/\/ \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0435\u0449\u0435 \u0434\u0432\u0430 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430, \u0441\u0440\u0430\u0437\u0443 \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 const m2 = coll.create({ id: 2, name: 'Jane', age: '20' }); const m3 = coll.create({ id: 3, name: 'Samantha', age: '19' });  \/\/ \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043c \u043f\u043e\u0438\u0441\u043a \u0432 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u043c \u043a\u044d\u0448\u0435 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438, \u043f\u043e\u0438\u0441\u043a \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043f\u043e \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u043e\u043c\u0443 \u043a\u043b\u044e\u0447\u0443 const m1dup = coll.peekOne(1);  \/\/ \u0442\u0430\u043a \u043a\u0430\u043a \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0431\u044b\u043b \u0441\u043e\u0437\u0434\u0430\u043d \u043a\u0430\u043a \u043d\u043e\u0432\u044b\u0439, \u0442\u043e \u0435\u0441\u0442\u044c \u0444\u043b\u0430\u0433 new \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d, \/\/ \u0442\u043e \u0442\u0430\u043a\u043e\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043d\u0435 \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043f\u043e\u0438\u0441\u043a\u0435, \u043f\u043e\u0441\u043b\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0433\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \/\/ \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d \u0432 \u0433\u0440\u0443\u043f\u043f\u0443 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 console.log(m1dup); \/\/ null  \/\/\/ \u043f\u043e\u0432\u0442\u043e\u0440\u0438\u043c \u043f\u043e\u0438\u0441\u043a \u0441 \u0434\u0440\u0443\u0433\u0438\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c const m2dup = coll.peekOne(2);  \/\/ \u0442\u0430\u043a \u043a\u0430\u043a \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043f\u043e\u0438\u0441\u043a \u0432 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u043c \u043a\u044d\u0448\u0435, \u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0435\u043d \/\/ \u0442\u043e\u0442 \u0436\u0435 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043c\u043e\u0434\u0435\u043b\u0438. \/\/ \u043a\u0430\u043a \u043c\u044b \u043f\u043e\u043c\u043d\u0438\u043c, \u0432 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u043c\u044b \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u043b\u0438 \u0443\u0441\u043b\u043e\u0432\u0438\u0435 \u0434\u043b\u044f \u0441\u0431\u0440\u043e\u0441\u0430 \u0444\u043b\u0430\u0433\u0430 new, \/\/ \u0435\u0441\u043b\u0438 \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u044b\u0439 \u043a\u043b\u044e\u0447 \u0443\u043a\u0430\u0437\u0430\u043d \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043c\u043e\u0434\u0435\u043b\u0438 console.log(m2dup === m2); \/\/ true  \/\/ \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u043e\u0438\u0441\u043a, \u0437\u0430\u0434\u0430\u0432 \u0444\u0438\u043b\u044c\u0442\u0440, \u044d\u0442\u043e\u0442 \u0436\u0435 \u043e\u0431\u044a\u0435\u043a\u0442 \u0441 \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u043c \/\/ \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0434\u0430\u0442\u044c \u0432\u0442\u043e\u0440\u044b\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c \u0434\u043b\u044f \u043c\u0435\u0442\u043e\u0434\u0430 `peekOne()` const models = coll.peek({ localFilter: data => Number(data.age) >= 20 });  \/\/ \u0442\u0430\u043a \u043a\u0430\u043a \u0443 Samantha \u0432\u043e\u0437\u0440\u0430\u0441\u0442 19, \u0430 John \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043f\u043e\u0438\u0441\u043a\u0435, \/\/ \u0442\u043e \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0438\u0440\u0443\u044e\u0449\u0435\u043c \u043c\u0430\u0441\u0441\u0438\u0432\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u043e\u0431\u044a\u0435\u043a\u0442 console.log(models.length); \/\/ 1  \/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c, \u0447\u0442\u043e \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u0435 \u043c\u043e\u0434\u0435\u043b\u0438, \u0447\u0442\u043e \u043c\u044b \u043e\u0436\u0438\u0434\u0430\u0435\u043c console.log(models.includes(m1), models.includes(m2)); \/\/ false true  \/\/ \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0441 \u0442\u0435\u043c \u0436\u0435 id, \u0447\u0442\u043e \u0438 \u0443 Samantha try {   coll.create({ id: 3, name: 'Sam', age: '20' }); } catch (e) {   console.log((e as Error).message); \/\/ duplicate primary key }  \/\/ \u043f\u043e\u043f\u0440\u0430\u0432\u0438\u043c \u0432\u043e\u0437\u0440\u0430\u0441\u0442 \u0443 Samantha m3.data.age = '20';  \/\/ \u043f\u043e\u0432\u0442\u043e\u0440\u0438\u043c \u043f\u043e\u0438\u0441\u043a const models2 = coll.peek({ localFilter: data => Number(data.age) >= 20 });  \/\/ \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432, \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e, \u0434\u0432\u0430 console.log(models2.length); \/\/ 2  \/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c, \u0447\u0442\u043e \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u0435 \u043c\u043e\u0434\u0435\u043b\u0438, \u0447\u0442\u043e \u043c\u044b \u043e\u0436\u0438\u0434\u0430\u0435\u043c console.log(models2.includes(m2), models2.includes(m3)); \/\/ true true  \/\/ \u0432\u044b\u0433\u0440\u0443\u0437\u0438\u043c \u0437\u0430\u043f\u0438\u0441\u044c \u0441 \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u044b\u043c \u043a\u043b\u044e\u0447\u043e\u043c 3, \u043f\u0435\u0440\u0435\u0434\u0430\u0432 uid \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 \u0432 \u043c\u0435\u0442\u043e\u0434 \/\/ `unload()` \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438. \u0421\u0432\u043e\u0439\u0441\u0442\u0432\u043e uid \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438, \/\/ \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043d\u043e\u0432\u043e\u0433\u043e \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 \u043c\u043e\u0434\u0435\u043b\u0438 \/\/ \u0442\u0435\u043f\u0435\u0440\u044c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b \u043d\u0443\u0436\u043d\u043e \u0443\u043d\u0438\u0447\u0442\u043e\u0436\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 unload, \u0430 \u043d\u0435 \u043f\u0440\u044f\u043c\u044b\u043c \u0432\u044b\u0437\u043e\u0432\u043e\u043c \/\/ \u043c\u0435\u0442\u043e\u0434\u0430 `destroy()` \u043c\u043e\u0434\u0435\u043b\u0438 coll.unload(m3.uid);  \/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0443 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e \u0448\u0430\u0433\u0430 console.log(m3.instanceDestroyed); \/\/ true  coll.destroy(); \/\/ \u043e\u0447\u0438\u0449\u0430\u0435\u0442 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044e, \u0432\u044b\u0437\u044b\u0432\u0430\u044f `unloadAll()`  \/\/ \u043e\u0447\u0438\u0449\u0435\u043d\u044b \u0432\u0441\u0435 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b, \u0434\u0430\u0436\u0435 \u0442\u0435, \u0447\u0442\u043e \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u043f\u0440\u0438 \u043f\u043e\u0438\u0441\u043a\u0435 console.log(m1.instanceDestroyed, m2.instanceDestroyed); \/\/ true, true <\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0422\u043e \u0435\u0441\u0442\u044c, \u0434\u0430\u0436\u0435 \u0434\u043b\u044f \u043c\u043e\u0434\u0435\u043b\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u044b \u0433\u0434\u0435-\u043b\u0438\u0431\u043e, \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 \u0432\u0441\u0435 \u0436\u0435 \u0434\u0430\u044e\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438.<\/p>\n<h3>\u041a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f \u0441 \u0434\u043e\u0441\u0442\u0443\u043f\u043e\u043c \u043a\u043e \u0432\u043d\u0435\u0448\u043d\u0435\u043c\u0443 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0443<\/h3>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 CRUD-\u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u043a \u043d\u0430\u0448\u0435\u0439 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438.<\/p>\n<pre><code class=\"typescript\">\/\/ file: .\/collections\/simple.ts import { Collection } from '@vueent\/store';  import type { Data, EncodedData, ModelType } from '@\/models\/simple'; import { Model } from '@\/models\/simple'; import * as api from '@\/api\/simple'; \/\/ \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u0434\u043b\u044f \u0432\u044b\u0437\u043e\u0432\u0430 API \u043c\u043d\u0438\u043c\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430  \/\/ \u043f\u0440\u0438 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0438 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 \u043d\u0443\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0432\u0441\u0435 \u0442\u0435 \u0442\u0438\u043f\u044b, \u0447\u0442\u043e \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u044b \u043d\u0438\u0436\u0435 export class SimpleCollection extends Collection&lt;Model, Data, EncodedData, ModelType> {   constructor() {     super({       construct: Model, \/\/ \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440       \/\/ \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b, \u043e\u043d\u0438 \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0442, \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0437\u0430       \/\/ \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435, \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435, \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435, \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u043e\u0434\u043d\u043e\u0439 \u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0438\u0437       \/\/ \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u043e \u0442\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e, \u043a\u043e\u0442\u043e\u0440\u043e\u0435       \/\/ \u0443\u043a\u0430\u0437\u0430\u043d\u043e \u043f\u0435\u0440\u0432\u044b\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0430 (super)       \/\/ \u0432 \u043a\u043b\u0430\u0441\u0441\u0435 \u043c\u043e\u0434\u0435\u043b\u0438.       createData: (data: EncodedData): Promise&lt;unknown> => {         return api.create(data);       },       destroyData: (id: unknown): Promise&lt;void> => {         return api.destroy({ id: id as number });       },       updateData: (id: unknown, data: EncodedData): Promise&lt;unknown> => {         return api.update({ ...data, id: id as number });       },       loadOneData: (pk: unknown): Promise&lt;EncodedData> => {         return api.findOne({ id: pk as number });       },       \/\/ \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 options \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u043e\u0431\u044a\u0435\u043a\u0442, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e queryParams,       \/\/ \u043d\u0430\u0431\u043e\u0440 \u043e\u043f\u0446\u0438\u0439 \u0432\u043d\u0443\u0442\u0440\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 queryParams \u0437\u0430\u0434\u0430\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u043c       loadManyData: async (options: {         queryParams?: {           ids?: number[];           name?: string;           age?: number;         };       }): Promise&lt;EncodedData[]> => {         const response = await api.find(options.queryParams ? options.queryParams : {});          return response.items;       }     });   }    \/\/ \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445 \u0434\u043b\u044f \u043c\u043e\u0434\u0435\u043b\u0438, \u0444\u0443\u043d\u043a\u0446\u0438\u0438 normalize \u0438 denormalize \u0431\u044b\u043b\u0438 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u0444\u0443\u043d\u0446\u0438\u044f\u043c\u0438,   \/\/ \u0437\u0434\u0435\u0441\u044c \u043e\u043d\u0438 \u0434\u0435\u043b\u0430\u044e\u0442 \u0440\u043e\u0432\u043d\u043e \u0442\u043e\u0436\u0435 \u0441\u0430\u043c\u043e\u0435, \u043d\u043e \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u044b \u0432 \u043a\u043b\u0430\u0441\u0441 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438. \u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e   \/\/ \u044d\u0442\u0438 \u043c\u0435\u0442\u043e\u0434\u044b \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0442 \u043f\u043b\u043e\u0441\u043a\u0443\u044e \u043a\u043e\u043f\u0438\u044e \u043e\u0431\u044a\u0435\u043a\u0442\u0430, \u0442\u0430\u043a \u0447\u0442\u043e \u0434\u043b\u044f \u043f\u043e\u0441\u0442\u044b\u0445 \u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u0438\u0445   \/\/ \u043c\u043e\u0436\u043d\u043e \u043d\u0435 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c. \u0422\u0430\u043a\u0436\u0435 \u0441\u044e\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u0432\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439.   public normalize(encoded: EncodedData): Data {     return {       id: encoded.id,       name: encoded.name,       age: String(encoded.age)     };   }    public denormalize(data: Data): EncodedData {     return {       id: data.id,       name: data.name,       age: Number(data.age)     };   } }<\/code><\/pre>\n<p>\u0412 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 \u0432\u044b\u0448\u0435 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u0432\u044b\u0437\u043e\u0432\u044b \u043d\u0435\u043a\u043e\u0435\u0433\u043e \u043c\u043e\u0434\u0443\u043b\u044f <code>api<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0435\u0449\u0435 \u043d\u0435 \u043e\u043f\u0438\u0441\u0430\u043d. \u0418\u0441\u043f\u0440\u0430\u0432\u0438\u043c \u044d\u0442\u0443 \u043e\u043f\u043b\u043e\u0448\u043d\u043e\u0441\u0442\u044c \u0438 \u0434\u0430\u0434\u0438\u043c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f. \u0422\u0430\u043a \u043a\u0430\u043a \u0437\u0434\u0435\u0441\u044c \u0443\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0435\u0449\u0435 \u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u043a\u043e\u0434\u0430, \u0447\u0442\u043e \u043c\u043e\u0434\u0443\u043b\u044c \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u0442\u044c \u0438\u0437 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0444\u0430\u0439\u043b\u043e\u0432.<\/p>\n<details class=\"spoiler\">\n<summary>\u041c\u043e\u0434\u0443\u043b\u044c api<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"typescript\">\/\/ file: .\/api\/simple\/requests.ts \/\/ \u0437\u0434\u0435\u0441\u044c \u0437\u0430\u0434\u0430\u0434\u0438\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b \u0434\u043b\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u0443\u0434\u043e\u0431\u043d\u043e \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \/\/ \u0441 \u043a\u043e\u043d\u0435\u0447\u043d\u044b\u043c\u0438 \u0442\u043e\u0447\u043a\u0430\u043c\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 import type { EncodedData } from '@\/models\/simple';  export interface Find {   ids?: number[];   name?: string;   age?: number; }  export interface FindOne {   id: number; }  export type Create = EncodedData;  export type Update = EncodedData;  export interface Destroy {   id: number; } <\/code><\/pre>\n<pre><code class=\"typescript\">\/\/ file: .\/api\/simple\/responses.ts \/\/ \u0437\u0434\u0435\u0441\u044c \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0438\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b \u043e\u0442\u0432\u0435\u0442\u043e\u0432 import type { EncodedData } from '@\/models\/simple';  export interface Find {   items: EncodedData[]; }  export type FindOne = EncodedData; export type Create = EncodedData; export type Update = EncodedData; <\/code><\/pre>\n<pre><code class=\"typescript\">\/\/ file: .\/api\/simple\/endpoints.ts \/\/ \u0437\u0434\u0435\u0441\u044c \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0449\u0438\u0435 \u0437\u0430\u043a\u043f\u0440\u043e\u0441\u044b \u043a \u043a\u043e\u043d\u0435\u0447\u043d\u044b\u043c \u0442\u043e\u0447\u043a\u0438 \u043d\u0430\u0448\u0435\u0433\u043e \"\u0441\u0435\u0440\u0432\u0435\u0440\u0430\" import * as storage from '@\/storage'; \/\/ \u043c\u043e\u0434\u0443\u043b\u044c, \u0438\u043c\u0438\u0442\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u0441\u0435\u0440\u0432\u0435\u0440  import type * as requests from '.\/requests'; import type * as responses from '.\/responses';  \/\/ \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f-\u0434\u0435\u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0437\u0434\u0435\u0441\u044c \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 JSON \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043b\u044f \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u043e\u0441\u0442\u0438  export async function find(req: requests.Find): Promise&lt;responses.Find> {   const response = await storage.find(req);    return JSON.parse(response); }  export async function findOne(req: requests.FindOne): Promise&lt;responses.FindOne> {   const response = await storage.findOne(req.id);    return JSON.parse(response); }  export async function create(req: requests.Create): Promise&lt;responses.Create> {   const response = await storage.create(JSON.stringify(req));    return JSON.parse(response); }  export async function update(req: requests.Update): Promise&lt;responses.Update> {   const response = await storage.update(req.id, JSON.stringify(req));    return JSON.parse(response); }  export async function destroy(req: requests.Destroy): Promise&lt;void> {   await storage.destroy(req.id); } <\/code><\/pre>\n<pre><code class=\"typescript\">\/\/ file: .\/api\/simple\/index.ts export * from '.\/endpoints'; <\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u043c\u0443\u043b\u044f\u0442\u043e\u0440 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u2014 \u043c\u043e\u0434\u0443\u043b\u044c <code>storage<\/code>, \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0431\u0443\u0434\u0443\u0442 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u043c\u0438 \u0434\u043b\u044f \u0438\u043c\u0438\u0442\u0430\u0446\u0438\u0438 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043f\u043e \u0441\u0435\u0442\u0438.<\/p>\n<details class=\"spoiler\">\n<summary>\u041c\u043e\u0434\u0443\u043b\u044c storage<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"typescript\">\/\/ file: .\/storage.ts import type { EncodedData } from '@\/models\/simple';  let idCounter = 0; \/\/ \u0441\u0447\u0435\u0442\u0447\u0438\u043a \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u0432 const storage = new Map&lt;number, string>(); \/\/ \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \/\/ \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f-\u043e\u0431\u0435\u0440\u0442\u043a\u0430 \u0434\u043b\u044f \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u043e\u0441\u0442\u0438 const genPk = () => ++idCounter;  \/\/ \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0430\u044f \u043e\u0431\u0435\u0440\u0442\u043a\u0430, \u0441\u0440\u0430\u0437\u0443 \u0434\u0435\u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0430\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0437 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 function get(key: number): any | undefined {   const result = storage.get(key);    return result ? JSON.parse(result) : undefined; }  \/\/ \u0435\u0449\u0435 \u043e\u0434\u043d\u0430 \u043e\u0431\u0435\u0440\u0442\u043a\u0430, \u0432 \u0446\u0438\u043a\u043b\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0449\u0430\u044f \u0434\u0435\u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 function forEach(callback: (value: any) => void) {   for (const [, item] of storage) {     callback(JSON.parse(item));   } }  \/\/ \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043d\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u043f\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c export async function find(queryParams?: { ids?: number[]; name?: string; age?: number }): Promise&lt;string> {   const res: { items: EncodedData[] } = { items: [] };    if (queryParams?.ids?.length) {     for (const id of queryParams.ids) {       const item = get(id);        if (item) res.items.push(item);     }   } else if (queryParams) {     const filters: Array&lt;(v: EncodedData) => boolean> = [];      if (queryParams.name) {       filters.push((v: EncodedData) => v.name === queryParams.name);     } else if (queryParams.age) {       filters.push((v: EncodedData) => v.age === queryParams.age);     }      forEach(item => {       if (filters.every(filter => filter(item))) res.items.push(item);     });   } else {     forEach(item => res.items.push(item));   }    res.items.sort((a, b) => a.id - b.id);    return JSON.stringify(res); }  \/\/ \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0437 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u043f\u043e \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0443 export async function findOne(id: number): Promise&lt;string> {   const data = storage.get(id);    if (!data) throw new Error('resource not found');    return data; }  \/\/ \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u043d\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 export async function create(data: string): Promise&lt;any> {   const item = JSON.parse(data);    item.id = genPk();    const encoded = JSON.stringify(item);    storage.set(item.id, encoded);    return encoded; }  \/\/ \u0438\u0437\u043c\u0435\u043d\u044f\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 export async function update(id: number, data: string): Promise&lt;string> {   if (!storage.has(id)) throw new Error('resource not found');    const item = JSON.parse(data);    item.id = id;    const encoded = JSON.stringify(item);    storage.set(id, encoded);    return encoded; }  \/\/ \u0443\u0434\u0430\u043b\u044f\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0437 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 export async function destroy(key: number): Promise&lt;void> {   if (storage.has(key)) storage.delete(key); }  \/\/ \u043e\u0447\u0438\u0441\u0442\u043a\u0430 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430, \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u043c\u0435\u0436\u0434\u0443 \u0442\u0435\u0441\u0442\u0430\u043c\u0438 export function clear() {   storage.clear();   idCounter = 0; } <\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u043a\u043e\u0433\u0434\u0430 \u0432\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043c\u043e\u0434\u0443\u043b\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u044b, \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 \u0432 \u0441\u0432\u044f\u0437\u043a\u0435 \u0441 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u043c. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435, \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u043c, \u0438\u0437\u043c\u0435\u043d\u0438\u043c \u0438 \u0443\u0434\u0430\u043b\u0438\u043c \u0438\u0445.<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 CRUD-\u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"typescript\">\/\/ \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u043c \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0434\u0443\u043b\u044c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430, \u0447\u0442\u043e\u0431\u044b \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0435\u0433\u043e \u043e\u0447\u0438\u0441\u0442\u0438\u0442\u044c \u0432 \u043a\u043e\u043d\u0446\u0435 \u0442\u0435\u0441\u0442\u0430 import * as storage from '@\/storage'; import { SimpleCollection } from '@\/collections\/simple';  const coll = new SimpleCollection();  \/\/ \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043f\u0443\u0441\u0442\u043e\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 const john = coll.create();  john.data.name = 'John'; john.data.age = '25';  await john.save();  const jane = coll.create();  jane.data.name = 'Jane'; jane.data.age = '20';  await jane.save();  const sam = coll.create();  sam.data.name = 'Samantha'; sam.data.age = '19';  const models = coll.peek();  \/\/ \u0442\u0430\u043a \u043a\u0430\u043a \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 sam \u043d\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d, \u0442\u043e \u0435\u0433\u043e \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 console.log(models.length); \/\/ 2 \/\/ \u043a\u0430\u043a \u0438 \u043e\u0436\u0438\u0434\u0430\u0435\u0442\u0441\u044f, \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b john \u0438 jane \u0432 \u043c\u0430\u0441\u0441\u0438\u0432\u0435 console.log(models.includes(john), models.includes(jane)); \/\/ true true  await sam.save();  const models2 = coll.peek();  \/\/ \u0442\u0435\u043f\u0435\u0440\u044c \u0432\u0441\u0435 \u0442\u0440\u0438 \u0437\u0430\u043f\u0438\u0441\u0438 \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u044c \u0438\u0437 \u043a\u044d\u0448\u0430 console.log(models2.length); \/\/ 3 \/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u043d\u0430\u0448\u0438 \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f \u043e\u043f\u0440\u0430\u0432\u0434\u0430\u043b\u0438\u0441\u044c console.log(models2.includes(john), models2.includes(jane), models2.includes(sam)); \/\/ true true true  const johnPk = john.pk as number;  \/\/ \u0432\u044b\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u0432\u0441\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u0438\u0437 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u044d\u0448\u0430 coll.unloadAll();  const models3 = coll.peek();  \/\/ \u043a\u0430\u043a \u0438 \u043e\u0436\u0438\u0434\u0430\u043b\u043e\u0441\u044c, \u043d\u0438\u0447\u0435\u0433\u043e \u0432 \u043a\u044d\u0448\u0435 \u043d\u0435\u0442 console.log(models3.length); \/\/ 0  \/\/ \u0432\u0441\u0435 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b \u043e\u0441\u0432\u043e\u0431\u043e\u0436\u0434\u0435\u043d\u044b console.log(john.instanceDestroyed); \/\/ true console.log(jane.instanceDestroyed); \/\/ true console.log(sam.instanceDestroyed); \/\/ true  \/\/ \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430, \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0442\u0430\u043a\u0436\u0435 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0444\u0438\u043b\u044c\u0442\u0440, \u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \/\/ \u043d\u043e \u0438\u0445 \u043f\u0440\u0438\u043c\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 \u043d\u0438\u0436\u0435 const john2 = await coll.findOne(johnPk, { localFilter: data => Number(data.age) > 20 });  if (!john2) {   console.error('loading failed');   coll.destroy();   storage.clear();   return; }  \/\/ \u043a\u0430\u043a \u0438 \u043e\u0436\u0438\u0434\u0430\u043b\u043e\u0441\u044c, \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b \u043d\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442, \u043d\u043e \u043c\u043e\u0434\u0435\u043b\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u043b\u0430\u0441\u044c console.log(john === john2, JSON.stringify(john2.data)); \/\/ false {\"id\":1,\"name\":\"John\",\"age\":\"25\"}  const models4 = await coll.find({   \/\/ \u0437\u0430\u0434\u0430\u0434\u0438\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0437\u0430\u043f\u0440\u043e\u0441\u0430   queryParams: {     ids: [1, 2, 3, 4]   },   reload: false, \/\/ \u0432\u043e\u0437\u0432\u0440\u0430\u0442\u0438\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u044d\u0448\u0430, \u0435\u0441\u043b\u0438 \u0445\u043e\u0442\u044f \u0431\u044b \u043e\u0434\u0438\u043d \u044d\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0443\u0434\u043e\u0432\u043b\u0435\u0442\u0432\u043e\u0440\u0438\u0442 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u043c\u0443 \u0444\u0438\u043b\u044c\u0442\u0440\u0443   localFilter: data => Number(data.age) > 19 });  \/\/ \u0442\u0430\u043a \u043a\u0430\u043a john \u0443\u0436\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d \u0438 \u0443\u043a\u0430\u0437\u0430\u043d \u0444\u043b\u0430\u0433 `reload: false`, \u0442\u043e \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043e\u0441\u0442\u0430\u043d\u0435\u0442\u0441\u044f \u043d\u0435\u0442\u0440\u043e\u043d\u0443\u0442\u043d\u044b\u043c console.log(models4.length, models4.includes(john2), models4.includes(jane), models4.includes(sam)); \/\/ 1 true false false  \/\/ \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u0432\u0441\u0435 \u0437\u0430\u043d\u043e\u0432\u043e, \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0444\u043b\u0430\u0433\u0430 `force` \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u0447\u0438\u0449\u0430\u0435\u043c \u0437\u0430\u043c\u0435\u043d\u0435\u043d\u043d\u044b\u0435 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b const models5 = await coll.find({ force: true });  \/\/ \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440, \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0439 \u043d\u0430 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u043c \u044d\u0442\u0430\u043f\u0435, \u043e\u0447\u0438\u0449\u0435\u043d console.log(models4[0].instanceDestroyed); \/\/ true  \/\/ \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043e 3 \u043d\u043e\u0432\u044b\u0445 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 console.log(models5.length); \/\/ 3  \/\/ \u0432\u044b\u0434\u0435\u043b\u044f\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0438\u0437 \u043c\u0430\u0441\u0441\u0438\u0432\u0430, \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u044b\u0439 \u043a\u043b\u044e\u0447 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u043b\u0441\u044f const john5 = models5.find(m => m.pk === johnPk); const jane5 = models5.find(m => m.data.name === 'Jane'); const sam5 = models5.find(m => m.data.name === 'Samantha');  if (!john5 || !jane5 || !sam5) {   console.error('some model was not loaded');   coll.destroy();   storage.clear();   return; }  \/\/ \u043f\u043e\u0432\u044b\u0441\u0438\u043c \u0432\u043e\u0437\u0440\u0430\u0441\u0442 Samantha sam5.data.age = '20';  \/\/ \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 await sam5.save();  \/\/ \u0443\u0434\u0430\u043b\u044f\u0435\u043c Jane jane5.delete(); await jane5.save();  \/\/ \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435, \u043d\u043e \u0438 \u0441\u0430\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0431\u044b\u043b \u043e\u0441\u0432\u043e\u0431\u043e\u0436\u0434\u0435\u043d \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 console.log(jane5.destroyed, jane5.instanceDestroyed); \/\/ true true  \/\/ \u0432\u044b\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u0432\u0441\u0435 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b \u043c\u043e\u0434\u0435\u043b\u0435\u0439 coll.unloadAll();  \/\/ \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u043c\u043e\u0434\u0435\u043b\u0438 \u043f\u043e \u043d\u043e\u0432\u043e\u0439 const models6 = await coll.find({ localFilter: data => Number(data.age) > 19 });  \/\/ \u0442\u0430\u043a \u043a\u0430\u043a Jane \u0443\u0436\u0435 \u0443\u0434\u0430\u043b\u0435\u043d\u0430, \u0442\u043e \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u043d\u0435\u0442 console.log(models6.length); \/\/ 2 \/\/ \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u044f\u0435\u043c\u0441\u044f, \u0447\u0442\u043e John \u0438 Samantha \u043d\u0430\u0439\u0434\u0435\u043d\u044b console.log(JSON.stringify(models6.find(m => m.data.name === 'John')!.data)); \/\/ {\"id\":1,\"name\":\"John\",\"age\":\"25\"} console.log(JSON.stringify(models6.find(m => m.data.name === 'Samantha')!.data)); \/\/ {\"id\":3,\"name\":\"Samantha\",\"age\":\"20\"}  \/\/ \u043e\u0447\u0438\u0449\u0430\u0435\u043c \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044e coll.destroy(); \/\/ \u043e\u0447\u0438\u0449\u0430\u0435\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 storage.clear(); <\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041f\u043e\u0436\u0430\u043b\u0443\u0439, \u044d\u0442\u043e \u0432\u0441\u0435, \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043e \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f\u0445 \u043d\u0430 \u0441\u0435\u0433\u043e\u0434\u043d\u044f\u0448\u043d\u0438\u0439 \u0434\u0435\u043d\u044c. \u041d\u0438\u043a\u0430\u043a\u043e\u0439 \u043c\u0430\u0433\u0438\u0438, \u0432\u0441\u0435 \u0440\u0435\u0448\u0430\u0435\u0442 \u0441\u0430\u043c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a.<\/p>\n<h3>\u041a\u043b\u0430\u0441\u0441 \u0438 \u0441\u0435\u0440\u0432\u0438\u0441 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430<\/h3>\n<p>\u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u043b\u0438\u0448\u044c \u0434\u0432\u0430 \u043a\u043b\u0430\u0441\u0441\u0430 \u0432 \u043f\u0430\u043a\u0435\u0442\u0435, \u043e\u0431\u0430 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u0441\u043e\u0431\u043e\u0439 \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0434\u043b\u044f \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439. \u041e\u0434\u0438\u043d \u0438\u0437 \u043d\u0438\u0445 (<code>StoreService<\/code>) \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0441\u0435\u0440\u0432\u0438\u0441 \u0434\u043b\u044f <code>@vueent\/core<\/code>, \u0430 \u0432\u0442\u043e\u0440\u043e\u0439 (<code>Store<\/code>) \u2014 \u043f\u0440\u043e\u0441\u0442\u043e \u043a\u043b\u0430\u0441\u0441. \u041e\u0431\u0430 \u0438\u043c\u0435\u044e\u0442 \u043e\u0434\u0438\u043d \u043b\u0438\u0448\u044c \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 <code>get<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044e \u043f\u043e \u0438\u043c\u0435\u043d\u0438 \u043a\u043b\u0430\u0441\u0441\u0430. \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u0443\u044e \u043d\u0430\u043c\u0438 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044e:<\/p>\n<pre><code class=\"typescript\">import { Store } from '@vueent\/store';  import * as storage from '@\/storage'; import { SimpleCollection } from '@\/collections\/simple';  \/\/ \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043a\u043b\u0430\u0441\u0441\u0430 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 const store = new Store([new SimpleCollection()]);  \/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 \u0438 \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043c\u043e\u0434\u0435\u043b\u0438 const jane = store.get(SimpleCollection).create();  jane.data.name = 'Jane'; jane.data.age = '20';  await jane.save();  console.log(JSON.stringify(jane.data)); \/\/ {\"id\":1,\"name\":\"Jane\",\"age\":\"20\"}  store.get(SimpleCollection).destroy(); storage.clear();<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u043f\u043e\u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0438\u0437 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0442\u0443 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432 \u043d\u0435\u043c \u043d\u0435 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0430, \u0442\u043e TypeScript \u0432\u044b\u0434\u0430\u0441\u0442 \u043e\u0448\u0438\u0431\u043a\u0443:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d7b\/9c3\/e4b\/d7b9c3e4b52b981f25ee56b0c2c01c4e.png\" alt=\"\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043f\u043e\u043f\u044b\u0442\u043a\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0439 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438\" title=\"\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043f\u043e\u043f\u044b\u0442\u043a\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0439 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438\" width=\"841\" height=\"391\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d7b\/9c3\/e4b\/d7b9c3e4b52b981f25ee56b0c2c01c4e.png\"\/><figcaption>\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043f\u043e\u043f\u044b\u0442\u043a\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0439 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438<\/figcaption><\/figure>\n<p>\u0415\u0441\u043b\u0438 \u0436\u0435 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f \u0438\u0437 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0430 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e, \u0442\u043e \u043c\u043e\u0436\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043c\u043e\u0434\u0435\u043b\u0438:<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/067\/323\/a34\/067323a34ff0324eac2a7d3f0ede4eb9.png\" alt=\"\u0410\u0432\u0442\u043e\u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0441 \u0443\u0447\u0435\u0442\u043e\u043c \u0442\u0438\u043f\u0430 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 \u043c\u043e\u0434\u0435\u043b\u0438\" title=\"\u0410\u0432\u0442\u043e\u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0441 \u0443\u0447\u0435\u0442\u043e\u043c \u0442\u0438\u043f\u0430 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 \u043c\u043e\u0434\u0435\u043b\u0438\" width=\"518\" height=\"154\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/067\/323\/a34\/067323a34ff0324eac2a7d3f0ede4eb9.png\"\/><figcaption>\u0410\u0432\u0442\u043e\u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0441 \u0443\u0447\u0435\u0442\u043e\u043c \u0442\u0438\u043f\u0430 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 \u043c\u043e\u0434\u0435\u043b\u0438<\/figcaption><\/figure>\n<p>\u0415\u0441\u043b\u0438 \u043a\u043b\u0430\u0441\u0441 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0442\u0438\u043f\u043e\u0432, \u0442\u043e \u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u0442\u0430\u043a\u043e\u0433\u043e \u0436\u0435 \u044d\u0444\u0444\u0435\u043a\u0442\u0430 \u0434\u043b\u044f \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u043c\u043d\u0435 \u043f\u043e\u043a\u0430 \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c, \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u044f\u0442\u044c \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438:<\/p>\n<pre><code class=\"typescript\">import { StoreService as VueentStoreService } from '@vueent\/store';  import { registerService } from '@\/vueent'; import { TrivialCollection } from '@\/collections\/trivial'; import { SimpleCollection } from '@\/collections\/simple';  \/\/ \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u044f\u0432\u043d\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0435 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 export default class StoreService extends VueentStoreService&lt;SimpleCollection | TrivialCollection> {   constructor() {     super([new SimpleCollection(), new TrivialCollection()]);   } }  registerService(StoreService);<\/code><\/pre>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044e \u043a\u043b\u0430\u0441\u0441\u0430, \u0435\u0433\u043e \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0432 \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 \u0438\u043b\u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 (<code>injectService<\/code>), \u043b\u0438\u0431\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>useService<\/code>:<\/p>\n<pre><code class=\"typescript\">import { useService } from '@\/vueent'; import * as storage from '@\/storage'; import StoreService from '@\/services\/store'; import { SimpleCollection } from '@\/collections\/simple';  \/\/ \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0441\u0435\u0440\u0432\u0438\u0441 \u0447\u0435\u0440\u0435\u0437 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u044f\u0434\u0440\u0430 const store = useService(StoreService); \/\/ \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0430 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u043a\u043b\u0430\u0441\u0441\u043e\u043c `Store` const jane = store.get(SimpleCollection).create();  jane.data.name = 'Jane'; jane.data.age = '20';  await jane.save();  console.log(JSON.stringify(jane.data)); \/\/ {\"id\":1,\"name\":\"Jane\",\"age\":\"20\"}  store.get(SimpleCollection).destroy(); storage.clear();<\/code><\/pre>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u0438\u0442\u0435, \u043d\u0438\u0447\u0435\u0433\u043e \u0441\u043b\u043e\u0436\u043d\u043e\u0433\u043e. \u0412\u0441\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u044c\u044e \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0432 <a href=\"https:\/\/github.com\/Devoter\/vueent-article\" rel=\"noopener noreferrer nofollow\">\u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435<\/a>.<\/p>\n<h3>\u0418\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f<\/h3>\n<ul>\n<li>\n<p>\u041d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u043f\u0440\u043e\u0435\u043a\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043b\u0441\u044f \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u043e\u0442\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u043d\u044b\u043c \u043e\u0442 \u0441\u0430\u043c\u043e\u0433\u043e Vue, \u043f\u043e\u043a\u0430 \u0435\u0449\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u043e\u0433\u043e Vue \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u0445, \u0442\u0430\u043a \u043a\u0430\u043a \u043f\u0430\u043a\u0435\u0442 <a href=\"https:\/\/github.com\/vuejs\/core\/tree\/main\/packages\/reactivity#readme\" rel=\"noopener noreferrer nofollow\">@vue\/reactivity<\/a> \u043d\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 watch, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439 \u0434\u043b\u044f \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439. \u0411\u0435\u0437 \u044d\u0442\u043e\u0439 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0431\u044b \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0432 React, \u0445\u043e\u0442\u044f, \u043a\u0430\u0436\u0435\u0442\u0441\u044f, React-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u0432 \u044d\u0442\u043e\u0442 \u043c\u043e\u043c\u0435\u043d\u0442 \u043f\u043e\u043f\u0435\u0440\u0445\u043d\u0443\u043b\u0438\u0441\u044c. \u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0442 \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0433\u043e <code>watch<\/code>, \u043d\u043e \u0437\u0430\u0434\u0430\u0447\u0443 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0441 \u043a\u0430\u043a\u0438\u043c-\u043b\u0438\u0431\u043e \u0438\u0437 \u043d\u0438\u0445 \u0435\u0449\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u043e\u0438\u0442 \u0440\u0435\u0448\u0438\u0442\u044c.<\/p>\n<\/li>\n<li>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0437\u0430\u0442\u0430\u0447\u0438\u0432\u0430\u043b\u0430\u0441\u044c, \u043f\u0440\u0435\u0436\u0434\u0435 \u0432\u0441\u0435\u0433\u043e, \u043f\u043e\u0434 \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438 \u0444\u043e\u0440\u043c\u0430\u043c\u0438 \u0432 \u043a\u0430\u043a\u0438\u0445-\u043d\u0438\u0431\u0443\u0434\u044c \u0430\u0434\u043c\u0438\u043d\u043a\u0430\u0445, CRM- \u0438\u043b\u0438 ERP-\u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0445, \u0442\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0433\u043e \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 \u043d\u0435 \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u043b\u0430\u0441\u044c \u043a\u0430\u043a \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u043d\u043e\u0435 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0438 \u043d\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043b\u043e\u0441\u044c. \u0421\u043b\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u043a\u0430\u043a\u043e\u0439 \u043e\u0431\u044a\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u043d\u0435\u0441\u0442\u0438 \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 SSR.<\/p>\n<\/li>\n<li>\n<p>\u041c\u043d\u043e\u0433\u043e\u0441\u043b\u043e\u0432\u043d\u043e\u0441\u0442\u044c \u2014 \u0446\u0435\u043d\u0430 \u0437\u0430 \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c \u0438 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u043c\u0430\u0433\u0438\u0438. \u0424\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438, \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u043d\u0430 \u0442\u043e\u043c \u0443\u0440\u043e\u0432\u043d\u0435, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043f\u043e\u0436\u0435\u043b\u0430\u0435\u0442. \u041c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u0435\u043a\u043e\u0440\u0430\u0442\u043e\u0440\u044b \u0434\u043b\u044f \u043a\u0430\u043a\u0438\u0445-\u0442\u043e \u0443\u0442\u0438\u043b\u0438\u0442\u0430\u0440\u043d\u044b\u0445 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043d\u0430 Vue, \u0438\u043b\u0438 \u0436\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u043c\u043e\u0434\u0435\u043b\u0438 \u0431\u0435\u0437 \u0432\u0441\u0435\u0433\u043e \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0433\u043e, \u0432 \u043a\u043e\u043d\u0446\u0435-\u043a\u043e\u043d\u0446\u043e\u0432, \u0441\u043e\u0447\u0435\u0442\u0430\u043d\u0438\u0435 <code>@vueent\/core<\/code> \u0438 <a href=\"https:\/\/pinia.vuejs.org\/\" rel=\"noopener noreferrer nofollow\">Pinia<\/a> \u0442\u0430\u043a\u0436\u0435 \u0432\u043f\u043e\u043b\u043d\u0435 \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430 \u043c\u043e\u043c\u0435\u043d\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u043a\u043e\u0434\u043e\u0432\u043e\u0439 \u0431\u0430\u0437\u044b, \u0442\u0430\u043a\u0438\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043a\u0430\u043a <a href=\"https:\/\/vuelidate.js.org\/\" rel=\"noopener noreferrer nofollow\">Vuelidate<\/a> \u0438 <a href=\"https:\/\/vee-validate.logaretm.com\" rel=\"noopener noreferrer nofollow\">VeeValidate<\/a> \u043d\u0435 \u0438\u043c\u0435\u043b\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u043d\u0438 Vue 3, \u043d\u0438 Composition API. \u0422\u0435\u043c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435, \u0441\u0442\u043e\u0438\u0442 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u0447\u0442\u043e VueEnt \u043e\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0431\u043e\u043b\u044c\u0448\u0438\u0439 \u0441\u043f\u0435\u043a\u0442\u0440 \u0437\u0430\u0434\u0430\u0447, \u0447\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0435 \u0432\u044b\u0448\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b, \u0434\u0430 \u0438 \u0434\u043b\u044f \u0441\u0430\u043c\u0438\u0445 \u0446\u0435\u043f\u043e\u0447\u0435\u043a \u043f\u0440\u0430\u0432\u0438\u043b \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043b\u044e\u0431\u0443\u044e \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u044e\u044e \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u2014 \u0432 \u044d\u0442\u043e\u043c \u043f\u043b\u0430\u043d\u0435 VueEnt \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0438\u043d\u043e\u0439 \u043f\u043b\u043e\u0441\u043a\u043e\u0441\u0442\u0438.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0436\u0430\u043b\u0443\u0439, \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043e\u0431\u043b\u0430\u0434\u0430\u0435\u0442 \u043a\u0440\u0443\u0442\u043e\u0432\u0430\u0442\u043e\u0439 \u043a\u0440\u0438\u0432\u043e\u0439 \u043f\u043e\u0440\u043e\u0433\u0430 \u0432\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f, \u043d\u043e \u044f \u043e\u0447\u0435\u043d\u044c \u043d\u0430\u0434\u0435\u044e\u0441\u044c, \u0447\u0442\u043e \u044d\u0442\u0430 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0441\u0433\u043b\u0430\u0434\u0438\u0442\u044c \u0443\u0433\u043e\u043b.<\/p>\n<\/li>\n<\/ul>\n<h3>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0434\u043e\u0447\u0438\u0442\u0430\u043b\u0438 \u0434\u043e \u044d\u0442\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438, \u0442\u043e \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u044b\u0440\u0430\u0437\u0438\u0442\u044c \u043c\u043e\u0435 \u043e\u0433\u0440\u043e\u043c\u043d\u043e\u0435 \u043f\u043e\u0447\u0442\u0435\u043d\u0438\u0435 \u0438 \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u043d\u043e\u0441\u0442\u044c \u0437\u0430 \u043f\u043e\u0442\u0440\u0430\u0447\u0435\u043d\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f. \u0418\u0441\u043a\u0440\u0435\u043d\u043d\u0435 \u043d\u0430\u0434\u0435\u044e\u0441\u044c, \u0447\u0442\u043e \u044d\u0442\u043e \u2014 \u043d\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044f\u044f \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u043f\u0440\u043e \u0434\u0430\u043d\u043d\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443, \u0442\u0430\u043a \u043a\u0430\u043a \u0435\u0449\u0435 \u0435\u0441\u0442\u044c \u0447\u0442\u043e \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c. \u041f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u044c \u0432 \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u0432 \u043d\u0430\u0448\u0435\u0439 \u0442\u043e\u0433\u0434\u0430 \u0435\u0449\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u0435 \u0432 \u0441\u0432\u044f\u0437\u0438 \u0441 \u0440\u043e\u0441\u0442\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0430: \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043a\u043e\u0434\u043e\u0432\u043e\u0439 \u0431\u0430\u0437\u043e\u0439 \u0441\u0442\u0430\u043b\u043e \u043a\u0440\u0430\u0439\u043d\u0435 \u0442\u044f\u0436\u0435\u043b\u043e, \u0430 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442, \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u0438\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043d\u0435 \u043d\u0430 \u0432\u0441\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443, \u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u044c\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u044f\u0435\u043c\u043e\u0439 \u0435\u0435 \u0447\u0430\u0441\u0442\u0438, \u0440\u0430\u0437\u0431\u0438\u0432\u0430\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043d\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0431\u0435\u0437 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0438 \u0432 \u043d\u0438\u0445, \u043f\u043e \u043c\u0430\u043a\u0441\u0438\u043c\u0443\u043c\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u0435\u043a\u043b\u0430\u0440\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u0441\u0442\u0438\u043b\u044c, \u0432 \u043a\u043e\u043d\u0446\u0435-\u043a\u043e\u043d\u0446\u043e\u0432, \u0438\u043c\u0435\u0442\u044c \u0435\u0434\u0438\u043d\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u041a\u0442\u043e-\u0442\u043e \u0441\u043a\u0430\u0436\u0435\u0442, \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u0432\u0441\u0435\u0445 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0445 \u0446\u0435\u043b\u0435\u0439 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0443\u0436\u0435 \u0438\u043c\u0435\u0432\u0448\u0438\u0445\u0441\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a \u0438 \u043f\u043e\u0434\u0445\u043e\u0434\u043e\u0432, \u043b\u0438\u0448\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0438\u0432 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0434\u043e\u043b\u044e \u0441\u0430\u043c\u043e\u0434\u0438\u0441\u0446\u0438\u043f\u043b\u0438\u043d\u044b. \u042f \u043e\u0442\u0432\u0435\u0447\u0443: \u0434\u0430, \u043c\u043e\u0436\u043d\u043e, \u0431\u043e\u043b\u0435\u0435 \u0442\u043e\u0433\u043e, \u043c\u044b \u0438 \u043f\u044b\u0442\u0430\u043b\u0438\u0441\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u0430\u043a, \u043d\u043e \u043f\u043e\u0441\u0442\u0435\u043f\u0435\u043d\u043d\u043e \u043e\u0431\u044a\u0435\u043c \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u043e\u043a \u0438 \u043f\u0440\u0430\u0432\u0438\u043b \u0441\u0442\u0430\u043b \u0432\u0441\u0435 \u0431\u043e\u043b\u044c\u0448\u0435 \u043f\u043e\u0445\u043e\u0434\u0438\u0442\u044c \u043d\u0430 \u043a\u043e\u043d\u0446\u0435\u043f\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u0438 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432 \u0438\u0442\u043e\u0433\u0435 \u0438 \u0432\u043e\u043f\u043b\u043e\u0442\u0438\u043b\u0441\u044f \u0432\u043e VueEnt. \u041c\u043d\u0435 \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f Vue, \u044f, \u043d\u0435 \u0431\u0435\u0437 \u0434\u043e\u043b\u0438 \u0438\u0440\u043e\u043d\u0438\u0438, \u043d\u0430\u0437\u044b\u0432\u0430\u044e \u0435\u0433\u043e <em>React \u0437\u0434\u043e\u0440\u043e\u0432\u043e\u0433\u043e \u0447\u0435\u043b\u043e\u0432\u0435\u043a\u0430<\/em>, \u043d\u043e \u0438 Vue, \u0438 React \u043d\u0435 \u0434\u0430\u044e\u0442 \u0442\u043e\u0433\u043e \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u043e\u0433\u043e \u043a\u0430\u0440\u043a\u0430\u0441\u0430, \u0447\u0442\u043e \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e\u0442 Angular \u0438 Ember. \u0418, \u043f\u0443\u0441\u043a\u0430\u0439 \u044d\u0442\u043e \u0437\u0432\u0443\u0447\u0438\u0442 \u043d\u0435\u043b\u0435\u043f\u043e, \u043c\u043d\u0435 \u0431\u044b \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c, \u0447\u0442\u043e\u0431\u044b \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 VueEnt \u0441\u0442\u0430\u043b\u0430 \u043c\u043e\u0441\u0442\u0438\u043a\u043e\u043c \u043c\u0435\u0436\u0434\u0443 \u0445\u0438\u043f\u0441\u0442\u0435\u0440\u0430\u043c\u0438, \u0432\u044b\u0431\u0440\u0430\u0432\u0448\u0438\u043c\u0438 Vue, \u043a\u0440\u043e\u0432\u0430\u0432\u044b\u043c \u044d\u043d\u0442\u0435\u0440\u043f\u0440\u0430\u0439\u0437\u043e\u043c \u0441 Angular \u0432\u043e \u0433\u043b\u0430\u0432\u0435. \u0421\u043f\u0430\u0441\u0438\u0431\u043e \u0437\u0430 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435.<\/p>\n<p>\u0425\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u0432\u044b\u0440\u0430\u0437\u0438\u0442\u044c \u043e\u0441\u043e\u0431\u0443\u044e \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u043d\u043e\u0441\u0442\u044c \u0414\u0430\u043d\u0438\u0438\u043b\u0443 \u043a\u0430\u043a \u0441\u043e\u0430\u0432\u0442\u043e\u0440\u0443 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u043d\u0430 \u0440\u0430\u043d\u043d\u0435\u043c \u044d\u0442\u0430\u043f\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0418\u043b\u044c\u0435, \u0431\u0435\u0437 \u043f\u0440\u0430\u0432\u043e\u043a \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u044d\u0442\u0430 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u0438 \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0435 \u0431\u044b\u043b\u0438 \u0431\u044b \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b \u0432 \u0442\u043e\u043c \u0432\u0438\u0434\u0435, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043e\u043d\u0438 \u0435\u0441\u0442\u044c \u0441\u0435\u0439\u0447\u0430\u0441.<\/p>\n<h3>\u0421\u0441\u044b\u043b\u043a\u0438<\/h3>\n<ul>\n<li>\n<p><a href=\"https:\/\/vueent.github.io\/vueent\" rel=\"noopener noreferrer nofollow\">VueEnt<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/vueent.github.io\/v9s\" rel=\"noopener noreferrer nofollow\">v9s<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/vueent\/v9sx\" rel=\"noopener noreferrer nofollow\">v9sx<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/vueent\/vueent-quick-start\" rel=\"noopener noreferrer nofollow\">\u0411\u044b\u0441\u0442\u0440\u044b\u0439 \u0441\u0442\u0430\u0440\u0442<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/Devoter\/vueent-article\" rel=\"noopener noreferrer nofollow\">\u041f\u0440\u0438\u043c\u0435\u0440\u044b \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u044c\u044e<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/vueent\/vueent-example\" rel=\"noopener noreferrer nofollow\">\u041f\u0440\u0438\u043c\u0435\u0440 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441\u043e \u0441\u043b\u043e\u0436\u043d\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u044c\u044e, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0432\u0441\u0435\u0445 \u043f\u0430\u043a\u0435\u0442\u043e\u0432 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438 \u0440\u0430\u0437\u0431\u0438\u0435\u043d\u0438\u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u043d\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0435 \u0441 \u043e\u0434\u043d\u0438\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u043e\u043c \u043c\u043e\u0434\u0435\u043b\u0438<\/a><\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/div>\n<\/div>\n<p> <!----> <!----><\/div>\n<p> <!----> <\/p>\n<div class=\"tm-article-poll\">\n<div class=\"tm-notice tm-article-poll__notice tm-notice_positive\"><!----> <\/p>\n<div class=\"tm-notice__inner\"><!----> <\/p>\n<div class=\"tm-notice__content\"><span>\u0422\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u043c\u043e\u0433\u0443\u0442 \u0443\u0447\u0430\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0432 \u043e\u043f\u0440\u043e\u0441\u0435. <a rel=\"nofollow\" href=\"\/kek\/v1\/auth\/habrahabr\/?back=\/ru\/post\/717680\/&#038;hl=ru\">\u0412\u043e\u0439\u0434\u0438\u0442\u0435<\/a>, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430.<\/span><\/div>\n<\/div>\n<\/div>\n<div class=\"tm-article-poll__header\">\u0418\u043d\u0442\u0435\u0440\u0435\u0441\u0435\u043d \u043b\u0438 \u0432\u0430\u043c \u0434\u0430\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442?<\/div>\n<div class=\"tm-article-poll__answers\">\n<div class=\"tm-article-poll__answer\">\n<div class=\"tm-article-poll__answer-data\"><span class=\"tm-article-poll__answer-percent tm-article-poll__answer-percent_winning\">             100%           <\/span> <span class=\"tm-article-poll__answer-label\">\u0414\u0430<\/span> <span class=\"tm-article-poll__answer-votes\">             1           <\/span><\/div>\n<div class=\"tm-article-poll__answer-bar\">\n<div class=\"tm-article-poll__answer-progress tm-article-poll__answer-progress_winning\" style=\"width:100%;\"><\/div>\n<\/div>\n<\/div>\n<div class=\"tm-article-poll__answer\">\n<div class=\"tm-article-poll__answer-data\"><span class=\"tm-article-poll__answer-percent\">             0%           <\/span> <span class=\"tm-article-poll__answer-label\">\u0417\u0430\u043a\u043e\u043f\u0430\u0439\u0442\u0435 \u0443\u0436\u0435 \u0441\u0442\u044e\u0430\u0440\u0434\u0435\u0441\u0441\u0443<\/span> <span class=\"tm-article-poll__answer-votes\">             0           <\/span><\/div>\n<div class=\"tm-article-poll__answer-bar\">\n<div class=\"tm-article-poll__answer-progress\" style=\"width:0%;\"><\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"tm-article-poll__stats\">        \u041f\u0440\u043e\u0433\u043e\u043b\u043e\u0441\u043e\u0432\u0430\u043b 1 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c.          \u0412\u043e\u0437\u0434\u0435\u0440\u0436\u0430\u043b\u0441\u044f 1 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c.      <\/div>\n<\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/717680\/\"> https:\/\/habr.com\/ru\/post\/717680\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u043f\u043e\u043b\u0442\u043e\u0440\u0430 \u0433\u043e\u0434\u0430 \u043d\u0430\u0437\u0430\u0434 \u0432\u044b\u0448\u043b\u0430 \u043c\u043e\u044f <a href=\"https:\/\/habr.com\/ru\/post\/574044\/\" rel=\"noopener noreferrer nofollow\">\u0441\u0442\u0430\u0442\u044c\u044f<\/a> \u043f\u0440\u043e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 <a href=\"https:\/\/vueent.github.io\/v9s\" rel=\"noopener noreferrer nofollow\">v9s<\/a>. \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u043a\u0440\u0438\u0442\u0438\u043a\u0435 \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445, \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0441\u0435\u0440\u044c\u0435\u0437\u043d\u043e \u043f\u0435\u0440\u0435\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443, \u0443\u0436\u0435 \u0433\u043e\u0434 \u043a\u0430\u043a \u0432\u044b\u0448\u043b\u0430 \u0432\u0442\u043e\u0440\u0430\u044f \u0431\u043e\u043b\u0435\u0435 \u0434\u0440\u0443\u0436\u0435\u043b\u044e\u0431\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f. \u0412 \u0442\u0435\u043a\u0441\u0442\u0435 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0431\u044b\u043b\u043e \u0441\u043a\u0430\u0437\u0430\u043d\u043e \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0442\u044c \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0438 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0444\u043e\u0440\u043c \u043d\u0430 <a href=\"https:\/\/vuejs.org\/\" rel=\"noopener noreferrer nofollow\">Vue<\/a>, \u0430 \u0435\u0449\u0435 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0438\u043d\u0434\u0438\u043a\u0430\u0446\u0438\u044e \u043a \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c \u0447\u0430\u0441\u0442\u044f\u043c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445. \u041f\u043e\u0441\u043b\u0435 \u0441\u0435\u0440\u0438\u0438 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u043e\u0432 \u0441\u043b\u043e\u0436\u0438\u043b\u0441\u044f \u043e\u0431\u0449\u0438\u0439 \u043a\u043e\u043d\u0446\u0435\u043f\u0442 \u043d\u043e\u0432\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438 \u043d\u0435\u0441\u043a\u0440\u043e\u043c\u043d\u043e\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 <code>VueEnt<\/code>, \u043d\u0430\u043c\u0435\u043a\u0430\u044e\u0449\u0435\u0435 \u043d\u0430 \u0441\u0444\u0435\u0440\u0443 \u0435\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f. \u0418\u0442\u0430\u043a, \u0435\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u044e\u0442 \u0442\u0435 \u0436\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043d\u0430 Vue, \u0447\u0442\u043e \u0438\u0437\u043b\u043e\u0436\u0435\u043d\u044b \u0432 \u043c\u043e\u0435\u0439 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435 \u0432\u044b\u0448\u0435, \u0442\u043e \u0437\u0430\u0432\u0430\u0440\u0438\u0442\u0435 \u0447\u0430\u0439\u043a\u0443 \u0438 \u043f\u0440\u0438\u0433\u043e\u0442\u043e\u0432\u044c\u0442\u0435 \u0431\u0443\u0442\u0435\u0440\u0431\u0440\u043e\u0434\u044b, \u0432\u0435\u0434\u044c, \u043d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u043e\u0431\u0437\u043e\u0440\u043d\u044b\u0439 \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438, \u0432 \u0434\u0432\u0443\u0445 \u0441\u043b\u043e\u0432\u0430\u0445 \u0432\u0441\u0435 \u043d\u0435 \u043e\u043f\u0438\u0441\u0430\u0442\u044c.<\/p>\n<p>\u0418\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0440\u0430\u0437\u0431\u0438\u0442\u044c \u0442\u0435\u043a\u0441\u0442 \u043d\u0430 \u0442\u0440\u0438 \u0447\u0430\u0441\u0442\u0438, \u043d\u043e \u0432\u044b\u0445\u043e\u0434\u0438\u0442 \u0442\u0430\u043a, \u0447\u0442\u043e \u0441\u0430\u043c\u0430\u044f \u0432\u0430\u0436\u043d\u0430\u044f \u0438 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u2014 \u0441\u0430\u043c\u0430\u044f \u043e\u0431\u044a\u0435\u043c\u043d\u0430\u044f, \u0431\u0435\u0437 \u043d\u0435\u0435 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0432\u044b\u0433\u043b\u044f\u0434\u044f\u0442 \u043d\u0435\u0437\u043d\u0430\u0447\u0438\u043c\u044b\u043c\u0438 \u043f\u0440\u0438\u0434\u0430\u0442\u043a\u0430\u043c\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u0430\u043c\u044b\u043c \u043d\u0435\u0442\u0435\u0440\u043f\u0435\u043b\u0438\u0432\u044b\u043c \u043c\u043e\u0433\u0443 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0438\u0442\u044c \u043f\u0440\u043e\u0439\u0442\u0438 \u0432 \u043a\u043e\u043d\u0435\u0446 \u043a <a href=\"#%D1%81%D1%81%D1%8B%D0%BB%D0%BA%D0%B8\" rel=\"noopener noreferrer nofollow\">\u0441\u0441\u044b\u043b\u043a\u0430\u043c<\/a>, \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0443 \u0441\u0435\u0431\u044f \u043d\u0430 \u041f\u041a \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0438 <em>\u043f\u043e\u0449\u0443\u043f\u0430\u0442\u044c<\/em> \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u0443\u044e \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0443\u044e.<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<h3>\u0421\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435<\/h3>\n<ol>\n<li>\n<p><a href=\"#%D1%86%D0%B5%D0%BB%D1%8C-%D0%BF%D1%83%D0%B1%D0%BB%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8\" rel=\"noopener noreferrer nofollow\">\u0426\u0435\u043b\u044c \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D0%BE%D1%87%D0%B5%D0%BD%D1%8C-%D1%81%D0%B6%D0%B0%D1%82%D0%BE%D0%B5-%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5-%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B0\" rel=\"noopener noreferrer nofollow\">\u041e\u0447\u0435\u043d\u044c \u0441\u0436\u0430\u0442\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/a> <\/p>\n<ol>\n<li>\n<p><a href=\"#%D0%BE%D1%81%D0%BD%D0%BE%D0%B2%D0%BD%D0%B0%D1%8F-%D1%86%D0%B5%D0%BB%D1%8C-%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B0\" rel=\"noopener noreferrer nofollow\">\u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0446\u0435\u043b\u044c \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D0%BD%D0%B5-%D1%8F%D0%B2%D0%BB%D1%8F%D1%8E%D1%82%D1%81%D1%8F-%D1%86%D0%B5%D0%BB%D1%8F%D0%BC%D0%B8\" rel=\"noopener noreferrer nofollow\">\u041d\u0435 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0446\u0435\u043b\u044f\u043c\u0438<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D1%81%D0%BF%D0%B8%D1%81%D0%BE%D0%BA-%D0%BF%D0%B0%D0%BA%D0%B5%D1%82%D0%BE%D0%B2-%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B0\" rel=\"noopener noreferrer nofollow\">\u0421\u043f\u0438\u0441\u043e\u043a \u043f\u0430\u043a\u0435\u0442\u043e\u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/a> <\/p>\n<ol>\n<li>\n<p><a href=\"#reactive\" rel=\"noopener noreferrer nofollow\">Reactive<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#core\" rel=\"noopener noreferrer nofollow\">Core<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#mix-models\" rel=\"noopener noreferrer nofollow\">Mix Models<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#store\" rel=\"noopener noreferrer nofollow\">Store<\/a><\/p>\n<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<\/li>\n<li>\n<p><a href=\"#%D0%B1%D1%8B%D1%81%D1%82%D1%80%D1%8B%D0%B9-%D1%81%D1%82%D0%B0%D1%80%D1%82\" rel=\"noopener noreferrer nofollow\">\u0411\u044b\u0441\u0442\u0440\u044b\u0439 \u0441\u0442\u0430\u0440\u0442<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D0%B1%D0%BE%D0%BB%D0%B5%D0%B5-%D0%B4%D0%B5%D1%82%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9-%D0%BE%D0%B1%D0%B7%D0%BE%D1%80-%D0%BF%D0%B0%D0%BA%D0%B5%D1%82%D0%BE%D0%B2-%D1%81-%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D0%B0%D0%BC%D0%B8\" rel=\"noopener noreferrer nofollow\">\u0411\u043e\u043b\u0435\u0435 \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u044b\u0439 \u043e\u0431\u0437\u043e\u0440 \u043f\u0430\u043a\u0435\u0442\u043e\u0432 \u0441 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u043c\u0438<\/a> <\/p>\n<ol>\n<li>\n<p><a href=\"#reactive-1\" rel=\"noopener noreferrer nofollow\">Reactive<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#core-1\" rel=\"noopener noreferrer nofollow\">Core<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#mix-models-1\" rel=\"noopener noreferrer nofollow\">Mix Models<\/a> <\/p>\n<ol>\n<li>\n<p><a href=\"#%D0%BF%D0%BE%D1%87%D0%B5%D0%BC%D1%83-%D0%BC%D0%B8%D0%BA%D1%81%D0%B8%D0%BD%D1%8B\" rel=\"noopener noreferrer nofollow\">\u041f\u043e\u0447\u0435\u043c\u0443 \u043c\u0438\u043a\u0441\u0438\u043d\u044b?<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B-%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D1%8F-%D0%B8-%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F\" rel=\"noopener noreferrer nofollow\">\u041f\u0440\u0438\u043c\u0435\u0440\u044b \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D0%BF%D1%80%D0%BE%D1%81%D1%82%D0%BE%D0%B9-%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80\" rel=\"noopener noreferrer nofollow\">\u041f\u0440\u043e\u0441\u0442\u043e\u0439 \u043f\u0440\u0438\u043c\u0435\u0440<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D0%BE%D1%82%D0%BA%D0%B0%D1%82-%D1%81%D0%BE%D1%81%D1%82%D0%BE%D1%8F%D0%BD%D0%B8%D1%8F\" rel=\"noopener noreferrer nofollow\">\u041e\u0442\u043a\u0430\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D1%81%D0%BE%D1%85%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5\" rel=\"noopener noreferrer nofollow\">\u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D0%B2%D0%B0%D0%BB%D0%B8%D0%B4%D0%B0%D1%86%D0%B8%D1%8F\" rel=\"noopener noreferrer nofollow\">\u0412\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D0%B4%D0%BE%D0%BF%D0%BE%D0%BB%D0%BD%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5-%D0%BF%D0%BE%D0%BB%D0%B5\" rel=\"noopener noreferrer nofollow\">\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u043f\u043e\u043b\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D1%81%D0%BB%D0%BE%D0%B6%D0%BD%D0%B0%D1%8F-%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C\" rel=\"noopener noreferrer nofollow\">\u0421\u043b\u043e\u0436\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c<\/a><\/p>\n<\/li>\n<\/ol>\n<\/li>\n<li>\n<p><a href=\"#store-1\" rel=\"noopener noreferrer nofollow\">Store<\/a> <\/p>\n<ol>\n<li>\n<p><a href=\"#%D0%BF%D1%80%D0%BE%D1%81%D1%82%D0%B0%D1%8F-%D0%BA%D0%BE%D0%BB%D0%BB%D0%B5%D0%BA%D1%86%D0%B8%D1%8F\" rel=\"noopener noreferrer nofollow\">\u041f\u0440\u043e\u0441\u0442\u0430\u044f \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D0%BA%D0%BE%D0%BB%D0%BB%D0%B5%D0%BA%D1%86%D0%B8%D1%8F-%D1%81-%D0%B4%D0%BE%D1%81%D1%82%D1%83%D0%BF%D0%BE%D0%BC-%D0%BA%D0%BE-%D0%B2%D0%BD%D0%B5%D1%88%D0%BD%D0%B5%D0%BC%D1%83-%D1%85%D1%80%D0%B0%D0%BD%D0%B8%D0%BB%D0%B8%D1%89%D1%83\" rel=\"noopener noreferrer nofollow\">\u041a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f \u0441 \u0434\u043e\u0441\u0442\u0443\u043f\u043e\u043c \u043a\u043e \u0432\u043d\u0435\u0448\u043d\u0435\u043c\u0443 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0443<\/a><\/p>\n<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<\/li>\n<li>\n<p><a href=\"#%D0%B8%D0%B7%D0%B2%D0%B5%D1%81%D1%82%D0%BD%D1%8B%D0%B5-%D0%BE%D0%B3%D1%80%D0%B0%D0%BD%D0%B8%D1%87%D0%B5%D0%BD%D0%B8%D1%8F\" rel=\"noopener noreferrer nofollow\">\u0418\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D0%B7%D0%B0%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D0%B5\" rel=\"noopener noreferrer nofollow\">\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#%D1%81%D1%81%D1%8B%D0%BB%D0%BA%D0%B8\" rel=\"noopener noreferrer nofollow\">\u0421\u0441\u044b\u043b\u043a\u0438<\/a><\/p>\n<\/li>\n<\/ol>\n<h3>\u0426\u0435\u043b\u044c \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438<\/h3>\n<p>\u0426\u0435\u043b\u044c\u044e \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0438\u043c\u0435\u044e\u0449\u0435\u0433\u043e\u0441\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f, \u043d\u043e \u0438 \u0432\u044b\u044f\u0441\u043d\u0435\u043d\u0438\u0435 \u043d\u0430\u043b\u0438\u0447\u0438\u044f, \u043b\u0438\u0431\u043e \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u044f \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0430 \u043a \u043f\u0440\u043e\u0435\u043a\u0442\u0443 \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432. \u0414\u0435\u043b\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0441\u0430\u043c\u044b\u0435 \u0442\u0440\u0443\u0434\u043d\u044b\u0435 \u0447\u0430\u0441\u0442\u0438 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0432\u0441\u0435 \u0435\u0449\u0435 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442, \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0441\u043e\u043a\u0440\u0430\u0442\u0438\u043b\u043e\u0441\u044c \u0441 \u0434\u0432\u0443\u0445 \u0434\u043e \u043e\u0434\u043d\u043e\u0433\u043e (\u043c\u0435\u043d\u044f), \u043c\u043e\u0435 \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e \u0432\u0435\u0441\u044c\u043c\u0430 \u0441\u043a\u0440\u043e\u043c\u043d\u044b\u043c\u0438 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c\u0438 \u0440\u0430\u043c\u043a\u0430\u043c\u0438, \u0438 \u0442\u0440\u0430\u0442\u0438\u0442\u044c \u0435\u0433\u043e \u043d\u0430 \u043d\u0438\u043a\u043e\u043c\u0443 \u043d\u0435 \u043d\u0443\u0436\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0431\u0430\u043d\u0430\u043b\u044c\u043d\u043e \u0436\u0430\u043b\u043a\u043e. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u0435\u0441\u043b\u0438 \u043a\u0442\u043e-\u043b\u0438\u0431\u043e \u0437\u0430\u0445\u043e\u0447\u0435\u0442 \u043f\u043e\u043c\u043e\u0447\u044c \u043f\u0440\u0430\u0432\u043a\u0430\u043c\u0438, \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438, \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u043a\u0440\u0438\u0442\u0438\u043a\u043e\u0439 \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445 \u0438\u043b\u0438 \u043b\u044e\u0431\u044b\u043c \u0438\u043d\u044b\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c \u2014 \u0431\u0443\u0434\u0443 \u0440\u0430\u0434.<\/p>\n<h3>\u041e\u0447\u0435\u043d\u044c \u0441\u0436\u0430\u0442\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/h3>\n<figure class=\"\"><figcaption><\/figcaption><\/figure>\n<p><a href=\"https:\/\/vueent.github.io\/vueent\/\" rel=\"noopener noreferrer nofollow\">VueEnt<\/a> \u044d\u0442\u043e \u043d\u0430\u0431\u043e\u0440 \u0438\u0437 \u0447\u0435\u0442\u044b\u0440\u0435\u0445 \u043f\u0430\u043a\u0435\u0442\u043e\u0432, \u0442\u0440\u0438 \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b \u0434\u0440\u0443\u0433 \u043e\u0442 \u0434\u0440\u0443\u0433\u0430. \u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u043a\u0430\u043a Vue 3, \u0442\u0430\u043a \u0438 Vue 2.7, \u043b\u0438\u0431\u043e Vue 2.6 \u0441 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u043c <a href=\"https:\/\/github.com\/vuejs\/composition-api\" rel=\"noopener noreferrer nofollow\">@vue\/composition-api<\/a>.<\/p>\n<h4>\u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0446\u0435\u043b\u044c \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/h4>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0446\u0435\u043b\u044c\u044e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u044b\u0445 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Vue. \u0412\u0435\u0441\u044c \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d \u043d\u0430 <a href=\"https:\/\/www.typescriptlang.org\/\" rel=\"noopener noreferrer nofollow\">TypeScript<\/a>, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u0434\u043d\u043e\u0439 \u0438\u0437 \u0432\u0430\u0436\u043d\u044b\u0445 \u0446\u0435\u043b\u0435\u0439 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0443\u0434\u043e\u0431\u0441\u0442\u0432 \u0432 \u0432\u0438\u0434\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0430\u0432\u0442\u043e\u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0438 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c\u044b\u0445 \u0442\u0438\u043f\u043e\u0432. \u041e\u0442\u0447\u0430\u0441\u0442\u0438 \u0438\u0437-\u0437\u0430 \u044d\u0442\u043e\u0433\u043e, \u043e\u0442\u0447\u0430\u0441\u0442\u0438 \u0438\u0437 \u0444\u0438\u043b\u043e\u0441\u043e\u0444\u0441\u043a\u0438\u0445 \u043f\u043e\u0431\u0443\u0436\u0434\u0435\u043d\u0438\u0439, \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043d\u0438\u043a\u0430\u043a\u043e\u0439 \u043c\u0430\u0433\u0438\u0438. \u0421 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b, \u044d\u0442\u043e \u043f\u043e\u0440\u043e\u0436\u0434\u0430\u0435\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u043d\u043e\u0433\u043e\u0441\u043b\u043e\u0432\u043d\u043e\u0441\u0442\u044c, \u043d\u043e \u0441 \u0434\u0440\u0443\u0433\u043e\u0439, \u0432\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u0430\u043a, \u043a\u0430\u043a \u043e\u0436\u0438\u0434\u0430\u0435\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a, \u0437\u0430 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u0435\u0432, \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0445 \u0441 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f\u043c\u0438 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 Vue.<\/p>\n<h4>\u041d\u0435 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0446\u0435\u043b\u044f\u043c\u0438<\/h4>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0435\u0449\u0435 \u043e\u0434\u043d\u043e\u0433\u043e \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 Vue \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0446\u0435\u043b\u044c\u044e VueEnt. \u0422\u0430\u043a\u0436\u0435 \u0446\u0435\u043b\u044c\u044e \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430\u0432\u044f\u0437\u044b\u0432\u0430\u043d\u0438\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0443 \u043a\u0430\u043a\u043e\u0439-\u043b\u0438\u0431\u043e \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b \u0438\u043b\u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u0441\u0435 \u043f\u0430\u043a\u0435\u0442\u044b \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b \u0434\u0440\u0443\u0433 \u043e\u0442 \u0434\u0440\u0443\u0433\u0430 \u0438 \u043c\u043e\u0433\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0438\u043b\u0438 \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u043e \u0436\u0435\u043b\u0430\u043d\u0438\u044e.<\/p>\n<h4>\u0421\u043f\u0438\u0441\u043e\u043a \u043f\u0430\u043a\u0435\u0442\u043e\u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/h4>\n<h3>Reactive<\/h3>\n<p>\u041f\u0430\u043a\u0435\u0442 <code>@vueent\/reactive<\/code> \u2014 \u044d\u0442\u043e \u043d\u0430\u0431\u043e\u0440 \u0434\u0435\u043a\u043e\u0440\u0430\u0442\u043e\u0440\u043e\u0432 TypeScript, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>ref<\/code>&#8212; \u0438 <code>computed<\/code>-\u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 Vue \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u043e\u043b\u0435\u0439 ES-\u043a\u043b\u0430\u0441\u0441\u043e\u0432.<\/p>\n<h3>Core<\/h3>\n<p>\u041f\u0430\u043a\u0435\u0442 <code>@vueent\/core<\/code>, \u043d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u2014 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u0442\u0430\u043a\u0438\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438, \u043a\u0430\u043a \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u044b \u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u044b, \u0432\u043e Vue-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435.<\/p>\n<h3>Mix Models<\/h3>\n<p>\u041f\u0430\u043a\u0435\u0442 <code>@vueent\/mix-models<\/code> \u2014 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0430\u044f \u043a\u043b\u0430\u0441\u0441\u044b \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u0434\u043b\u044f <a href=\"https:\/\/ru.wikipedia.org\/wiki\/NoSQL\" rel=\"noopener noreferrer nofollow\">NoSQL<\/a>-\u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u0441 \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f, \u043e\u0442\u043a\u0430\u0442\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f (<em>rollback<\/em>) \u0438 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438. \u0418\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u043e\u0442 \u043f\u0430\u043a\u0435\u0442 \u0441\u0430\u043c\u044b\u0439 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0430\u043c\u044b\u043c \u0431\u043e\u043b\u044c\u0448\u0438\u043c \u0438 \u0432\u0430\u0436\u043d\u044b\u043c \u0432\u043e \u0432\u0441\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435.<\/p>\n<h3>Store<\/h3>\n<p>\u042d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0430\u043a\u0435\u0442 <code>@vueent\/store<\/code> \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043a\u043b\u0430\u0441\u0441\u044b \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439 \u043c\u043e\u0434\u0435\u043b\u0435\u0439, \u0442\u043e \u0435\u0441\u0442\u044c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u0441\u0438\u043b\u044c\u043d\u043e \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u043d\u044b\u0439 \u0430\u043d\u0430\u043b\u043e\u0433 <a href=\"https:\/\/github.com\/emberjs\/data\" rel=\"noopener noreferrer nofollow\">ember-data<\/a>, \u043d\u043e \u0431\u0435\u0437 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0440\u0435\u043b\u044f\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u0441\u0432\u044f\u0437\u0435\u0439.<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435:<\/strong> \u0415\u0441\u043b\u0438 \u0432\u0430\u043c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u043c\u043e\u0434\u0435\u043b\u044f\u043c\u0438, \u0442\u043e \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u0441\u0440\u0430\u0437\u0443 \u0436\u0435 \u043f\u0440\u043e\u043b\u0438\u0441\u0442\u0430\u0442\u044c \u0434\u043e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0433\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0430, \u0442\u0430\u043a \u043a\u0430\u043a \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044e \u044d\u0442\u043e \u043d\u0438\u043a\u0430\u043a \u043d\u0435 \u043f\u043e\u043c\u0435\u0448\u0430\u0435\u0442.<\/p>\n<h3>\u0411\u044b\u0441\u0442\u0440\u044b\u0439 \u0441\u0442\u0430\u0440\u0442<\/h3>\n<p>\u0414\u043b\u044f \u0442\u0435\u0445, \u043a\u043e\u043c\u0443 \u043b\u0435\u043d\u044c \u0447\u0438\u0442\u0430\u0442\u044c \u0442\u0435\u043a\u0441\u0442, \u043d\u043e \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u043f\u043e\u0449\u0443\u043f\u0430\u0442\u044c \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 \u0440\u0430\u0431\u043e\u0447\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435, \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043b\u0435\u043d \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 <a href=\"https:\/\/github.com\/vueent\/vueent-quick-start\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u043e\u0435\u043a\u0442<\/a>:<\/p>\n<pre><code class=\"bash\">git clone https:\/\/github.com\/vueent\/vueent-quick-start.git cd vueent-quick-start npm i npm run dev<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0435\u043a\u0442 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u0441\u043f\u0438\u0441\u043a\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432, \u0433\u0434\u0435 \u0443 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0435\u0441\u0442\u044c \u0438\u043c\u044f, \u0444\u0430\u043c\u0438\u043b\u0438\u044f, \u0442\u0435\u043b\u0435\u0444\u043e\u043d \u0438 \u0432\u043e\u0437\u0440\u0430\u0441\u0442. \u0414\u0430\u043d\u043d\u044b\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u044e\u0442\u0441\u044f \u0432 <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/IndexedDB_API\/Using_IndexedDB\" rel=\"noopener noreferrer nofollow\">IndexedDB<\/a>. \u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043f\u043e\u044f\u0441\u043d\u044f\u044e\u0449\u0438\u0435 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438.<\/p>\n<p>\u0425\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u0442\u0430\u043a\u0436\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043d\u043e \u044d\u0442\u0430 \u0442\u0435\u043c\u0430 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043e\u0431\u0448\u0438\u0440\u043d\u0430 \u0438 \u0437\u0430\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u0435\u0442 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438.<\/p>\n<h3>\u0411\u043e\u043b\u0435\u0435 \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u044b\u0439 \u043e\u0431\u0437\u043e\u0440 \u043f\u0430\u043a\u0435\u0442\u043e\u0432 \u0441 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u043c\u0438<\/h3>\n<h4>Reactive<\/h4>\n<p>\u041a\u043e\u0433\u0434\u0430 \u044f \u0432\u043f\u0435\u0440\u0432\u044b\u0435 \u0443\u0432\u0438\u0434\u0435\u043b Vue Composition API, \u0442\u043e \u0441\u0440\u0430\u0437\u0443 \u0436\u0435 \u043f\u043e\u0434\u0443\u043c\u0430\u043b \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0442\u0435\u043f\u0435\u0440\u044c \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c \u0443\u0434\u043e\u0431\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432, \u043d\u043e \u0438 \u0437\u0430 \u0438\u0445 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u043c\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0432 \u043a\u0430\u043a\u0438\u0445-\u043d\u0438\u0431\u0443\u0434\u044c \u043a\u043b\u0430\u0441\u0441\u0430\u0445. \u041e\u0434\u043d\u0430\u043a\u043e \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u0432\u0438\u0434\u0435\u0442\u044c \u043e\u0431\u044b\u0447\u043d\u044b\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430, \u0430 \u043d\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b, \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u043e\u043b\u0435\u0439 \u043a\u043b\u0430\u0441\u0441\u043e\u0432, \u0432\u0435\u0434\u044c \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u044d\u0442\u043e \u043f\u043e\u043b\u0435 \u043a\u043b\u0430\u0441\u0441\u0430 \u043d\u0435 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e, \u0430 \u0437\u0430\u0432\u0442\u0440\u0430 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c\u0441\u044f. \u0415\u0441\u043b\u0438 \u0432\u044b \u043f\u0440\u043e\u0431\u043e\u0432\u0430\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>ref<\/code> \u0438 <code>computed<\/code> \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432 \u043a\u043b\u0430\u0441\u0441\u043e\u0432, \u0442\u043e \u043c\u043e\u0433\u043b\u0438 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u044d\u0442\u043e \u043d\u0435 \u0441\u043b\u0438\u0448\u043a\u043e\u043c-\u0442\u043e \u0443\u0434\u043e\u0431\u043d\u043e. \u0418\u0442\u0430\u043a, \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0439\u0442\u0435 \u0434\u0435\u043a\u043e\u0440\u0430\u0442\u043e\u0440\u044b <code>tracked<\/code> (\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 <code>ref<\/code>) \u0438 <code>calculated<\/code> (\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 <code>computed<\/code>):<\/p>\n<pre><code class=\"typescript\">import { tracked, calculated } from '@vueent\/reactive';  class MyClass {   @tracked public num = 2;   @tracked public factor = 3;    @calculated public get mul() {     console.log('calculate mul');      return this.num * this.factor;   } }  const my = new MyClass();  my.factor = 4;  console.log(my.mul); \/\/ \"calculate mul\", 8 - \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043a\u0430\u043a \u043e\u0436\u0438\u0434\u0430\u043b\u043e\u0441\u044c console.log(my.mul); \/\/ 8 - \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0433\u043e \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u043d\u0435\u0442, \u043a\u0430\u043a \u0438 \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u043e<\/code><\/pre>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435:<\/strong> \u041d\u0430\u0447\u0438\u043d\u0430\u044f \u0441 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 TypeScript, \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0434\u0435\u043a\u043e\u0440\u0430\u0442\u043e\u0440\u044b, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0430 \u0432 <code>tsconfig.json<\/code>:<\/p>\n<pre><code class=\"json\">\"moduleResolution\": \"node\", \"useDefineForClassFields\": false, \"experimentalDecorators\": true<\/code><\/pre>\n<p>\u041a\u0430\u043a \u0438 \u0431\u044b\u043b\u043e \u0441\u043a\u0430\u0437\u0430\u043d\u043e \u0432 \u0441\u0430\u043c\u043e\u043c \u043d\u0430\u0447\u0430\u043b\u0435, \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u043e\u0431\u0437\u043e\u0440\u043d\u0430\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0437\u0430 \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u044b\u043c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u043f\u0430\u043a\u0435\u0442\u0430 \u043f\u0440\u043e\u0448\u0443 \u043f\u0440\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u043f\u043e <a href=\"https:\/\/vueent.github.io\/vueent\/guide\/reactive.html\" rel=\"noopener noreferrer nofollow\">\u0441\u0441\u044b\u043b\u043a\u0435<\/a>.<\/p>\n<h4>Core<\/h4>\n<p>\u0418\u0434\u0435\u044f <code>@vueent\/core<\/code> \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u043d\u0430 Vue. \u0418\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438 \u043d\u0430\u043c \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e views \u0438\u043b\u0438 pages (\u0435\u0441\u043b\u0438 \u0440\u0435\u0447\u044c \u043f\u0440\u043e <a href=\"https:\/\/nuxtjs.org\/\" rel=\"noopener noreferrer nofollow\">Nuxt<\/a>) \u0434\u043b\u044f \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432-\u043c\u0430\u0440\u0448\u0440\u0443\u0442\u043e\u0432, \u0445\u043e\u0442\u044f \u0441\u0430\u043c \u043f\u043e \u0441\u0435\u0431\u0435 Vue \u0432\u043e\u043e\u0431\u0449\u0435 \u043d\u0435 \u043d\u0430\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442 \u043a\u0430\u043a\u0438\u0445-\u043b\u0438\u0431\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439 \u043d\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0444\u0430\u0439\u043b\u043e\u0432. \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0432\u0445\u043e\u0434\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u043e\u0439 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0430 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442. \u041d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u043f\u043e Vue \u044f \u043d\u0435 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u043b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 (\u043f\u043e\u043f\u0440\u0430\u0432\u044c\u0442\u0435, \u0435\u0441\u043b\u0438 \u044f \u0441\u043b\u0435\u043f), \u043d\u043e \u0442\u0430\u043c \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<blockquote>\n<p>Components allow us to split the UI into independent and reusable pieces, and think about each piece in isolation.<\/p>\n<\/blockquote>\n<blockquote>\n<p>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u043d\u0430\u043c \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043d\u0430 \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b\u0435 \u0438 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 \u0447\u0430\u0441\u0442\u0438 \u0438 \u0434\u0443\u043c\u0430\u0442\u044c \u043e \u043a\u0430\u0436\u0434\u043e\u0439 \u0438\u0437 \u043d\u0438\u0445 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e.<\/p>\n<\/blockquote>\n<p>\u0422\u043e \u0435\u0441\u0442\u044c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u044f\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u043d\u0435 \u0447\u0442\u043e \u0438\u043d\u043e\u0435, \u043a\u0430\u043a <em>\u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435<\/em>, \u0433\u043e\u0432\u043e\u0440\u044f \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043c\u0438 \u0442\u043e\u0433\u043e \u0436\u0435 <a href=\"https:\/\/ru.wikipedia.org\/wiki\/Model-View-ViewModel\" rel=\"noopener noreferrer nofollow\">MVVM<\/a>. \u0415\u0441\u043b\u0438 \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u043a\u0430\u043a \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435, \u0442\u043e \u043e\u043d \u043d\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0432 \u0441\u0435\u0431\u044f \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0443, \u0445\u043e\u0442\u044f \u0438\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u043e \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0447\u0430\u0441\u0442\u043e \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u043d\u0430 Vue \u0438 <a href=\"https:\/\/reactjs.org\/\" rel=\"noopener noreferrer nofollow\">React<\/a>. \u0414\u043b\u044f \u0438\u043d\u043a\u0430\u043f\u0441\u0443\u043b\u044f\u0446\u0438\u0438 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0438 \u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0434\u0430\u043d\u043d\u044b\u043c \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441\u044b, \u0430 \u0434\u043b\u044f \u043e\u0442\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0441\u043b\u043e\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043e\u0442 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u044b (\u0445\u043e\u0442\u044f, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043d\u0435 \u0441\u0430\u043c\u043e\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0435\u0435). \u0418\u043c\u0435\u043d\u043d\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u044b \u0441 \u043b\u0435\u043d\u0438\u0432\u043e\u0439 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u0430\u043a\u0435\u0442 <code>@vueent\/core<\/code>. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0440\u0435\u0444\u0435\u0440\u0435\u043d\u0441\u043d\u044b\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u043c\u043e\u0436\u043d\u043e \u0432\u0437\u044f\u0442\u044c <a href=\"https:\/\/angular.io\/\" rel=\"noopener noreferrer nofollow\">Angular<\/a> \u0438\u043b\u0438 <a href=\"https:\/\/emberjs.com\/\" rel=\"noopener noreferrer nofollow\">Ember<\/a>. \u0422\u0430\u043a\u0436\u0435 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u044d\u0442\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430 \u043d\u0430\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u043d\u0430 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044e \u0437\u0434\u0435\u0441\u044c, <a href=\"https:\/\/habr.com\/ru\/company\/simbirsoft\/blog\/556270\/\" rel=\"noopener noreferrer nofollow\">\u043d\u0430 \u0445\u0430\u0431\u0440\u0435<\/a>, \u043d\u0435\u043f\u043b\u043e\u0445\u043e \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0449\u0443\u044e \u043a\u043e\u043d\u0446\u0435\u043f\u0442.<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u044b \u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043f\u0435\u0440\u0432\u0430 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c <em>\u044f\u0434\u0440\u043e<\/em>:<\/p>\n<pre><code class=\"typescript\">\/\/ file: .\/vueent.ts import { initVueent } from '@vueent\/core';  export const {   useVueent,   registerService,   registerController,   useService,   useController,   injectService,   injectController } = initVueent();<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043a\u043b\u0438\u043a\u043e\u0432:<\/p>\n<pre><code class=\"typescript\">\/\/ file: .\/services\/clicker.ts import { Service } from '@vueent\/core'; import { tracked } from '@vueent\/reactive';  import { registerService } from '@\/vueent';  export default class ClickerService extends Service {   @tracked private _counter = 0; \/\/ \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e    public get counter() {     return this._counter;   }    public increment() {     ++this._counter;   } }  registerService(ClickerService); \/\/ \u043d\u0443\u0436\u043d\u043e \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u0440\u0441\u0438\u0441<\/code><\/pre>\n<p>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0439 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u043c\u0443 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0443 \u0438 \u043c\u0435\u0442\u043e\u0434\u0443, \u0438\u0437\u043c\u0435\u043d\u044f\u044e\u0449\u0435\u043c\u0443 \u0435\u0433\u043e:<\/p>\n<pre><code class=\"typescript\">\/\/ file: .\/app.ts import { Controller } from '@vueent\/core';  import { registerController, injectService as service } from '@\/vueent'; import ClickerService from '@\/services\/clicker';  export default class AppController extends Controller {   \/\/ \u043b\u0435\u043d\u0438\u0432\u0430\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u0435\u0440\u0432\u0438\u0441\u0430   @service(ClickerService) private readonly clicker!: ClickerService;    public readonly date: number;    public get counter() {     return this.clicker.counter; \/\/ \u0432\u043e\u0437\u0432\u0440\u0430\u0442 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0441\u0435\u0440\u0432\u0438\u0441\u0430   }    constructor(date: number) {     super();     this.date = date;   }    public init() {     console.log('onBeforeMount');   }    public reset() {     console.log('onBeforeUnmount');   }    public destroy() {     console.log('onUnmounted'); \/\/ \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043d\u0430\u0431\u043b\u044e\u0434\u0430\u0442\u0435\u043b\u0435\u0439 (watchers), \u0442\u0430\u0439\u043c\u0435\u0440\u043e\u0432 \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435   }    public increment() {     this.clicker.increment();   } }  registerController(AppController); \/\/ \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u0442\u0430\u043a\u0436\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c<\/code><\/pre>\n<p>\u041d\u0430\u043a\u043e\u043d\u0435\u0446, \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"xml\">&lt;!-- file: app.vue:template --> &lt;template> &lt;div>   &lt;div>Started at: {{ timestamp }}&lt;\/div>   &lt;div>Button clicks: {{ counter }}&lt;\/div>   &lt;div>     &lt;button type=\"button\" @click=\"increment\">Increment&lt;\/button>   &lt;\/div> &lt;\/div> &lt;\/template><\/code><\/pre>\n<pre><code class=\"typescript\">\/\/ file: app.vue:script import { defineComponent, computed } from 'vue';  import { useController } from '@\/vueent';  import<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-345584","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/345584","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=345584"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/345584\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=345584"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=345584"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=345584"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}