深入双向数据绑定原理
来源:互联网 发布:表白网整站html源码 编辑:程序博客网 时间:2024/04/27 00:03
首先附上一篇好文
Vue的双向数据绑定的原理是什么呢,首先讲一下ES5的这个修改属性的方法Object.defineProperty():
这个方法接收三个参数,属性所在的对象obj,属性的名字key,一个描述符对象option;
- 当修改的是数据属性时,option包含:configurable(能否修改、删除delete)、enumerable(能否通过for-in遍历属性)、writable(能否修改属性的值)、value(属性的数据值)
- 当修改的是访问器属性时,option包含:configurable、enumerable、get(读取属性时调用的函数)、set(写入属性时调用的函数)
这里用的当然是访问器属性啦
当你把一个普通的 JavaScript 对象传给 Vue 实例的 data 选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。用户看不到 getter/setter,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。每个组件实例都有相应的 watcher 实例对象,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的 setter 被调用时,会通知 watcher 重新计算,从而致使它关联的组件得以更新。
接下来通过代码说说双向数据绑定是如何实现的吧?
import Watcher from '../watcher'import {observe} from "../observer"export default class Vue { constructor (options={}) { //这里简化了。。其实要merge this.$options=options //这里简化了。。其实要区分的 let data = this._data=this.$options.data Object.keys(data).forEach(key=>this._proxy(key)) observe(data,this) } $watch(expOrFn, cb, options){ new Watcher(this, expOrFn, cb) } _proxy(key) { var self = this Object.defineProperty(self, key, { configurable: true, enumerable: true, get: function proxyGetter () { return self._data[key] }, set: function proxySetter (val) { self._data[key] = val } }) }}
- observe的对象:通过递归,将它所有的属性,包括子属性的属性,都给加上set和get,
这样的话,给这个对象的某个属性赋值,就会触发set。
//observer.jsexport default class Observer{ constructor(value) { this.value = value this.walk(value) } //递归。。让每个字属性可以observe walk(value){ Object.keys(value).forEach(key=>this.convert(key,value[key])) } convert(key, val){ defineReactive(this.value, key, val) }}export function defineReactive (obj, key, val) { var dep = new Dep() var childOb = observe(val) Object.defineProperty(obj, key, { enumerable: true, configurable: true, get: ()=>{ // 说明这是watch 引起的 if(Dep.target){ dep.addSub(Dep.target) } return val }, set:newVal=> { var value = val if (newVal === value) { return } val = newVal childOb = observe(newVal)//如果新赋值的值是个复杂类型。再递归它,加上set/get。 dep.notify() } })}export function observe (value, vm) { if (!value || typeof value !== 'object') { return } return new Observer(value)}export default class Dep { constructor() { this.subs = [] } addSub(sub){ this.subs.push(sub) } notify(){ this.subs.forEach(sub=>sub.update()) }}
//watcher.jsexport default class Watcher { constructor(vm, expOrFn, cb) { this.cb = cb this.vm = vm //此处简化.要区分fuction还是expression,只考虑最简单的expression this.expOrFn = expOrFn this.value = this.get() } update(){ this.run() } run(){ const value = this.get() if(value !==this.value){ this.value = value this.cb.call(this.vm) } } get(){ //此处简化。。要区分fuction还是expression const value = this.vm._data[this.expOrFn] Dep.target = null return value }}
阅读全文
0 0
- 深入双向数据绑定原理
- 双向数据绑定原理
- Angular双向数据绑定原理
- vue双向数据绑定原理
- angularjs双向数据绑定原理
- Vue 双向数据绑定原理
- Vue双向数据绑定原理分析
- vue双向数据绑定的原理解密
- vue双向数据绑定的原理
- Vue.js双向数据绑定原理
- vue实现数据双向绑定原理剖析
- Vue双向数据绑定原理解析
- vue.js双向数据绑定实现原理
- angularjs双向数据绑定原理解析
- 深入理解vue.js双向绑定的实现原理
- angular 双向绑定原理
- vue双向绑定原理
- 双向数据绑定原理(三种实现方式)
- 装饰者模式
- JSON之HTML的<Input>标签存放json-yellowcong
- (剑指offer)青蛙跳台阶
- 改变我们的家居生活的三种技术"3D打印、AR/VR以及物联网"
- 基于Redis实现分布式锁
- 深入双向数据绑定原理
- javascriptAPI百度地图定位学习
- 资深程序员之路(1)--如何保证代码是没安全漏洞的
- python6+selenium自动化测试demo之一搜索测试用例
- javascript中通过document.cookie写入不了cookie的问题
- 机器学习(Machine learning: a probabilistic perspective) 第三章阅读笔记
- [MYSQL -17]组合查询
- SpringMVC之ModelAndView的用法
- 如何清除Httpclint的日志