摘要:响应式原理作为写业务的码农,几乎不必知道原理。所以找工作之前可以先复习下,只要是关于的,必定会问响应式原理。如果是,运行其方法,其方法中含有的值时,会触发收集当更新时,也会触发更新重新获取值如果是会触发的函数响应式原理计算属性值这是
Vue响应式原理
作为写业务的码农,几乎不必知道原理。但是当你去找工作的时候,可是需要造原子弹的,什么都得知道一些才行。所以找工作之前可以先复习下,只要是关于vue的,必定会问响应式原理。
核心:
//es5 Object.defineProperty(obj,key,{ get() { // 获取obj[key]的时候触发 }, set(val) { // obj[key] = "xxx"时触发 } })
其实,只需要在修改data值的时候,需要触发一个回调方法,来更新与此值有关的数据,就完了。但是你面试的时候,那些大佬可不会觉得是这样的,需要把整个流程说明白才行。
简单的Vue响应式代码如下: Vue.js:class Vue { constructor(opts) { this.opts = opts if (opts.data) this.initData(opts.data); if (opts.watch) this.initWatch(opts.watch); if (opts.computed) this.initComputed(opts.computed); if (opts.el) this.$mount(opts.el) } initData(data) { // 让data上的数据被get的时候能够搜集watcher,data变为观察者 new Observable(data); this.data = data // 数据可在this上直接读取 Object.keys(data).forEach(key => { this.proxy(key) }) } initWatch(watch) { Object.keys(watch).forEach(key => { // new Watcher(this, key, watch[key]) }) } initComputed(data) { Object.keys(data).forEach(key => { new Watcher(this, key) this.proxy(key, { get: data[key], }) }) } $mount(el) { el = document.querySelector(el) this.template = el.innerHTML this.el = el const fn = _ => { const nwTemp = this.parseHTML(this.template) this.el.innerHTML = nwTemp if(this.opts.mounted) { this.opts.mounted.call(this) } } new Watcher(this, fn) } parseHTML(template) { return template.replace(/{{(.*?)}}/g, (str, str1) => { return this[str1.trim()] }) } // 将数据直接挂到this上,使用getterSetter代理,获取vm.data上的值 proxy(key, getterSetter) { const vm = this getterSetter = getterSetter || { set(value) { vm.data[key] = value }, get() { return vm.data[key] } } Object.defineProperty(vm, key, getterSetter) } } // 给data作为观察者用的 class Observable { constructor(obj) { Object.keys(obj).forEach(key => { this.defineReact(obj, key, obj[key]) }); } defineReact(obj, key, value) { const dep = new Dep() Object.defineProperty(obj, key, { get() { // 获取data里面信息的时候,能够搜集依赖,这些依赖都是watcher实例 if (Dep.target) { dep.append(Dep.target) } return value }, set(val) { value = val // 修改data里面数据的时候,去通知已搜集的依赖更新 dep.notify() } }) } } // 搜集与触发wacher class Dep { constructor() { this.subs = [] } append(watcher) { // 避免重复添加watcher // watcher 在update的时候,会重新获取值,此时不必再添加 if(this.subs.includes(watcher)) return this.subs.push(watcher) } notify() { this.subs.forEach(watcher => { watcher.update() }) } } Dep.target = null class Watcher { // keyOrFn 为字符串或者function,opts.watch为字符串,computed,$mount中为function constructor(vm, keyOrFn, cb) { this.cb = cb if (typeof keyOrFn === "string") { this.getter = function () { return vm[keyOrFn] // 例:initWatch时,watch:{a(){}} ,a为data里的数据,此处获取vm.a会触发a的收集 } } else { this.getter = keyOrFn // 如果为fn(computed中)值为此函数的返回值 } this.value = this.get() } get() { Dep.target = this // 此watcher记录下来 const value = this.getter(this.vm) // 运行getter,如果是watch,获取一次data里的值,完成收集。 // 如果是computed,运行其方法,其方法中含有data的值时,会触发收集 // 当更新时,也会触发getter Dep.target = null return value } update() { // 更新 const oldValue = this.value // 重新获取值 this.value = this.get() if (this.cb) { //如果是watch,会触发watch的函数 this.cb.call(this.vm, this.value, oldValue) } } }index.html
Vue响应式原理
msg: {{ msg }}
num: {{ num }}
num+1计算属性值:{{ add1 }}
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/104174.html
摘要:工程实践立足实践,提示实际水平内联函数与性能很多关于性能优化的文章都会谈及内联函数,其也是常见的被诟病为拖慢性能表现的元凶之一不过本文却是打破砂锅问到底,论证了内联函数并不一定就会拖慢性能,过度的性能优化反而会有损于应用性能。 showImg(https://segmentfault.com/img/remote/1460000011481413?w=1240&h=825); 前端每周...
摘要:深入学习作为配合使用的数据状态管理库,针对解决兄弟组件或多层级组件共享数据状态的痛点问题来说,非常好用。至此,构造函数部分已经过了一遍了。 深入学习Vuex vuex作为配合vue使用的数据状态管理库,针对解决兄弟组件或多层级组件共享数据状态的痛点问题来说,非常好用。本文以使用者的角度,结合源码来学习vuex。其中也参考了许多前辈的文章,参见最后的Reference Vue加载Vuex...
阅读 3819·2021-11-18 13:22
阅读 1748·2021-11-17 09:33
阅读 2857·2021-09-26 09:46
阅读 1142·2021-08-21 14:11
阅读 2839·2019-08-30 15:53
阅读 2646·2019-08-30 15:52
阅读 1840·2019-08-30 10:52
阅读 1494·2019-08-29 15:30