Vue源码解析-简单实现文本插值并且简单封装(三)

2023-12-21 17:43:05

Vue中最基本的数据绑定形式是文本插值,它使用的是“Mustache”语法 (即双大括号){{}}的形式来进行数据的绑定,我们这里来进行一个简单的复刻,并且用字符串路径来访问对象成员,完成一个简单的封装。

<div id="root">
	<div>
		<div>
			<div>
				{{name}}{{message}}
			</div>
		</div>
	</div>
	<p>{{name}}</p>
	<p>{{message}}</p>
	<p>{{frit.fritOne}}</p>
	<p>{{frit.fritTwo}}</p>
</div>
<script type="text/javascript">
	let rkuohao = /\{\{(.+?)\}\}/g; //正则表达式

	function compiler(template, data) {
		let childNodes = template.childNodes; //取出子元素
		console.log(template)
		for (let i = 0; i < childNodes.length; i++) {
			let type = childNodes[i].nodeType; //nodeType用来描述节点的类型,当值为1时表示元素,为3时表示文本节点
			if (type === 3) {
				//当为文本节点的时候可以判断里面是否有{{}}的插值
				let txt = childNodes[i].nodeValue; //取出文本|nodeValue该属性只有文本节点有意义
				//判断文本里面有没有{{}}
				txt = txt.replace(rkuohao, function(_, g) { //使用正则表达式匹配一次,函数就会调用一次(函数第0个参数表示匹配到的内容,第n个参数表示正则表达式的第n组)
					let path = g.trim(); //得到{{}}里面的东西


					let value = getValueByPath(data, path);

					//将{{***}}用取到的值进行替换
					return value;
				})

				//注意现在txt和Dom元素是没有关系的

				childNodes[i].nodeValue = txt; //现在将元素重新加回去
			} else if (type === 1) {
				//当为元素的时候,需要考虑里面是否有子元素,需要对子元素进行判断是否插值
				compiler(childNodes[i], data);
			}
		}
	}

	function Vuew(options) {
		//定义数据
		this._data = options.data;
		this._el = options.el;

		//定义模板
		this._templateDOM = document.querySelector(this._el);
		this._parent = this._templateDOM.parentNode;

		//开始渲染
		this.render()
	}

	//将模板和数据结合得到HTML加入到页面
	Vuew.prototype.render = function() {
		this.compiler();
	}
	//将模板与数据结合得到DOM元素
	Vuew.prototype.compiler = function(tmpNode) {
		let realHTMLDOM = this._templateDOM.cloneNode(true); //用模板拷贝一个准DOM
		compiler(realHTMLDOM, this._data);
		this.update(realHTMLDOM);
	}
	//将DOM元素放到页面中
	Vuew.prototype.update = function(real) {
		this._parent.replaceChild(real, document.querySelector('#root'))
	}

	//用字符串路径来访问对象成员
	function getValueByPath(obj, path) {
		let paths = path.split('.') //分割获取到数组
		let res = obj;
		let prop;
		while (prop = paths.shift()) {
			res = res[prop];
		}
		return res;
	}

	let app = new Vuew({
		el: '#root',
		data: {
			name: '一个name',
			message: '一个message',
			frit: {
				fritOne: '一个fritOne',
				fritTwo: '一个fritTwo'
			}
		}
	})
</script>

最后我们完成的效果为这样

?

?

文章来源:https://blog.csdn.net/qq_58159494/article/details/132778045
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。