You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
BabtVue 构造函数接受一个 options,options 中包含 data,root(即 html 中指定的根结点),template 模版,methods 四个 option,我们把这些 option 挂载到 this 方法上,以便后续的函数能轻松地拿到他们。然后执行 observe 和 resolveTemplate 方法
observe 方法:
BabyVue.prototype.observe=function(){Object.keys(this.data).forEach(key=>{letval=this.data[key];constobserver=newObserver();Object.defineProperty(this.data,key,{get: ()=>{if(Observer.target){observer.subscribe(Observer.target);}returnval;},set: newValue=>{if(val===newValue){return;}
val =newValue;observer.publish(newValue);}});});};
observe 方法中先对 this.data 中的数据进行遍历,这里没有考虑更深层的结构,只对第一层数据进行遍历,利用闭包缓存它的当前值 val 和一个观察者 observer,并用Object.defineProperty方法设置它的 get 和 set 属性,在获取值的时候判断 Observer.target 是否存在,若存在,则将 Observer.target 加入订阅者(后面再详述其作用),最后返回 val;设置值的时候,将新值与 val 对比,若不同,则更新 val 值,并通知订阅者更新
先根据正则匹配{},若符合条件,获取了大括号的标识符后,先将Object.target设为元素的标识,在将元素的 innerHTML 置为 data 中的数据,要注意,在此时,我们获取了一次this.data[key],会触发之前设置的 get 属性,在其中判断Observer.target是否存在,因为我们刚刚设置过,Observer.target当前为元素的标识,所以,它被加到订阅者中。
访问 https://bowencodes.com 以获得最佳体验
这周参考了一些博文,自己写了一个简单的 vue,网上这类实现很多,我的实现也没什么新奇,权当一个自我练习吧
具体实现
首先,得先有一个 Vue 类,当然,我写的一个很粗糙的 Vue 类,所以我把它叫做 BabyVue:
BabtVue 构造函数接受一个 options,options 中包含 data,root(即 html 中指定的根结点),template 模版,methods 四个 option,我们把这些 option 挂载到 this 方法上,以便后续的函数能轻松地拿到他们。然后执行 observe 和 resolveTemplate 方法
observe 方法:
observe 方法中先对 this.data 中的数据进行遍历,这里没有考虑更深层的结构,只对第一层数据进行遍历,利用闭包缓存它的当前值 val 和一个观察者 observer,并用
Object.defineProperty
方法设置它的 get 和 set 属性,在获取值的时候判断 Observer.target 是否存在,若存在,则将 Observer.target 加入订阅者(后面再详述其作用),最后返回 val;设置值的时候,将新值与 val 对比,若不同,则更新 val 值,并通知订阅者更新下面是 Observer 的代码,实现了一个简单的观察者模式:
订阅者用其特殊属性进行标识,在更新时,先通过属性选择器拿到目标 dom 再更新其值
下面是 resolveTemplate 的代码,其主要是渲染模版、增加元素标识和挂载事件,Vue 中对模版解析使用的应当是更高级的方法,我这里只是对 template 字符串一些简单的解析
我对模版中的每一个元素增加一个特殊标示,形似
v-xxx
,方便根据表示标示获取真实 dom(为什么不直接保存 node?可以试试使用了createElement
创建的元素再设置innerHTML
,会出现一些问题)。先根据正则匹配
{}
,若符合条件,获取了大括号的标识符后,先将Object.target
设为元素的标识,在将元素的 innerHTML 置为 data 中的数据,要注意,在此时,我们获取了一次this.data[key]
,会触发之前设置的 get 属性,在其中判断Observer.target
是否存在,因为我们刚刚设置过,Observer.target
当前为元素的标识,所以,它被加到订阅者中。再获取其事件属性,我们这里只简单地获取
v-on:click
属性,我们将它的属性值和元素标识保存到 events 中最后等待模版挂载在 root 元素中后,我们遍历 events 数组,挂载事件
至此,我的 BabyVue 已基本实现了
Demo
实现的是一个简单的计数器:

有兴趣的小伙伴可以复制以下代码运行查看效果:
最后
今天是我的生日,哈哈哈,祝我生日快乐~
The text was updated successfully, but these errors were encountered: