实现一个简单版本的vue及源码解析

原创 黎云锐 教程 前端 3431阅读 22 天前 举报

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

Let data to observable

首先假定一种最简单的情况,不去考虑其他情况。在initData中会调用observe这个函数将Vue的数据设置成observable的。当_data数据发生改变的时候就会触发set,对订阅者进行回调(在这里是render)。
为了操作方便,我们需要将 _data 上的数据代理到vm实例上.
依赖收集

依赖收集的原因

按照上面的方法进行绑定会出现一个问题——实际模板中未使用的数据被更改后也会进行重新渲染,而这样无疑会消耗性能,因此需要依赖收集来保证只渲染实际模板中使用到的数据。

Dep

当对data上的对象进行修改值的时候会触发它的setter,那么取值的时候自然就会触发getter事件,所以我们只要在最开始进行一次render,那么所有被渲染所依赖的data中的数据就会被getter收集到Dep的subs中去。在对data中的数据进行修改的时候setter只会触发Dep的subs的函数.

Dep.prototype.depend 方法是将观察者Watcher实例赋值给全局的Dep.target,然后触发render操作只有被Dep.target标记过的才会进行依赖收集。有Dep.target的对象会将Watcher的实例push到subs中,在对象被修改触发setter操作的时候dep会调用subs中的Watcher实例的update方法来重新获取数据生成虚拟节点,再由服务端将虚拟节点渲染成真实DOM。

src/oberver/dep.js
实现

上面讲述响应式原理和依赖收集的原因,接下来就来简单实现一下。开始正式编程前,照常先写测试用例。
  addDep (dep) {
    this.deps.push(dep)
    dep.addSub(this)
  },
  update: jasmine.createSpy()
}
// observing primitive value
Dep.target = watcher
obj.a
Dep.target = null
expect(watcher.deps.length).toBe(1) // obj.a

});
});

接下来正式实现数据绑定,其中 observe 的作用是返回一个 observer 实例,而 observer 则负责实现数据绑定.
在上面的代码中我们用到了一些工具函数,下面我们就把这些工具函数在单独的文件中实现,方便之后其他组件的调用。

全栈学习交流

上面已经简单实现了数据绑定,接下来不妨使用 npm run test 命令来测试下项目吧。
评论 ( 0 )
最新评论
暂无评论

赶紧努力消灭 0 回复