Vue双向数据绑定之原理及实现2

一、数据代理

我们封装的代码中,进行数据访问是myVue.data.name,而实际Vue中的如果要获取数据肯定不需要添加data选项即 myVue.namemyVue.skill
此时就可以通过代理,将data数据选项绑定在Vue对象中,修改时同步到data。

function Vue(options){	
	this.el = options.el		// 元素
	this.data = options.data 	// 数据
	this.watcher = {}	// 属性、数据、元素 的关联
	
	var self = this 
	Object.keys(this.data).forEach(function(key){	// 遍历所有key
		self.proxyKeys(key); // 添加代理(data项的处理)
		self.defineProperty(self.data, key, self.data[key])	
	})
	
	// 解析DOM
	this.compile()	
}

Vue.prototype = {
    proxyKeys(key){
        var self = this 
        Object.defineProperty(this, key, {
            enumerable: false,
            configurable: true,
            get(){
                return self.data[key]
            },
            set(newVal){
                self.data[key] = newVal
            }
        })
    },
      
    // defineProperty、compile保持不变
    // ...
}

二、createDocumentFragment

对于DOM节点我们采取的是遍历操作,直接操作DOM,影响页面的性能。

createDocumentFragment创建一个新的空白的文档片段(DocumentFragment)。

DocumentFragments是DOM节点。它们不是主DOM树的一部分。通常的用例是创建文档片段,将元素附加到文档片段,然后将文档片段附加到DOM树。在DOM树中,文档片段被其所有的子元素所代替。因为文档片段存在于内存中,并不在DOM树中,因此使用文档片段通常会带来更好的性能。

Vue.prototype = {
    // ....

    compile(){	// 解析DOM即更新数据
		// 获取到对象绑定的元素
		var ele = document.querySelector(this.el);
		
		// 所有子元素
		var childEls = ele.childNodes;
		
		// 创建fragment
		var fragment = document.createDocumentFragment();
		
		// 获取到第一个子元素
		var child = ele.firstChild;
		while (child) {
	        // 将Dom元素移入fragment中
	        // appendChild: 如果被插入的节点已经存在于当前文档的文档树中,则那个节点会首先从原先的位置移除,然后再插入到新的位置
	        fragment.appendChild(child)
	        // 再获取第一个(其实就是下一个下一个的操作)
	        child = ele.firstChild
	    }
		
		// 遍历所有子元素
		[].slice.call(fragment.childNodes).forEach(el => {	
			var reg = /\{\{(.*)\}\}/;
			var text = el.textContent;
			if(reg.test(text)){	
				var key = reg.exec(text)[1]; 
				el.textContent = this.data[key]; 

				this.watcher[key] = function(newVal){
					el.textContent = newVal
				}
			}
		})
		
		// 添加
		ele.appendChild(fragment)
	}
}
发布了10 篇原创文章 · 获赞 0 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/emperorzhi/article/details/104511089