Heim > Web-Frontend > js-Tutorial > Verwendung des Attributs defineProperty von vue

Verwendung des Attributs defineProperty von vue

php中世界最好的语言
Freigeben: 2018-06-07 14:49:13
Original
2861 Leute haben es durchsucht

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是否可以枚举
Nach dem Login kopieren

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])
}
Nach dem Login kopieren

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两个属性
Nach dem Login kopieren

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); // 书记
Nach dem Login kopieren

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>
Nach dem Login kopieren
-Seite ist sehr einfach; Es enthält:

    eine Eingabe unter Verwendung der V-Modell-Anweisung
  1. eine Schaltfläche unter Verwendung der V-Klick-Anweisung
  2. An h3, verwenden Sie den Befehl v-bind.
  3. Wir werden schließlich eine bidirektionale Datenbindung ähnlich wie bei Vue-Paaren implementieren
var app = new xhVue({
  el:'#app',
  data: {
  number: 0
  },
  methods: {
  increment: function() {
   this.number ++;
  },
  }
 })
Nach dem Login kopieren

2.1 Definition

Zuerst müssen wir definieren ein xhVue-Konstruktor

function xhVue(options){
 
}
Nach dem Login kopieren

2.2 Fügen Sie

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
}
Nach dem Login kopieren

2.3 Transformation und Upgrade

Ä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实时更新
}
Nach dem Login kopieren

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(); 
      });
     }
    }
   })
  }
 }
}
Nach dem Login kopieren

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(&#39;v-click&#39;)) {
   node.onclick = (function () {
    var attrVal = nodes[i].getAttribute(&#39;v-click&#39;);
    // bind让data的作用域与methods函数的作用域保持一致
    return _this.$method[attrVal].bind(_this.$data);
   })();
  };
  // 如果有v-model属性;并且元素是input或者textrea;我们监听他的input事件
  if (node.hasAttribute(&#39;v-model&#39;) && (node.tagName = &#39;INPUT&#39; || node.tagName == &#39;TEXTAREA&#39;)) {
   node.addEventListener(&#39;input&#39;, (function (key) {
    var attrVal = node.getAttribute(&#39;v-model&#39;);
    _this._binding[attrVal]._directives.push(new xhWatcher(
     &#39;input&#39;, 
     node, 
     _this,
     attrVal, 
     &#39;value&#39;
    ));
    return function () {
     // 让number的值和node的value保持一致;就实现了双向数据绑定
     _this.$data[attrVal] = nodes[key].value
    }
   })(i));
  };
  // 如果有v-bind属性;我们要让node的值实时更新为data中number的值
  if (node.hasAttribute(&#39;v-bind&#39;)) {
   var attrVal = node.getAttribute(&#39;v-bind&#39;);
   _this._binding[attrVal]._directives.push(new xhWatcher(
    &#39;text&#39;, 
    node, 
    _this,
    attrVal,
    &#39;innerHTML&#39;
   ))
  }
 }
}
Nach dem Login kopieren

并且将解析函数也加到_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);
}
Nach dem Login kopieren

最后

<!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(&#39;v-click&#39;)) {
    node.onclick = (function () {
     var attrVal = node.getAttribute(&#39;v-click&#39;);
     console.log(attrVal);
     // bind让data的作用域与method函数的作用域保持一致
     return _this.$method[attrVal].bind(_this.$data);
    })();
   };
   // 如果有v-model属性;并且元素是input或者textrea;我们监听他的input事件
   if (node.hasAttribute(&#39;v-model&#39;) && (node.tagName = &#39;INPUT&#39; || node.tagName == &#39;TEXTAREA&#39;)) {
    node.addEventListener(&#39;input&#39;, (function (key) {
     var attrVal = node.getAttribute(&#39;v-model&#39;);
     _this._binding[attrVal]._directives.push(new xhWatcher(
      &#39;input&#39;,
      node,
      _this,
      attrVal,
      &#39;value&#39;
     ));
     return function () {
      // 让number的值和node的value保持一致;就实现了双向数据绑定
      _this.$data[attrVal] = nodes[key].value
     }
    })(i));
   };
   // 如果有v-bind属性;我们要让node的值实时更新为data中number的值
   if (node.hasAttribute(&#39;v-bind&#39;)) {
    var attrVal = node.getAttribute(&#39;v-bind&#39;);
    _this._binding[attrVal]._directives.push(new xhWatcher(
     &#39;text&#39;,
     node,
     _this,
     attrVal,
     &#39;innerHTML&#39;
    ))
   }
  }
 }
 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: &#39;#app&#39;,
  data: {
   number: 0
  },
  methods: {
   increment: function () {
    this.number++;
   }
  }
 });
</script>
</html>
Nach dem Login kopieren

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

怎样使用jQuery滚动条美化插件nicescroll

Angular中怎样调用第三方库

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!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage