vue中的数据绑定原理的实现
本文主要介绍了vue中的数据绑定原理的实现,分享给大家,也给自己留个笔记,具体如下: vue中的响应式数据绑定是通过数据劫持和观察者模式来实现的。当前学习源码为vue2.0 源码关键目录 当我们实例化一个vue应用的时候,会伴随着各种的初始化工作,相关的初始化工作代码在init.js文件中 Vue.prototype._init = function (options?: Object) {
... initLifecycle(vm) initEvents(vm) callHook(vm,'beforeCreate') initState(vm) callHook(vm,'created') initRender(vm) } 在这里可以看到对state的初始化工作initState() export function initState (vm: Component) {
vm._watchers = [] initProps(vm) initData(vm) initComputed(vm) initMethods(vm) initWatch(vm) } 可以看到这里有对各种sate的初始化工作,我们看initData() function initData (vm: Component) {
let data = vm.$options.data data = vm._data = typeof data === 'function' ? data.call(vm) : data || {} if (!isPlainObject(data)) { data = {} process.env.NODE_ENV !== 'production' && warn( 'data functions should return an object.',vm ) } // proxy data on instance const keys = Object.keys(data) const props = vm.$options.props let i = keys.length while (i--) { if (props && hasOwn(props,keys[i])) { process.env.NODE_ENV !== 'production' && warn( The data property "${keys[i]}" is already declared as a prop. +Use prop default value instead. ,vm) } else { proxy(vm,keys[i]) } } // observe data observe(data) data.ob && data.ob.vmCount++ } 这里做了一点判断,判断data方法是否返回的是一个对象,以及props中是否有与data中重名的属性,最后会调用observe对data进行监听,看一下observe export function observe (value: any): Observer | void {
if (!isObject(value)) { return } let ob: Observer | void if (hasOwn(value,'ob') && value.ob instanceof Observer) { ob = value.ob } else if ( observerState.shouldConvert && !config._isServer && (Array.isArray(value) || isPlainObject(value)) && Object.isExtensible(value) && !value._isVue ) { ob = new Observer(value) } return ob } 可已看到这里也是做了一点判断,如果有__ob__属性的话就用它,或者如果data是数组或对象或可扩展对象的话,就为它新建一个Observer,看一下Observer export class Observer {
value: any; dep: Dep; vmCount: number; // number of vms that has this object as root $data constructor (value: any) { /**
/**
判断data是不是数组,如果是数组就对数组元素再去调用observe方法做同样的处理,如果不是,就调用walk去劫持该数据,对数据的劫持主要再defineReactive方法中,正如函数名,让数据变得响应式。看一下defineReactive方法 export function defineReactive (
obj: Object,key: string,val: any,customSetter?: Function ) { const dep = new Dep() // data中的每一个成员都有一个对应的Dep,在此闭包创建。 const property = Object.getOwnPropertyDescriptor(obj,key) // cater for pre-defined getter/setters let childOb = observe(val) 遍历状态,修改状态的getter和setter,当页面上对应状态被首次渲染的时候,会为页面上每一个使用到data的地方新建一个watcher,并将当前watcher保存到全局变量Dep.target中,在对应data的getter中就会调用Dep.depend方法,将当前的watcher添加到当前的Dep中,一个Dep对应一个或多个watcher,着取决于,此状态被使用的数量。当data被修改时,对应的setter就会被触发,会调用对应的Dep中的notify方法,通知所有观察者,进行更新。 这里出现了两个定的类:Dep和Watcher,其中Dep管理观察者,Wathcer代表观察者 先看一下Dep export default class Dep {
static target: ?Watcher; id: number; subs: Array constructor () { addSub (sub: Watcher) { removeSub (sub: Watcher) { depend () { notify () { 看一下watcher.js export default class Watcher {
... addDep (dep: Dep) { const id = dep.id if (!this.newDepIds.has(id)) { this.newDepIds.add(id) this.newDeps.push(dep) if (!this.depIds.has(id)) { // 将当前watcher添加到当前的Dep中 dep.addSub(this) } } } ... } 总结vue的响应式数据绑定主要依赖Object.defineProperty和观察者模式。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程之家。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |