双向绑定实现,vue篇

大家好,我是热狗得小舔狗!
给大家分享一下,如何自己封装一个Vue实例
看图!!!

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>new vue</title>
	</head>
	<body>
		<div id="app">
			<input type="text" name="in" v-model="count">
			<ul>
				<li><div><p><ul>{{message}}</ul></p></div></li>
				<li>{{count}}</li>
				<li>--------------</li>
			</ul>
			{{message}}
		</div>
	</body>
	
	
	<script src="js/compile.js"></script>
	<script src="js/mvvm.js"></script>
	<script type="text/javascript">
		let app = new Mvvm({
			el: '#app',
			data: {
				message: 'hello',
				count: 1
			}
		})
	</script>
</html>

在这里插入图片描述

那么它是如何实现的呢。
在这里插入图片描述
我们都知道在vue中实现双向绑定需要
1 模板的编译
2 数据劫持
3 Watcher

这篇主要实现简单模板的编译。
大致思想:使用类的概念,创建实例时new MVVM({…})对里的对象当参数处理。
input等标签通过js获取v-model属性和值,节点,然后把传来的对应data参数渲染出去。
{{message}}通过匹配 获取{{}}里字符,在把传来的对应data参数渲染出去。

  1. 首先 index.html文件
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>new vue</title>
	</head>
	<body>
		<div id="app">
			<input type="text" name="in" v-model="count">
			<ul>
				<li><div><p><ul>{{message}}</ul></p></div></li>
				<li>{{count}}</li>
				<li>--------------</li>
			</ul>
			{{message}}
		</div>
	</body>
	
	
	<script src="js/compile.js"></script>
	<script src="js/mvvm.js"></script>
	<script type="text/javascript">
		let app = new Mvvm({
			el: '#app',
			data: {
				message: 'hello',
				count: 1
			}
		})
	</script>
</html>

上面代码大家也可以看到,还需要两个js文件。
MVVM.js文件

class Mvvm {
	constructor(obj) {
	    this.$el = obj.el;
		this.$data = obj.data;
		
		if(this.$el) {
			// 渲染
			new Compile(this);
		}
	}
}

这里就是写一个MVVM类。这里constructor函数有点python的__init__()的味道,在new MVVM()的创建实例时候,会自动调用该函数。options为传入参数{ el: “app”, data: {count: 2} }。

Compile.js

class Compile {
	constructor(app) {
		// 判断传入是dom整体元素  还是dom的id
		// this.el使用dom整体元素
	    this.el = this.isElementNode(app.$el) ? app.$el : document.querySelector(app.$el);
		this.data = app.$data;
		this.app = app
		
		if(this.el) {
			// 返回内存dom对象
			let fragment = this.CreateFragment(this.el);
			
			// 编译内存dom
			this.compile(fragment);
			
			// 取出内存dom
			// 不然浏览器上就会没有显示
			this.el.appendChild(fragment)
		}
	}
	
	// 创建内存dom
	CreateFragment(el) {
		let fragment = document.createDocumentFragment();
		let firstChild;
		
		while(firstChild = el.firstChild) {
			fragment.appendChild(firstChild)
		}
		
		return fragment;
	}
	
	// 编译
	compile(fragment) {
		let childNodes = fragment.childNodes;
		
		Array.from(childNodes).forEach(node => {
			
			if(this.isElementNode(node)){
				// 元素节点
				this.compileElement(node);
				// 深度编译
				// 因为有标签嵌套
				this.compile(node);
			}else{
				// 文本节点
				this.compileText(node);
			}
		})
	}
	
	// 编译元素节点中指令 
	// ex: v-model 
	compileElement(node) {
		let attrs = node.attributes;
		Array.from(attrs).forEach(attr => {
			let attrName = attr.name;
			if(attrName.includes('v-')) {
				let [, type] = attrName.split('-');
				let attrValue = attr.value;
				CompileUtil[type](node, this.app, attrValue);
			}
		})
		
	}
	
	// 编译文本中指令
	// ex: {{...}}
	compileText(node) {
		let textContent = node.textContent;
		let reg = /\{\{([^}]+)\}\}/g;
		
		if(reg.test(textContent)) {
			CompileUtil['text'](node, this.app, textContent);
		}
	}
	
	

	isElementNode(node) {
		return node.nodeType === 1;
	}
}

/**
 * 编译工具类
 * 
 * 主要实现vue指令 最终渲染
 */

CompileUtil = {
	model(node, app, attrValue) {
		node.value = app.$data[attrValue];
	},
	
	
	text(node, app, textContent) {
		let value = textContent.replace(/\{\{([^}]+)\}\}/g, (...args) => args[1]).replace(/^\s+|\s+$/g,"");

		node.textContent = app.$data[value];
	}
}

大家可以直接copy运行一下,我的已经可以跑起来了。不过呢,注意文件路径!!!
下一篇文章将会写一下数据劫持和Watcher。实现最终的效果!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值