پلاگین jQuery جهت فیلتر کردن اطلاعات و استفاده در گزارش سازهای تحت وب ( پیش نمایش )
(jui_filter_rules is a jQuery Data filtering plugin (query builder
مدل دیگری از آن افزونهی jQuery QueryBuilder میباشد
پلاگین jQuery جهت فیلتر کردن اطلاعات و استفاده در گزارش سازهای تحت وب ( پیش نمایش )
(jui_filter_rules is a jQuery Data filtering plugin (query builder
مدل دیگری از آن افزونهی jQuery QueryBuilder میباشد
var product = { ProductId: 1001, ProductName: "Product 1001", Available: true, Filename: "Image02.png" };
var productCount = 100; var products = []; function datasourceFilling() { for (var i = 0; i < productCount; i++) { var product = { ProductId: i, ProductName: "Product " + i + " Name", Available: i % 2 == 0 ? true: false, Filename: i % 2 == 0 ? "Image01.png" : "Image02.png" }; products.push(product); } }
function makekendoGrid() { $("#grid").kendoGrid({ dataSource: { data: products, schema: { model: { //id: "ProductId", fields: { ProductId: { editable: false, nullable: true }, ProductName: { validation: { required: true } }, Available: { type: "boolean" }, ImageName: { type: "string", editable: false }, Filename: { type: "string", validation: { required: true } } } } }, pageSize: 20 }, height: 550, scrollable: true, sortable: true, filterable: true, pageable: { input: true, numeric: false }, editable: { mode: "popup", }, columns: [ { field: "ProductName", title: "Product Name" }, { field: "Available", width: "100px", template: '<input type="checkbox" #= Available ? checked="checked" : "" # disabled="disabled" ></input>' }, { field: "ImageName", width: "150px", template: "<img src='/img/#=Filename#' alt='#=Filename #' Title='#=Filename #' height='80' width='80'/>" }, { field: "Filename", width: "100px", editor: fileEditor }, { command: ["edit"], title: " ", width: "200px" } ] }); var grid = $('#grid').data('kendoGrid'); grid.hideColumn(3); }
function fileEditor(container, options) { $('<input type="file" name="file"/>') .appendTo(container) .kendoUpload({ multiple: false, async: { saveUrl: "@Url.Action("Save", "Home")", removeUrl: "@Url.Action("Remove", "Home")", autoUpload: true, }, upload: function (e) { alert("upload"); e.data = { Id: options.model.Id }; }, success: function (e) { alert("success"); options.model.set("ImageName", e.response.ImageUrl); }, error: function (e) { alert("error"); alert("Failed to upload " + e.files.length + " files " + e.XMLHttpRequest.status + " " + e.XMLHttpRequest.responseText); } }); }
[System.Web.Mvc.HttpPost] public virtual ActionResult Save(HttpPostedFileBase file) { var exName = Path.GetExtension(file.FileName); var totalFileName = System.Guid.NewGuid().ToString().ToLower().Replace("-", "") + exName; var physicalPath = Path.Combine(Server.MapPath("/img"), totalFileName); file.SaveAs(physicalPath); return Json(new { ImageUrl = totalFileName }, "text/plain"); } [System.Web.Mvc.HttpPost] public virtual ContentResult Remove(string fileName) { if (fileName != null) { var physicalPath = Path.Combine(Server.MapPath("/img"), fileName); System.IO.File.Delete(physicalPath); } // Return an empty string to signify success return Content(""); }
namespace ShowAlertSignalR.Models { public class Product { public int Id { get; set; } public string Title { get; set; } public string Description { get; set; } public float Price { get; set; } public Category Category { get; set; } } public enum Category { [Display(Name = "دسته بندی اول")] Cat1, [Display(Name = "دسته بندی دوم")] Cat2, [Display(Name = "دسته بندی سوم")] Cat3 } }
namespace ShowAlertSignalR.Models { public class ProductDbContext : DbContext { public ProductDbContext() : base("productSample") { Database.Log = sql => Debug.Write(sql); } public DbSet<Product> Products { get; set; } } }
[HttpPost] [ValidateAntiForgeryToken] public ActionResult Create(Product product) { if (ModelState.IsValid) { db.Products.Add(product); db.SaveChanges(); return RedirectToAction("Index"); } return View(product); }
public ActionResult Index(bool notifyUsers = false) { ViewBag.NotifyUsers = notifyUsers; return View(db.Products.ToList()); }
[HttpPost] [ValidateAntiForgeryToken] public ActionResult Create(Product product) { if (ModelState.IsValid) { db.Products.Add(product); db.SaveChanges(); return RedirectToAction("Index", new { notifyUsers = true }); } return View(product); }
namespace ShowAlertSignalR.Hubs { public class NotificationHub : Hub { public void SendNotification() { Clients.Others.ShowNotification(); } } }
@section scripts { <script src="~/Scripts/jquery.signalR-2.0.2.min.js"></script> <script src="~/signalr/hubs"></script> <script> var notify = $.connection.notificationHub; notify.client.showNotification = function() { $('#result').append("<div class='alert alert-info alert-dismissable'>" + "<button type='button' class='close' data-dismiss='alert' aria-hidden='true'>×</button>" + "رکورد جدیدی هم اکنون ثبت گردید، برای مشاهده آن صفحه را بروزرسانی کنید" + "</div>"); }; $.connection.hub.start().done(function() { @{ if (ViewBag.NotifyUsers) { <text>notify.server.sendNotification();</text> } } }); </script> }
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width" /> <title>@ViewBag.Title</title> <link href="~/Content/Site.css" rel="stylesheet" /> <link href="~/Content/themes/default/style.min.css" rel="stylesheet" /> <script src="~/Scripts/jquery.min.js"></script> <script src="~/Scripts/jstree.min.js"></script> </head> <body dir="rtl"> @RenderBody() @RenderSection("scripts", required: false) </body> </html>
right_to_left = $("body").css("direction") === "rtl";
using System.Collections.Generic; namespace MvcJSTree.Models { public class JsTreeNode { public string id { set; get; } // نام این خواص باید با مستندات هماهنگ باشد public string text { set; get; } public string icon { set; get; } public JsTreeNodeState state { set; get; } public List<JsTreeNode> children { set; get; } public JsTreeNodeLiAttributes li_attr { set; get; } public JsTreeNodeAAttributes a_attr { set; get; } public JsTreeNode() { state = new JsTreeNodeState(); children = new List<JsTreeNode>(); li_attr = new JsTreeNodeLiAttributes(); a_attr = new JsTreeNodeAAttributes(); } } public class JsTreeNodeAAttributes { // به هر تعداد و نام اختیاری میتوان خاصیت تعریف کرد public string href { set; get; } } public class JsTreeNodeLiAttributes { // به هر تعداد و نام اختیاری میتوان خاصیت تعریف کرد public string data { set; get; } } public class JsTreeNodeState { public bool opened { set; get; } public bool disabled { set; get; } public bool selected { set; get; } public JsTreeNodeState() { opened = true; } } }
[HttpPost] public ActionResult GetTreeJson() { var nodesList = new List<JsTreeNode>(); var rootNode = new JsTreeNode { id = "dir", text = "Root 1", icon = Url.Content("~/Content/images/tree_icon.png"), a_attr = { href = "http://www.bing.com" } }; nodesList.Add(rootNode); nodesList.Add(new JsTreeNode { id = "test1", text = "Root 2", icon = Url.Content("~/Content/images/tree_icon.png"), a_attr = { href = "http://www.bing.com" } }); return Json(nodesList, JsonRequestBehavior.AllowGet); }
<div id="jstree"> </div>
$('#jstree').jstree({ "core": { "multiple": false, "check_callback": true, 'data': { 'url': '@getTreeJsonUrl', "type": "POST", "dataType": "json", "contentType": "application/json; charset=utf8", 'data': function (node) { return { 'id': node.id }; } }, 'themes': { 'variant': 'small', 'stripes': true } }, "types": { "default": { "icon": '@Url.Content("~/Content/images/bookmark_book_open.png")' }, }, "plugins": ["contextmenu", "dnd", "state", "types", "wholerow", "sort", "unique"], "contextmenu": { "items": function (o, cb) { var items = $.jstree.defaults.contextmenu.items(); items["create"].label = "ایجاد زیر شاخه"; items["rename"].label = "تغییر نام"; items["remove"].label = "حذف"; var cpp = items["ccp"]; cpp.label = "ویرایش"; var subMenu = cpp["submenu"]; subMenu["copy"].label = "کپی"; subMenu["paste"].label = "پیست"; subMenu["cut"].label = "برش"; return items; } } });
@{ ViewBag.Title = "Demo"; var getTreeJsonUrl = Url.Action(actionName: "GetTreeJson", controllerName: "Home"); }
$('#jstree').jstree({ // تمام تنظیمات مانند قبل }).on('delete_node.jstree', function (e, data) { }) .on('create_node.jstree', function (e, data) { }) .on('rename_node.jstree', function (e, data) { }) .on('move_node.jstree', function (e, data) { }) .on('copy_node.jstree', function (e, data) { }) .on('changed.jstree', function (e, data) { }) .on('dblclick.jstree', function (e) { }) .on('select_node.jstree', function (e, data) { });
function postJsTreeOperation(operation, data, onDone, onFail) { $.post('@doJsTreeOperationUrl', { 'operation': operation, 'id': data.node.id, 'parentId': data.node.parent, 'position': data.position, 'text': data.node.text, 'originalId': data.original ? data.original.id : data.node.original.id, 'href': data.node.a_attr.href }) .done(function (result) { onDone(result); }) .fail(function (result) { alert('failed.....'); onFail(result); }); }
.on('create_node.jstree', function (e, data) { postJsTreeOperation('CreateNode', data, function (result) { data.instance.set_id(data.node, result.id); }, function (result) { data.instance.refresh(); }); })
[HttpPost] public ActionResult DoJsTreeOperation(JsTreeOperationData data) { switch (data.Operation) { case JsTreeOperation.CopyNode: case JsTreeOperation.CreateNode: //todo: save data var rnd = new Random(); // آی دی رکورد پس از ثبت در بانک اطلاعاتی دریافت و بازگشت داده شود return Json(new { id = rnd.Next() }, JsonRequestBehavior.AllowGet); case JsTreeOperation.DeleteNode: //todo: save data return Json(new { result = "ok" }, JsonRequestBehavior.AllowGet); case JsTreeOperation.MoveNode: //todo: save data return Json(new { result = "ok" }, JsonRequestBehavior.AllowGet); case JsTreeOperation.RenameNode: //todo: save data return Json(new { result = "ok" }, JsonRequestBehavior.AllowGet); default: throw new InvalidOperationException(string.Format("{0} is not supported.", data.Operation)); } }
namespace MvcJSTree.Models { public enum JsTreeOperation { DeleteNode, CreateNode, RenameNode, MoveNode, CopyNode } public class JsTreeOperationData { public JsTreeOperation Operation { set; get; } public string Id { set; get; } public string ParentId { set; get; } public string OriginalId { set; get; } public string Text { set; get; } public string Position { set; get; } public string Href { set; get; } } }
var selectedData; // ... .on('dblclick.jstree', function (e) { var href = selectedData.node.a_attr.href; alert('selected node: ' + selectedData.node.text + ', href:' + href); // auto redirect if (href) { window.location = href; } // activate edit mode //var inst = $.jstree.reference(selectedData.node); //inst.edit(selectedData.node); }) .on('select_node.jstree', function (e, data) { //alert('selected node: ' + data.node.text); selectedData = data; });
در حالیکه ECMAScript 5 قابلیتهای فوق العادهای را برای کنترل کردن خصوصیات موجود در اشیاء، در اختیار شما قرار میدهد، اما هیچ راه کاری را برای خصوصیاتی که موجود نیستند، ندارد. شما میتوانید برای خواص موجود، از رونویسی (تنظیم writable برابر false) و یا حذف شدن (تنظیم configurable برابر false) جلوگیری کنید. شما میتوانید از اختصاص خصوصیات جدید به اشیاء با استفاده از ()Object.preventExtensions و یا تنظیم تمام خصوصیات به صورت فقط خواندنی و یا غیرقابل حذف ()Object.freeze جلوگیری کنید.
اگر شما نمیخواهید تمام خصوصیات را فقط خواندنی کنید میتوانید از ()Object.seal استفاده کنید. اینها مانع از اضافه کردن خصوصیات و یا حذف کردن خصوصیات موجود میشوند. اگر به یک شیء مهر و موم شده (sealed)، زمانی که از strict mode استفاده میکنید، یک خصوصیت جدید اضافه کنید باعث ایجاد خطا میشود:
"use strict"; var person = { name: "Vahid Mohammad Taheri" }; Object.seal(person); person.age = 27; // Error!
پروکسیها، دارای سابقه طولانی و پیچیده ای در ECMAScript 6 است. طرح اولیه آن توسط Firefox و Chrome قبل از تصمیم TC-39 به تغییر پروکسیها، اجرا شده است. این تغییرات، برای بهتر و روانتر شدن پروکسیها از طرح اولیه پروکسیها انجام گرفت.
بزرگترین تغییر صورت گرفته، معرفی شیء هدف که میخواست با پروکسی در تعامل باشد، بود. به جای تعریف دام برای نوعهای مختلفی از عملیات، با ایجاد پروکسی، مستقیما برای عملیاتی از قبل تعیین شده بر روی اشیاء هدف، این کار را انجام میدهیم.
این کار از طریق یک سری از روشهایی که به مخفی کردن عملیات در ECMAScript مطابقت دارند، انجام میشود. به عنوان مثال زمانیکه بر روی یک ویژگی از یک شیء، عمل خواندن انجام میشود، عملیات [[Get]]
در موتور جاوااسکریپت انجام میگیرد. نحوهی رفتار [[Get]]
را نمیتوان تغییر داد؛ با این حال، با استفاده از پروکسیها میتوان دامی برای زمان فراخوانی [[Get]]
قرار داد و عملیات خاص مورد نظر خود را اعمال کرد. به مثال زیر توجه کنید:
var proxy = new Proxy({ name: "Vahid" }, { get: function(target, property) { if (property in target) { return target[property]; } else { return 13; } } }); console.log(proxy.time); // 13 console.log(proxy.name); // "Vahid" console.log(proxy.title); // 13
[[Get]]
به دام افتاده و تابع تعریف شدهی ما اجرا میشود (باقی عملیات به صورت عادی اجرا میشوند). دامی که برای شیء مورد نظر تعریف کردهایم دو پارامتر دریافت میکند (اول شی هدف، دوم ویژگی مورد نظر). با استفاده از کد نوشته شده در آن ابتدا بررسی میشود که شیء مورد نظر دارای ویژگی ارسال شده است یا خیر؟ در صورتی که وجود داشته باشد، مقدار آن بازگشت داده میشود و در غیر اینصورت به صورت ثابت مقدار 13 برگشت داده میشود.[[Get]]
را درک کنید و هدف از این کار صدور خطا در زمان دستیابی به ویژگی ای از شیءایی که وجود ندارد است.function createDefensiveObject(target) { return new Proxy(target, { get: function(target, property) { if (property in target) { return target[property]; } else { throw new ReferenceError("Property \"" + property + "\" does not exist."); } } }); }
()createDefensiveObject
یک شیء را به عنوان هدف میپذیرد و یک شیء دفاعی برای آن ایجاد میکند. پروکسی یک دام به نام get دارد؛ برای زمانی که عمل خواندن انجام میشود. اگر ویژگی خوانده شده در شیء وجود داشت، مقدار آن برگشت داده میشود و از سوی دیگر، وقتی ویژگی خوانده شده در شیء وجود نداشته باشد، سبب بروز خطا میشود. به مثال زیر توجه کنید:var person = { name: "Vahid" }; var defensivePerson = createDefensiveObject(person); console.log(defensivePerson.name); // "Vahid" console.log(defensivePerson.age); // Error!
var person = { name: "Vahid" }; var defensivePerson = createDefensiveObject(person); console.log(defensivePerson.name); // "Vahid" defensivePerson.age = 13; console.log(defensivePerson.age); // 13
var person = { name: "Vahid" }; var defensivePerson = createDefensiveObject(person); console.log("name" in defensivePerson); // true console.log(defensivePerson.hasOwnProperty("name")); // true console.log("age" in defensivePerson); // false console.log(defensivePerson.hasOwnProperty("age")); // false
var person = { name: "Vahid" }; Object.preventExtensions(person); var defensivePerson = createDefensiveObject(person); defensivePerson.age = 27; // Error! console.log(defensivePerson.age); // Error!
defensivePerson
برای هر دو حالت خواندن و نوشتن ویژگیهایی که وجود ندارند، خطا صادر میکند.function Person(name) { this.name = name; return createDefensiveObject(this); } var person = new Person("Vahid"); console.log(person.age); // Error!
()createDefensiveObject
درون سازنده، میتوانید اطمینان کامل داشته باشید که همهی نمونههای ساخته شدهی از شیء Person، دارای حالت دفاعی میباشند.در بیشتر زبانهای برنامهنویسی قابلیتی تحت عنوان String Interpolation وجود دارد. منظور، فرآیند جایگزین کردن مقادیر، با یکسری placeholder درون یک رشته است. در نسخههای قبلی جاوا اسکریپت محدودیتهایی در استفاده از رشتهها وجود داشت و امکان انجام این کار به صورت توکار مهیا نبود. یعنی برای پیادهسازی این قابلیت میتوانستیم با تغییر prototype شیء String و یا روشهای دیگری اینحالت را پیادهسازی کنیم (+):
// First, checks if it isn't implemented yet. if (!String.prototype.format) { String.prototype.format = function() { var args = arguments; return this.replace(/{(\d+)}/g, function(match, number) { return typeof args[number] != 'undefined' ? args[number] : match ; }); }; } "Hello, {0}, I'm a simple {1}, Today is: {2}".format("World", "String", new Date()); // Output "Hello, World, I'm a simple String, Today is: Tue Dec 29 2015 10:21:10 GMT+0330 (Iran Standard Time)"
اما در ES 6 با کمک قابلیتی تحت عنوان template string این محدودیتها به طور قابل ملاحظهایی کاهش پیدا کرده است. در واقع یک template string، یک رشتهی جاوا اسکریپتی است که به جای (" ") و یا (' ') درون دو کاراکتر (` `) یا به اصطلاح back-tick character محصور خواهد شد. این ویژگی در سناریوهای مختلفی کاریرد دارد. از این ویژگی میتوانیم جهت الحاق رشتهها استفاده کنیم. به عنوان مثال میتوانیم کد زیر را:
let category = "music"; let id = 2112; let url = "http://apiserver/" + category + "/" + id;
با کمک template string به اینصورت بازنویسی کنیم:
let category = "music"; let id = 2112; let url = `http://apiserver/${category}/${id}`;
و یا میتوانیم مثال ابتدای مطلب را به اینصورت بازنویسی کنیم:
console.log(`Hello, ${"World"}, I'm a simple ${"String"}, Today is: ${new Date()}`);
همانطور که عنوان شد برای استفاده از این قابلیت باید رشتهی موردنظر را درون دو کاراکتر (` `) قرار دهیم. سپس درون این کاراکترها میتوانیم literal text و همچنین یکسری placeholder جهت جایگزین کردن با مقادیر و عبارات موردنظر داشته باشیم. این placeholderها نیز با استفاده از سینتکس { }$ قابل تعریف هستند. لازم به ذکر است که عبارت موردنظرمان را باید درون دو علامت { } بنویسیم. مقادیر درون این دو علامت میتوانند هر عبارت معتبر جاوا اسکریپتی باشند:
let a = 5; let b = 10; console.log(`Fifteen is ${a + b} and\nnot ${2 * a + b}.`); // "Fifteen is 15 and // not 20."
در کد فوق متغیرهای a و b درون placeholderهای مربوطه جایگزین خواهند شد. همانطور که مشاهده میکنید، این سینتکس نسبت به سینتکس + که برای الحاق رشتهها قبلاً مورد استفاده قرار میگرفت خیلی بهتر و خواناتر است.
به صورت خلاصه:
`\`` // یا "`"
Multiline Strings
console.log(`string text line 1 string text line 2`); // "string text line 1 // string text line 2"
همانطور که مشاهده میکنید، template string از متنهای چندخطی نیز به خوبی پشتیبانی میکند. به عنوان مثال اگر رشتهی فوق را درون گیومه مینوشتیم میبایستی از سینتکس + برای الحاق دو خط فوق استفاده میکردیم:
console.log("string text line 1\n"+ "string text line 2"); // "string text line 1 // string text line 2"
var x = 1; var y = 3; var result = upper `${x} + ${y} is ${x+y}`; console.log(result); // Output // 1 + 3 IS 4
let upper = function(strings, ...values){ let result = ""; for(var i = 0; i < strings.length; i++){ result += strings[i]; if(i < values.length){ result += values[i]; } } return result.toUpperCase(); };
strings = ["", " + ", " is ", ""]; values = [1, 3, 4];
var name = "سیروان عفیفی"; var price = 150000; var text = withToman `${name} با تشکر از خرید شما, مبلغ قابل پرداخت: ${price}`; alert(text);
function withToman(strings, ...values) { return strings.reduce( function (s, v, idx) { if(idx > 0) { if(typeof values[idx - 1] == "number") { s += `${values[idx - 1].toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")} تومان` } else { s += values[idx -1]; } } return s + v; }, ""); }
Ext.data.JsonP.request({ url: '@url', params: { apiKey: '1234' }, callbackKey: 'myCallbackFn', success: function(){ }, failure: function(){ }, scope: this });
حال با همه این تفاسیر آیا این فریم ورک یک رویا برای هر توسعه دهنده وب خواهد بود؟
به طور قطع نه. با توجه به اصل واقع بینی! همواره به خاطر داشته باشید که
اگر این فریم ورک یک ابزار بی نقص و همه منظوره بود الآن مطمئنا صدها کتاب و
مستندات درباره آن نوشته شده بود و شاید شهرتی بس فراتر از این داشت.
کابوسی به نام ExtJs
Ext.Net چیست؟
Ext.Net یک پیاده سازی خاص از فریم ورک ExtJs است که برای توسعه پروژههای Asp.Net Web Forms و Asp.Net MVC طراحی شده است. تفاوت اصلی بین این دو محصول در نوع کدنویسی برای استفاده در پروژههای Asp.Net است. برای مثال در هنگام کار با Ext.Net و پروژههای MVC از آنجا که این محصول سازگاری کامل با موتور Razor دارد به راحتی میتوانید به صورت سینتکس Razor صفحات خود را طراحی کنید.
مثال:
ExtJs
Ext.create('Ext.panel.Panel', { title: 'Fit Layout', width: 500, height: 200, items: { title: 'Inner Panel', html: 'Panel content', bodyPadding: 10, border: true }, renderTo: Ext.getBody() });
Ext.Net
@(X.Panel() .ID("ExpandablePanel") .Title("Panel") .Width(500) .Height(300) .Collapsible(true) .Loader(X.ComponentLoader() .Url(Url.Action("RenderChild")) .Mode(LoadMode.Frame) .DisableCaching(true) .Params(new { containerId = "ExpandablePanel" }) .LoadMask(lm => lm.ShowMask = true) ) .Listeners(l => { l.Expand.Handler = "this.reload();"; l.Collapse.Handler = "this.clearContent();"; }) )
جمع بندی:
یک برنامهی Vue.js را ایجاد کنید و سپس یک پوشه را در فولدر src بنام mixins بسازید. در این پوشه یک فایل را با نام دلخواهی از نوع جاوااسکریپت، ایجاد کنید و محتوای زیر را در آن قرار دهید:
export default { data() { return { title: 'Mixins are cool', copyright: 'All rights reserved. Product of super awesome people' }; }, created: function () { this.greetings(); }, methods: { greetings() { console.log('Howdy my good fellow!'); } } };
برای استفاده از mixin بشکل زیر عمل میکنیم. در واقع کد زیر شامل تمام موارد تعریف شده در myMixin.js میباشد.
<script> import myMixin from './mixins/myMixin' export default { name: 'app', //را دریافت میکند mixins آرایه ای از mixins:[myMixin] } </script> <style>
نکته: در صورتیکه بین mixin و کامپوننت، دادههای همنامی وجود داشته باشد، اولویت با داده یا تابعی است که در خود کامپوننت تعریف شدهاست. مثال زیر را در نظر بگیرید:
export default { data() { return { blogName: 'google.com' }; }, methods: { print() { console.log(this.blogName); } } };
و در کامپوننتی که از mixin فوق استفاده میکند:
<script> import myMixin from "./mixins/myMixin"; import duplicateFuncData from "./mixins/duplicateFuncData"; export default { name: "app", data() { return { // و کامپوننت جاری تکراری ست mixin نام این متغیر در blogName: "microsoft.com" }; }, methods: { // و کامپوننت جاری تکراری ست ولی عملکرد متفاوت دارد mixin نام این تابع در print() { alert(this.blogName); } }, components: {}, //را دریافت میکند mixins آرایه ای از mixins: [myMixin, duplicateFuncData] }; </script>
و نتیجهی اجرا:
تعریف mixin بصورت سراسری: وقتی یک mixin را بصورت global تعریف میکنیم، تمام نمونههای وهله سازی شده از vue، دارای قابلیتهای تعریف شدهی در mixin میباشند. کد main.js را بشکل زیر تغییر میدهیم. اکنون با اجرای برنامه، به ازای هر نمونهای از vue که وهله سازی میشود، تابع زیر اجرا میگردد.
import Vue from 'vue' import App from './App.vue' Vue.config.productionTip = false // بصورت سراسری تعریف شده Vue.mixin({ created: function () { alert('from global mixin') } }) new Vue({ render: h => h(App), }).$mount('#app')
نتیجهگیری:
1) استفاده از mixin باعث اجتناب از تکرار کدها و دادههای تکراری میشود (DRY).
2) از mixin در ساخت پلاگین برای Vue.js استفاده میشود.
// 3. inject some component options Vue.mixin({ created: function () { // some logic ... } ... })
3) اگر mixin و کامپوننتی که از mixin استفاده میکند، هر دو توابع lifecycle را پیاده سازی کرده باشند، اول توابع lifecycle مربوط به mixin اجرا میشود و سپس توابع lifecycle مربوط به کامپوننت.
4) اگر دو کامپوننت، mixin مشترکی را استفاده کنند، دادههای آنها share نخواهد شد و برای اینکه دو کامپوننتی که از mixin واحدی استفاده میکنند بتوانند از دادههای یکسانی در mixin استفاده کنند، نیاز به تزریق وابستگی دارند.
5) اگر از ادغام قسمت جاوااسکریپتی و HTML مربوط به کامپوننتها ناراضی هستید، یک راه حل جداسازی، استفاده از mixin به ازای هر کامپوننت است.
6) استفاده از mixin باعث به روزسانی، نگهداری و توسعهی سادهتر و همچنین ماژولار بودن برنامه میشود.
نکته: برای اجرای برنامه و دریافت پکیجهای مورد استفاده در مثال جاری، نیاز است دستور زیر را اجرا کنید:
npm install