Dieses Mal werde ich Ihnen die Verwendung des defineProperty-Attributs von vue vorstellen. Was sind die Vorsichtsmaßnahmen für die Verwendung des defineProperty-Attributs von vue? Das Folgende ist ein praktischer Fall.
1. Prinzip
Ich glaube, jeder kennt das Prinzip der bidirektionalen Datenbindung, hauptsächlich durch das defineProperty-Attribut des ES5-Objekts Set- und Get-Funktionen sind implementiert
, daher werden wir ES6 in Zukunft nicht mehr für die eigentliche Codeentwicklung verwenden. Wenn die Funktion während des Prozesses die übergeordnete Funktion verwendet, sollten wir weiterhin die Zwischenvariablen und Schließungen für den Anzeigecache verwenden Der Grund dafür ist, dass die Pfeilfunktion keinen unabhängigen Ausführungskontext hat. Wenn dieses Objekt also innerhalb der Pfeilfunktion erscheint, greift es direkt auf das übergeordnete Objekt zu, sodass die Pfeilfunktion die Verwendung nicht vollständig ersetzen kann Szenario der Funktion; zum Beispiel, wenn wir dies oder das Argument unabhängig benötigen
1.2 Was ist defineProperty
Syntax:
Object.defineProperty(obj , Requisite, Deskriptor)
Parameter:
obj: notwendiges Zielobjekt
prop: notwendiger Attributname, der definiert oder geändert werden muss
Deskriptor: notwendiges Attribut, das allen Zielattributen gehört
Rückgabewert:
Gibt die erste übergebene Funktion zurück, d. h. den ersten Parameter obj
Diese Methode ermöglicht das präzise Hinzufügen oder Ändern von Die durch Zuweisung hinzugefügten Eigenschaften werden in der Attributaufzählung angezeigt (fon...in; object.key); einige Eigenschaften können hierfür auch geändert oder gelöscht werden Attribut; z. B. ob es schreibgeschützt und nicht beschreibbar ist; derzeit werden zwei Formen bereitgestellt: Datenbeschreibung (set; get; value; beschreibbar; aufzählbar; konfigurierbar) und Accessorbeschreibung (set; get)
Datenbeschreibung
Beim Ändern oder Definieren des Objekts Wenn ein bestimmtes Attribut hinzugefügt wird; fügen Sie diesem Attribut einige Eigenschaften hinzu
var obj = { name:'xiangha' } // 对象已有的属性添加特性描述 Object.defineProperty(obj,'name',{ configurable:true | false, // 如果是false则不可以删除 enumerable:true | false, // 如果为false则在枚举时候会忽略 value:'任意类型的值,默认undefined' writable:true | false // 如果为false则不可采用数据运算符进行赋值 }); 但是存在一个交叉;如果wrirable为true;而configurable为false的时候;所以需要枚举处理enumerable为false --- 我是一个writable栗子 --- var obj = {}; Object.defineProperty(obj,'val',{ value:'xiangha', writable:false, // false enumerable:true, configurable:true }); obj.val = '书记'; // 这个时候是更改不了a的 --- 我是一个configurable栗子 --- var obj = {}; Object.defineProperty(obj,'val',{ value:'xiangha', writable:true, // true enumerable:true, configurable:false // false }); obj.val = '书记'; // 这个时候是val发生了改变 delete obj.val 会返回false;并且val没有删除 --- 我是一个enumerable栗子 --- var obj = {}; Object.defineProperty(obj,'val',{ value:'xiangha', writable:true, enumerable:false, // false configurable:true }); for(var i in obj){ console.log(obj[i]) // 没有具体值 } 综上:对于我们有影响主要是configurable控制是否可以删除;writable控制是否可以修改赋值;enumerable是否可以枚举
Wenn Sie also Object.defineProperty() verwenden, um Attribute hinzuzufügen das Objekt; wenn Sie dann die Eigenschaften des Attributs nicht festlegen; der Standardwert ist false
var obj = {}; Object.defineProperty(obj,'name',{}); // 定义了心属性name后;这个属性的特性的值都为false;这就导致name这个是不能重写不能枚举不能再次设置特性的 obj.name = '书记'; console.log(obj.name); // undefined for(var i in obj){ console.log(obj[i]) }
Zusammenfassungsfunktionen:
Wert: Legen Sie den Wert des Attributs fest
writable ['raɪtəbl]: Ob der Wert überschrieben werden kann
enumerable [ɪ'nju:mərəbəl] : Ob das Zielattribut aufgezählt werden kann
konfigurierbar [kən'fɪgərəbl] ]: Ob das Zielattribut gelöscht werden kann und ob das Attribut erneut geändert werden kann
Accessor-Beschreibung
var obj = {}; Object.defineProperty(obj,'name',{ get:function(){} | undefined, set:function(){} | undefined, configuracble:true | false, enumerable:true | false }) 注意:当前使用了setter和getter方法;不允许使用writable和value两个属性
gettet&& setter
Beim Einstellen, um ein bestimmtes Attribut des Objekts zu erhalten, können Sie Getter und angeben Setter-Methoden
var obj = {}; var value = 'xiangha'; Object.defineProperty(obj,'name',{ get:function(){ // 获取值触发 return value }, set:function(val){ // 设置值的时候触发;设置的新值通过参数val拿到 value = val; } }); console.log(obj.name); // xiangha obj.name = '书记'; console,.log(obj.name); // 书记
get und set müssen nicht paarweise erscheinen; wenn Sie keine set- und get-Methode verwenden, ist sie undefiniert
Haha; abgeschlossen
Ergänzung: Wenn Sie Vue zum Entwickeln eines Projekts verwenden und versuchen, das Datenobjekt zu drucken, finden Sie jedes Attribut in den Daten. Beide verfügen über Methoden zum Abrufen und Festlegen von Attributen. Hier finden Sie eine Beschreibung des Unterschieds bei der bidirektionalen Datenbindung zwischen Vue und Angular
Angular verwendet die Erkennung fehlerhafter Daten; wenn sich das Modell ändert, wird erkannt, ob alle Ansichten an relevante Daten gebunden sind; Aktualisieren Sie die Ansicht
vue verwendet der Publish-Subscribe-Modus; Punkt-zu-Punkt-Bindungsdaten
2. Die <p id="app">
<form>
<input type="text" v-model="number">
<button type="button" v-click="increment">增加</button>
</form>
<h3 v-bind="number"></h3>
</p>
var app = new xhVue({ el:'#app', data: { number: 0 }, methods: { increment: function() { this.number ++; }, } })
Zuerst müssen wir definieren ein xhVue-Konstruktor
function xhVue(options){ }
hinzu, um diesen Konstruktor zu initialisieren; fügen Sie ihm ein _init-Attribut hinzu
function xhVue(options){ this._init(options); } xhVue.prototype._init = function(options){ this.$options = options; // options为使用时传入的结构体;包括el,data,methods等 this.$el = document.querySelector(options.el); // el就是#app,this.$el是id为app的Element元素 this.$data = options.data; // this.$data = {number:0} this.$methods = options.methods; // increment }
Ändern Sie die Funktion _init und implementieren Sie die Funktion _xhob
指令类watcher;用来绑定更新函数;实现对DOM更新
function xhWatcher(name,el,vm,exp,attr){ this.name = name; // 指令名称;对于文本节点;例如text this.el = el; // 指令对应DOM元素 this.vm = vm; // 指令所属vue实例 this.exp = exp; // 指令对应的值;例如number this.attr = attr; // 绑定的属性值;例如innerHTML this.update(); } xhWatcher.prototype.update = function(){ this.el[this.attr] = this.vm.$data[this.exp]; // 例如h3的innerHTML = this.data.number;当numner改变则会触发本update方法;保证对应的DOM实时更新 }
2.5 完善_init和_xhob
继续完善_init和_xhob函数
// 给init的时候增加一个对象来存储model和view的映射关系;也就是我们前面定义的xhWatcher的实例;当model发生变化时;我们会触发其中的指令另其更新;保证了view也同时更新 xhVue.prototype._init = function(options){ this.$options = options; this.$el = document.querySelector(options.el); this.$data = options.data; this.$method = options.methods; this._binding = {}; // _binding this._xhob(this.$data); } // 通过init出来的_binding xhVue.prototype._xhob = function(obj){ // obj = {number:0} var value; for(key in obj){ if(obj.hasOwnProperty(ket)){ this._binding[key] = { // _binding = {number:_directives:[]} _directives = [] } value = obj[key]; if(typeof value === 'object'){ this._xhob(value); } var binding = this._binding[key]; Object.defineProperty(this.$data,key,{ enumerable:true, configurable:true, get:function(){ return value; }, set:function(newVal){ if(value !== newVal){ value = newVal; // 当number改变时;触发_binding[number]._directives中已绑定的xhWatcher更新 binding._directives.forEach(function(item){ item.update(); }); } } }) } } }
2.6 解析指令
怎么才能将view与model绑定;我们定义一个_xhcomplie函数来解析我们的指令(v-bind;v-model;v-clickde)并这这个过程中对view和model进行绑定
xhVue.prototype._xhcompile = function (root) { // root是id为app的element的元素;也就是根元素 var _this = this; var nodes = root.children; for (var i = 0,len = nodes.length; i < len; i++) { var node = nodes[i]; if (node.children.length) { // 所有元素进行处理 this._xhcompile(node) }; // 如果有v-click属性;我们监听他的click事件;触发increment事件,即number++ if (node.hasAttribute('v-click')) { node.onclick = (function () { var attrVal = nodes[i].getAttribute('v-click'); // bind让data的作用域与methods函数的作用域保持一致 return _this.$method[attrVal].bind(_this.$data); })(); }; // 如果有v-model属性;并且元素是input或者textrea;我们监听他的input事件 if (node.hasAttribute('v-model') && (node.tagName = 'INPUT' || node.tagName == 'TEXTAREA')) { node.addEventListener('input', (function (key) { var attrVal = node.getAttribute('v-model'); _this._binding[attrVal]._directives.push(new xhWatcher( 'input', node, _this, attrVal, 'value' )); return function () { // 让number的值和node的value保持一致;就实现了双向数据绑定 _this.$data[attrVal] = nodes[key].value } })(i)); }; // 如果有v-bind属性;我们要让node的值实时更新为data中number的值 if (node.hasAttribute('v-bind')) { var attrVal = node.getAttribute('v-bind'); _this._binding[attrVal]._directives.push(new xhWatcher( 'text', node, _this, attrVal, 'innerHTML' )) } } }
并且将解析函数也加到_init函数中
xhVue.prototype._init = function(options){ this.$options = options; this.$el = document.querySelector(options.el); this.$data = options.data; this.$method = options.methods; this._binding = {}; // _binding this._xhob(this.$data); this._xhcompile(this.$el); }
最后
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <p id="app"> <form> <input type="text" v-model="number"> <button type="button" v-click="increment">增加</button> </form> <h3 v-bind="number"></h3> </p> </body> <script> function xhVue(options) { this._init(options); } xhVue.prototype._init = function (options) { this.$options = options; this.$el = document.querySelector(options.el); this.$data = options.data; this.$method = options.methods; this._binding = {}; // _binding this._xhob(this.$data); this._xhcompile(this.$el); } xhVue.prototype._xhob = function (obj) { var value; for (key in obj) { if (obj.hasOwnProperty(key)) { this._binding[key] = { _directives: [] } value = obj[key]; if (typeof value === 'object') { this._xhob(value); } var binding = this._binding[key]; Object.defineProperty(this.$data, key, { enumerable: true, configurable: true, get: function () { console.log(`get${value}`) return value; }, set: function (newVal) { if (value !== newVal) { value = newVal; console.log(`set${newVal}`) // 当number改变时;触发_binding[number]._directives中已绑定的xhWatcher更新 binding._directives.forEach(function (item) { item.update(); }); } } }) } } } xhVue.prototype._xhcompile = function (root) { // root是id为app的element的元素;也就是根元素 var _this = this; var nodes = root.children; for (var i = 0, len = nodes.length; i < len; i++) { var node = nodes[i]; if (node.children.length) { // 所有元素进行处理 this._xhcompile(node) }; // 如果有v-click属性;我们监听他的click事件;触发increment事件,即number++ if (node.hasAttribute('v-click')) { node.onclick = (function () { var attrVal = node.getAttribute('v-click'); console.log(attrVal); // bind让data的作用域与method函数的作用域保持一致 return _this.$method[attrVal].bind(_this.$data); })(); }; // 如果有v-model属性;并且元素是input或者textrea;我们监听他的input事件 if (node.hasAttribute('v-model') && (node.tagName = 'INPUT' || node.tagName == 'TEXTAREA')) { node.addEventListener('input', (function (key) { var attrVal = node.getAttribute('v-model'); _this._binding[attrVal]._directives.push(new xhWatcher( 'input', node, _this, attrVal, 'value' )); return function () { // 让number的值和node的value保持一致;就实现了双向数据绑定 _this.$data[attrVal] = nodes[key].value } })(i)); }; // 如果有v-bind属性;我们要让node的值实时更新为data中number的值 if (node.hasAttribute('v-bind')) { var attrVal = node.getAttribute('v-bind'); _this._binding[attrVal]._directives.push(new xhWatcher( 'text', node, _this, attrVal, 'innerHTML' )) } } } function xhWatcher(name, el, vm, exp, attr) { this.name = name; // 指令名称;对于文本节点;例如text this.el = el; // 指令对应DOM元素 this.vm = vm; // 指令所属vue实例 this.exp = exp; // 指令对应的值;例如number this.attr = attr; // 绑定的属性值;例如innerHTML this.update(); } xhWatcher.prototype.update = function () { this.el[this.attr] = this.vm.$data[this.exp]; // 例如h3的innerHTML = this.data.number;当numner改变则会触发本update方法;保证对应的DOM实时更新 } var app = new xhVue({ el: '#app', data: { number: 0 }, methods: { increment: function () { this.number++; } } }); </script> </html>
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
Das obige ist der detaillierte Inhalt vonVerwendung des Attributs defineProperty von vue. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!