onLoad(option) { _self = this; _self.$data.xxxx = "te"; }
元素~~~~html
<input @click="categoryChange" :data-id="item.id" />
方法node
methods: { tabSelect(e) { this.TabCur = e.currentTarget.dataset.id; }, }
https://www.cnblogs.com/wangjiachen666/p/9883916.html缓存
Vue内部经过Object.defineProperty方法属性拦截的方式,把data对象里每一个数据的读写转化成getter/setter,当数据变化时通知视图更新。
也就是说:
输入框内容变化时,data 中的数据同步变化。即 view => model 的变化。
data 中的数据变化时,文本节点的内容同步变化。即 model => view 的变化。函数
Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。this
完成了数据的'可观测',即咱们知道了数据在何时被读或写了,那么,咱们就能够在数据被读或写的时候通知那些依赖该数据的视图更新了,为了方便,咱们须要先将全部依赖收集起来,一旦数据发生变化,就统一通知更新。其实,这就是典型的“发布订阅者”模式,数据变化为“发布者”,依赖对象为“订阅者”。双向绑定
订阅者Watcher 是一个 类,在它的构造函数中,定义了一些属性:code
vm:一个Vue的实例对象;
exp:是node节点的v-model或v-on:click等指令的属性值。如v-model="name",exp就是name;
cb:是Watcher绑定的更新函数;server
实现数据的双向绑定,首先要对数据进行劫持监听,因此咱们须要设置一个监听器Observer,用来监听全部属性。若是属性发上变化了,就须要告诉订阅者Watcher看是否须要更新。由于订阅者是有不少个,因此咱们须要有一个消息订阅器Dep来专门收集这些订阅者,而后在监听器Observer和订阅者Watcher之间进行统一管理的。htm
index.html对象
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <h1 id="name"></h1> <input type="text"> <input type="button" value="改变data内容" onclick="changeInput()"> <script src="observer.js"></script> <script src="watcher.js"></script> <script> function myVue (data, el, exp) { this.data = data; observable(data); //将数据变的可观测 el.innerHTML = this.data[exp]; // 初始化模板数据的值 new Watcher(this, exp, function (value) { el.innerHTML = value; }); return this; } var ele = document.querySelector('#name'); var input = document.querySelector('input'); var myVue = new myVue({ name: 'hello world' }, ele, 'name'); //改变输入框内容 input.oninput = function (e) { myVue.data.name = e.target.value } //改变data内容 function changeInput(){ myVue.data.name = "难凉热血" } </script> </body> </html>
observer.js
/** * 把一个对象的每一项都转化成可观测对象 * @param { Object } obj 对象 */ function observable (obj) { if (!obj || typeof obj !== 'object') { return; } let keys = Object.keys(obj); keys.forEach((key) =>{ defineReactive(obj,key,obj[key]) }) return obj; } /** * 使一个对象转化成可观测对象 * @param { Object } obj 对象 * @param { String } key 对象的key * @param { Any } val 对象的某个key的值 */ function defineReactive (obj,key,val) { let dep = new Dep(); Object.defineProperty(obj, key, { get(){ dep.depend(); console.log(`${key}属性被读取了`); return val; }, set(newVal){ val = newVal; console.log(`${key}属性被修改了`); dep.notify() //数据变化通知全部订阅者 } }) } class Dep { constructor(){ this.subs = [] } //增长订阅者 addSub(sub){ this.subs.push(sub); } //判断是否增长订阅者 depend () { if (Dep.target) { this.addSub(Dep.target) } } //通知订阅者更新 notify(){ this.subs.forEach((sub) =>{ sub.update() }) } } Dep.target = null;
watcher.js
class Watcher { constructor(vm,exp,cb){ this.vm = vm; this.exp = exp; this.cb = cb; this.value = this.get(); // 将本身添加到订阅器的操做 } get(){ Dep.target = this; // 缓存本身 let value = this.vm.data[this.exp] // 强制执行监听器里的get函数 Dep.target = null; // 释放本身 return value; } update(){ let value = this.vm.data[this.exp]; let oldVal = this.value; if (value !== oldVal) { this.value = value; this.cb.call(this.vm, value, oldVal); } } }