![38d8fc06a2d21ab844e7c34bfcff953c.png](https://img-blog.csdnimg.cn/img_convert/38d8fc06a2d21ab844e7c34bfcff953c.png)
相信大家平时的前端开发中对像Vue这类的MVVM框架依赖程度很高,对Vue的使用想必也十分熟练了。其中有些人可能看过Vue的源码,了解过Vue是如何实现数据监听和数据绑定这些技术的。最近我也看了一些源码实现,读了React的部分源码也了解了下Vue的实现原理。看完之后就突然想自己实现一个简单的Vue框架玩一玩,这篇文章就是想跟大家分享一下自己的Vue框架是如何实现的,希望能和大家多多交流经验,一起成长。
先在这里感谢一下LucasHC老师在 gitchat上前端进阶课程中所带来的帮助。
![466c2f7f52c4db04f5e182e85c318461.png](https://img-blog.csdnimg.cn/img_convert/466c2f7f52c4db04f5e182e85c318461.png)
主要的功能实现主要分为3部分:
- 数据劫持/数据代理:数据改变时通知相关函数进行更新操作
- 数据依赖收集:建立保存dom节点与数据的关联关系
- 模板与数据之间的绑定:接收到新数据时对dom节点进行更新(Watcher)
先看一下构造方法
function WueComponent(wueComponentProps = {}) {
const {
template = "",
data = () => {
},
methods = {},
watch = {},
} = wueComponentProps;
this.$watch = watch;
this.$watchers = {};
this.$methods = methods;
this.$data = data() || {};
bindVueProperties(this, data() || {});
this.observe(this.$data);
this.observe(this);
bindVueProperties(this, this.$methods);
this.$template = htmlStringToElement(template);
this.$wueDomNode = this.compile();
}
构造方法里拿到传入的参数,再调用一些方法对上边提到的3部分的功能进行实现。这些方法我都放在了原型链上(prototype),这样方便在方法中使用实例的context(this)。因为之后我们需要在执行mehtods中的方法时可能同时要访问data和mehtods,所以这里利用bindVueProperties将data和mehtods复制到了实例的根层。
function bindVueProperties(vueInstance, obj) {
for (let key of Object.keys(obj)) {
vueInstance[key] = obj[key];
}
}
- 数据劫持/数据代理
WueComponent.prototype.observe = function (data, path = "") {
const self = this;
if (!data || Object.prototype.toString.call(data) !== "[object Object]") {
return;