vue双向绑定的简单实现

2020-06-16 05:44:46易采站长站整理

研究了一下vue双向绑定的原理,所以简单记录一下,以下例子只是简单实现,还请大家不要吐槽~

之前也了解过vue是通过数据劫持+订阅发布模式来实现MVVM的双向绑定的,但一直没仔细研究,这次深入学习了一下,借此机会分享给大家。

首先先将流程图给大家看一下

参考文章:Vue.js双向绑定的实现原理

我虽然参考的是这篇文章,下面的代码也是在阅读几遍后仿造的,自己只是简单添加了个递归实现所有dom子节点的双向绑定,以及添加了一些理解,但真正让我了然于心,让我可以独立写出2遍完整逻辑的其实是这张图,所以个人认为这张流程图才是最重要的,而我参考的这篇文章的作者也是参考这幅图的原作者的。

原文章:剖析Vue原理&实现双向绑定MVVM

站在阅读和理解MVVM的完整逻辑的话,推荐大家看第一篇,但是第二篇原文章的图文更能说明一些问题

如果大家看了我的解释也能够完全理解的话,那就更好啦啦啦啦啦~哈哈

好,下面我会从2个角度开始讲解,先上单向绑定,再由单向绑定过渡到双向绑定;

首先,先为大家解释一下单向绑定model => view层的逻辑
1、劫持dom结构;
2、创建文档碎片,利用文档碎片重构dom结构;
3、在重构的过程中解析dom结构实现MVVM构造函数实例化后的数据初始化视图数据;
4、利用判断dom一级子元素是否依然有子元素从而进行所有子元素的单向绑定;
5、将文档碎片添加至根节点中.

这就是我总结的关于单向绑定的逻辑了,下面利用代码跟大家解释


//dom结构
<div id="app">
<input type="text" v-model="msg">
<p>{{msg}}</p>
<ul>
<li>1</li>
<li>{{msg}}</li>
<li>{{test}}</li>
</ul>
</div>

//one-way-binding.js
//判断每个dom节点是否拥有子节点,若有则返回该节点
function isChild(node){
//这里使用childNodes可以读取text文本节点,所以不用children
if(node.childNodes.length ===0){
return false;
}
else{
return node;
}
}

//利用文档碎片劫持dom结构及数据,进而进行dom的重构
function nodeToFragment(node,vm){
var frag = document.createDocumentFragment();
var child;
while(child = node.firstChild){
//一级dom节点数据绑定
compile(child,vm);
//判断每个一级dom节点是否有二级节点,若有则递归处理文档碎片
if(isChild(child)){
//递归实现二级dom节点的重构
nodeToFragment(isChild(child),vm);