美文网首页
1. 看看 vue 的前几个 commit

1. 看看 vue 的前几个 commit

作者: 飞天御剑流co | 来源:发表于2023-12-23 08:39 被阅读0次

刚刚项目已经能勉强跑起来了,但是本菜鸡还是看不懂代码里那么多东西,怎么办呢,只能从头开始了,从起初的 commit 看一下吧

让我们将时间线切回到第三次提交

可以看到,作者进行了尝试,用短短 70 行代码就实现了 vue 的最初版雏形

那来看一下具体的代码

可以看到,最初的尝试就是现在锁熟知的 vue 的样子

运行项目

可以看到,三个 msg 被转化为下面 msg 中的变量的值,另外两个没有的变量则没有任何反应

			var bindingMark = 'data-element-binding'
			function Element (id, initData) {

				var self = this,
					el = self.el = document.getElementById(id)
					bindings = {} // the internal copy
					data 	 = self.data = {} // the external interface
					content  = el.innerHTML.replace(/\{\{(.*)\}\}/g, markToken)
				el.innerHTML = content

				for (var variable in bindings) {
					bind(variable)
				}

				if (initData) {
					for (var variable in initData) {
						data[variable] = initData[variable]
					}
				}

				function markToken (match, variable) {
					bindings[variable] = {}
					return '<span ' + bindingMark + '="' + variable +'"></span>'
				}

				function bind (variable) {
					console.log('binding', variable)
					bindings[variable].els = el.querySelectorAll('[' + bindingMark + '="' + variable + '"]')
				    ;[].forEach.call(bindings[variable].els, function (e) {
				        e.removeAttribute(bindingMark)
				    })
					Object.defineProperty(data, variable, {
						set: function (newVal) {
						    [].forEach.call(bindings[variable].els, function (e) {
						        bindings[variable].value = e.textContent = newVal
						    })
						},
						get: function () {
						    return bindings[variable].value
						}
					})
				}
			}

			var app = new Element('test', {
				msg: 'hello'
			})

首先看调用形式

			var app = new Element('test', {
				msg: 'hello'
			})

第一个参数是 id , 第二个数据是初始数据

				var self = this,
					el = self.el = document.getElementById(id)
					bindings = {} // the internal copy
					data 	 = self.data = {} // the external interface
					content  = el.innerHTML.replace(/\{\{(.*)\}\}/g, markToken)
				el.innerHTML = content

然后在函数内部初始化了一大堆变量

将函数本身指向 self , 去获取 id 为 test 的 dom 元素,创建一个空对象 bindings,定义 data 和 self.data,并且将这俩指向同一个地址,定义 content 等于 el.innerHTML.replace(/\{\{(.*)\}\}/g, markToken),然后,直接将 dom 元素的内容赋值为刚刚初始化完成的 content

这段代码带给我疑惑的地方就是 content 变量的初始化,第一个给定的正则是匹配 {{xxxxx}} 这种形式的

其中使用了

mdn replace

经查询,可以了解到其用法,进而得知 markToken,是一个函数

然后看一下这个函数

				function markToken (match, variable) {
					bindings[variable] = {}
					return '<span ' + bindingMark + '="' + variable +'"></span>'
				}
// 依赖的 外部变量是这个
var bindingMark = 'data-element-binding'

经过我的 log 信息可知,此函数的收到的参数是这样子的

那自然可以推出来,这个函数会把 bindings 变成下面的样子

然后函数的返回值是这样子的

用 span 标签将花括号的东西全部替换掉,可以看到,渲染出来的东西也是这样子的

然后返回主线,看下一段代码

				for (var variable in bindings) {
					bind(variable)
				}

遍历了 bindings ,上面的代码可知, bindings 是被赋值过的,那么 key 值就是刚刚的 msg what hey

				function bind (variable) {
					bindings[variable].els = el.querySelectorAll('[' + bindingMark + '="' + variable + '"]')
				    ;[].forEach.call(bindings[variable].els, function (e) {
				        e.removeAttribute(bindingMark)
				    })
					Object.defineProperty(data, variable, {
						set: function (newVal) {
						    [].forEach.call(bindings[variable].els, function (e) {
						        bindings[variable].value = e.textContent = newVal
						    })
						},
						get: function () {
						    return bindings[variable].value
						}
					})
				}

然后执行 bind 函数,先是使用 querySelectorAll 去获取一个类数组对象,也就是节点列表,将获取到的节点列表赋值到 bindings[variable] 的 els 属性上,赋值完成后将自定义的标签数据进行了移除,现在的 bindings 是这个样子的

这个 函数使用 [].forEach.call 这种方式而不是直接 forEach 的原因也是因为 els 本身是一个类数组,其本身是没有 forEach 方法的,并且在此我了解到,那个时候还没有箭头函数,所以都要使用 function 的写法

下面就执行了我们最最最熟悉的响应式的地方,这里就不再多说了,网上的文章已经将这东西将烂了

这里做的就是,在给最起初定义的 data 对象赋值 hey msg what 等属性的时候,去给 bindings[variable].value 赋值,同时将 dom 元素的文本内容赋值为 newVal , get 的时候则会返回其值

继续回到主线

				if (initData) {
					for (var variable in initData) {
						data[variable] = initData[variable]
					}
				}

然后最后一段逻辑就是给 data 赋值,触发刚刚定义好的 data setValue 的行为

这时候打开浏览器就可以看到,三个 msg 的花括号是渲染出来了的,其他两个是空值

拓展一下,写一个按钮,去操作刚刚的 msg 字段,页面应该可以实时更新

经测试逻辑通过

本文完

本文使用 文章同步助手 同步

相关文章

网友评论

      本文标题:1. 看看 vue 的前几个 commit

      本文链接:https://www.haomeiwen.com/subject/xwnqndtx.html