本文主要介绍了vue中的数据绑定原理的实现,分享给大家,也给自己留个笔记,具体如下:
vue中的响应式数据绑定是通过数据劫持和观察者模式来实现的。当前学习源码为vue2.0
源码关键目录
src |---core | |---instance | |---init.js | |---state.js | |---observer | |---dep.js | |---watcher.js
当我们实例化一个vue应用的时候,会伴随着各种的初始化工作,相关的初始化工作代码在init.js文件中
// src/core/instance/init.js Vue.prototype._init = function (options"htmlcode">// src/core/instance/state.js export function initState (vm: Component) { vm._watchers = [] initProps(vm) initData(vm) initComputed(vm) initMethods(vm) initWatch(vm) }可以看到这里有对各种sate的初始化工作,我们看initData()
// src/core/instance/state.js function initData (vm: Component) { let data = vm.$options.data data = vm._data = typeof data === 'function' "${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
// src/core/observer/index.js 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
// src/core/observer/index.js export class Observer { value: any; dep: Dep; vmCount: number; // number of vms that has this object as root $data constructor (value: any) { this.value = value this.dep = new Dep() this.vmCount = 0 def(value, '__ob__', this) if (Array.isArray(value)) { const augment = hasProto "htmlcode">// src/core/observer/index.js export function defineReactive ( obj: Object, key: string, val: any, customSetter"htmlcode">// src/core/observer/dep.js export default class Dep { static target: "htmlcode">// src/core/observer/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和观察者模式。
- 在我们新建一个vue实例的时候,做一系列的初始化工作,这部分的逻辑集中在src文件夹下的core文件夹下的instance和observer文件夹内
- 响应式数据绑定是在状态的初始化阶段完成的,在initState方法中的initData中进行data的数据绑定。
- 在initData中调用observe方法,为该data新建一个Observer类,然后最终调用为data中的每一个成员调用walk方法,在walk中通过defineReactive方法劫持当前数据
- 在defineReactive中通过Object.defineProperty去修改数据的getter和setter
- 在页面渲染的时候,页面上每一个用到data的地方都会生成一个watcher,并将它保存到全局变量Dep.target中,watcher改变每一个观察者,Dep用来管理观察者。
- 然后在data的getter中将调用Dep的depend方法,将Dep.target中的watcher添加到此data对应的Dep中,完成依赖收集
- 在data被修改的时候,对应data的setter方法就会被出动,会调用Dep.notify()方法发布通知,调用每个watcher的uptade方法进行更新。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
暂无评论...
更新日志
2024年11月25日
2024年11月25日
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]