vue之双绑实现
// 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]; }
“我相当乐意花一天的时间通过编程把一个任务实现自动化,除非这个任务手动只需要10秒钟就能完成”