应用开发

关于Vue.js的响应式原理

时间:2010-12-5 17:23:32  作者:IT科技   来源:应用开发  查看:  评论:0
内容摘要:写在前面因为对Vue.js很感兴趣,而且平时工作的技术栈也是Vue.js,这几个月花了些时间研究学习了一下Vue.js源码,并做了总结与输出。文章的原地址:https://github.com/ans

写在前面

因为对Vue.js很感兴趣,关于而且平时工作的式原技术栈也是Vue.js,这几个月花了些时间研究学习了一下Vue.js源码,关于并做了总结与输出。式原

文章的关于原地址:https://github.com/answershuto/learnVue。

在学习过程中,式原为Vue加上了中文的关于注释https://github.com/answershuto/learnVue/tree/master/vue-src,希望可以对其他想学习Vue源码的式原小伙伴有所帮助。

可能会有理解存在偏差的关于地方,欢迎提issue指出,式原共同学习,关于共同进步。式原

关于Vue.js

Vue.js是关于一款MVVM框架,上手快速简单易用,式原通过响应式在修改数据的关于时候更新视图。服务器租用Vue.js的响应式原理依赖于Object.defineProperty,尤大大在Vue.js文档中就已经提到过,这也是Vue.js不支持E8 以及更低版本浏览器的原因。Vue通过设定对象属性的 setter/getter 方法来监听数据的变化,通过getter进行依赖收集,而每个setter方法就是一个观察者,在数据变更的时候通知订阅者更新视图。

将数据data变成可观察(observable)的

那么Vue是如何将所有data下面的所有属性变成可观察的(observable)呢?

function observer(value) {      Object.keys(value).forEach((key) => defineReactive(value, key, value[key] , cb)) } function defineReactive (obj, key, val, cb) {      Object.defineProperty(obj, key, {          enumerable: true,         configurable: true,         get: ()=>{              /*....依赖收集等....*/         },         set:newVal=> {              cb();/*订阅者收到消息的回调*/         }     }) } class Vue {      constructor(options) {          this._data = options.data;         observer(this._data, options.render)     } } let app = new Vue({      el: #app,     data: {          text: text,         text2: text2     },     render(){          console.log("render");     } })  

为了便于理解,首先考虑一种最简单的情况,站群服务器不考虑数组等情况,代码如上所示。在initData中会调用observe这个函数将Vue的数据设置成observable的。当_data数据发生改变的时候就会触发set,对订阅者进行回调(在这里是render)。

那么问题来了,需要对app._date.text操作才会触发set。为了偷懒,我们需要一种方便的方法通过app.text直接设置就能触发set对视图进行重绘。那么就需要用到代理。

代理

我们可以在Vue的构造函数constructor中为data执行一个代理proxy。这样我们就把data上面的属性代理到了vm实例上。

_proxy(options.data);/*构造函数中*/ /*代理*/ function _proxy (data) {      const that = this;     Object.keys(data).forEach(key => {          Object.defineProperty(that, key, {              configurable: true,             enumerable: true,             get: function proxyGetter () {                  return that._data[key];             },             set: function proxySetter (val) {                  that._data[key] = val;             }         })     }); }  

我们就可以用app.text代替app._data.text了。 

copyright © 2025 powered by 益强资讯全景  滇ICP备2023006006号-31sitemap