1. 程式人生 > >vue之雙綁實現

vue之雙綁實現

config NPU IE dev 名稱 函數 complie per listen

// html

<body>
  <div id="app">
    <input type="text" v-model="number">     <input type="text" v-model="num">     <input type="button" v-click="increment" value="加1">     <input type="button" v-click="increment" value="加2">     <h3 v-bind="number"></h3>     <h3 v-bind="num"></h3>
  </div>
</body>
// js vue的實例

  window.onload = function () {
    var app = new Vue({
      el: #app,
      data: {
        number: 0,
        num: 5,
      },
      methods: {
        increment: function () {
          this.number++;
          this.num++;
        },
      }
    })
  }
// vue的構造函數

  function Vue(options) {
    
this._init(options); } Vue.prototype._init = function (options) { this.$options = options; this.$el = document.querySelector(options.el); this.$data = options.data; this.$methods = options.methods; this._binding = {}; this._obverse(this.$data); this._complie(this.$el); } Vue.prototype._obverse
= function (obj) { var _this = this for (let key in obj) { if (obj.hasOwnProperty(key)) { this._binding[key] = { _directives: [] }; let value = obj[key]; if (typeof value === object) { this._obverse(value); } let binding = this._binding[key]; Object.defineProperty(this.$data, key, { enumerable: true,//目標屬性是否可以被枚舉。true | false configurable: true, //目標屬性是否可以被刪除或是否可以再次修改特性 true | false get: function () { return value; }, set: function (newVal) { if (value !== newVal) { value = newVal; binding._directives.forEach(function (item) { item.update(); }) } } }) } } } Vue.prototype._complie = function (root) { var _this = this; var nodes = root.children; for (let i = 0; i < nodes.length; i++) { let node = nodes[i]; if (node.children.length) { _this._complie(node); } if (node.hasAttribute(v-click)) { node.onclick = (function () { var attrVal = nodes[i].getAttribute(v-click); return _this.$methods[attrVal].bind(_this.$data); })(i); } if (node.hasAttribute(v-model) && (node.tagName == INPUT || node.tagName == TEXTAREA)) { node.addEventListener(input, (function() { var attrVal = node.getAttribute(v-model); _this._binding[attrVal]._directives.push(new Watcher( input, node, _this, attrVal, value )) return function () { _this.$data[attrVal] = nodes[key].value; } })()); } if(node.hasAttribute("v-bind")){ var attrVal = node.getAttribute(v-bind); _this._binding[attrVal]._directives.push(new Watcher( text, node, _this, attrVal, innerHTML )) } } } function Watcher(name, el, vm, exp, attr) { this.name = name; //指令名稱,例如文本節點,該值設為"text" this.el = el; //指令對應的DOM元素 this.vm = vm; //指令所屬myVue實例 this.exp = exp; //指令對應的值,本例如"number" this.attr = attr; //綁定的屬性值,本例為"innerHTML" this.update(); } Watcher.prototype.update = function () { this.el[this.attr] = this.vm.$data[this.exp]; }

vue之雙綁實現