顾名思义, 使用v-bind实现数据(data)=>视图(input), 使用@input事件实现视图(input)=>数据(data)
重点在v-bind
不要认为数据发生改变,界面就跟着更新,这并不是理所当然的,这其实是Vue的内部做了许多的操作
首先我们要思考两个问题
1.当data中的数据被修改时,Vue内部是如何监听data中数据的改变
首先这一部分用到了Object.defineProperty,目的是监听对象属性的改变
2.当data中的数据发生改变时,Vue是如何知道要通知哪些数据以及界面发生刷新
这一部分用到的是发布订阅者模式,这是一种设计模式, 也是由Object.defineProperty实现
[define]定义[Property]属性
该方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
Object.defineProperty(obj, prop, descriptor) //obj 对象 //prop 要定义或修改的属性的名称或 Symbol //descriptor 要定义或修改的属性描述符。 例如: Object.defineProperty(object1, 'property1', { value: 42, writable: false })
descriptor分为数据描述符和存取描述符
数据描述符:
value 任何有效的 JavaScript 值, 默认undefined
writable value值可写true/默认false
存取描述符: get set
⭐重点是两个回调函数⭐
Object.defineProperty(o, "b", { // get : function() { return bValue; }, // set : function(newValue) { bValue = newValue; }, get() { return bValue; }, set(newValue) { bValue = newValue; }, }); get() { return ...; }//当访问该属性时,会调用此函数 set(newValue) { ... }//当属性值被修改时,会调用此函数,newValue=修改的新值
一个数据变化 => 多个数据
发布者(也叫观察者)Observer的实现, Object.defineProperty() 的 set() 回调函数
1 监听数据
2 数据变化时通知Watcher
var _data_ = data() //data函数返回一个对象 _data_.forEach(function(key) { Object.defineProperty(_data_, key, { set(newValue) { key变化时触发, 通知订阅者Watcher }, }); });
依赖收集器subs=[] 的实现, Object.defineProperty() 的 get() 回调函数
var _data_ = data() //data函数返回一个对象 _data_.forEach(function(key) { Object.defineProperty(_data_, key, { get() { 访问(使用)key时触发, subs.push( target添加订阅者,就是添加data的依赖 )}, }); }); 通过Watcher得到依赖 => target _data_[key] 主动触发上边的get() 保存依赖
Compile解析指令
1 解析模板指令,将模板中的变量替换成数据,初始化渲染页面视图. 与响应式无关, 页面编译只有一次
2 获得v-bind v-text 数据依赖
3 将数据依赖传给Watcher
订阅者Watcher, 依赖于data的数据, 比如computed属性
1 能够订阅并收到每个属性变动的通知
2 执行指令绑定的相应回调函数, 就是接受 数据依赖
3 更新视图