先发一个临时版,内容会更新,随后可以引用一个 vdom 库来实现虚拟 dom 功能。
Hover your mouse over me for a few seconds
to see my dynamically bound title!
var app2 = new Zi({
el: '#app-2',
data: {
message: 'You loaded this page on ' + new Date().toLocaleString()
}
})
需要读取标签的 z-bind:title 然后进行操作,然后将属性解析为一个函数 zbind 接收 title, message 和一个 context 做为参数。然后将 message 变量内容进行替换后更新 span 属性 title 为 message 的值。
上一次我们简单实现如何替换{{}}的占位变量,我们今天继续向下看 vue API,要实现下面的效果,替换掉z-bind:title="message"
中 message 内容,想起来很简单,不过弄来弄去还是不太理想,还得弄虚拟dom,整理一下思路
- 根据 el 指向 dom 生成一颗虚拟dom,简单定义一下结构,
interface VAttr{
attrName:string;
attrVal:string;
}
interface VMNode{
tagName:string;
attrs?:VAttr[];
children?:VMNode[];
}
interface renderVMNode{
(vMNode:VMNode):HTMLElement
}
class VMEngine {
constructor(){
}
generator(dom:HTMLElement):any{
}
}
写一个生产虚拟dom方法,就是遍历节点生成虚拟 dom 的结构。
generator(dom:HTMLElement):any{
let rootVMNode:VMNode = {tagName:"root"};
if(dom != null){
rootVMNode.tagName = dom.nodeName;
if(dom.hasAttributes()){
let vAttrs:VAttr[] = [];
let attrs = dom.attributes;
for(let i = 0; i < attrs.length; i++){
let attrName:string = attrs[i].name;
let attrVal:string |null = dom.getAttribute(attrName);
let vAttr:VAttr = {
attrName:"",
attrVal:""
};
vAttr.attrName = attrName;
if(attrVal == null){
vAttr.attrVal = "";
}else{
vAttr.attrVal = attrVal
}
vAttrs[i] = vAttr
}
rootVMNode.attrs = vAttrs;
}
if(dom.hasChildNodes()){
let childhtmlDoms = dom.childNodes;
rootVMNode.children = [];
if(childhtmlDoms.length > 0){
for(let i = 0; i < childhtmlDoms.length; i++){
let childDom:HTMLElement | null = childhtmlDoms[i];
if( childDom instanceof HTMLElement){
let childVMNode:VMNode = this.generator(childDom)
if(childVMNode != null){
rootVMNode.children[i] = childVMNode;
}
}
}
}
}
}
return rootVMNode;
}
为了规范我们看给函数定义类型,通过 interface 对函数进行限制的接口,我们处理 dom 元素上自定义标签
然后用 context 中内容替换掉 虚拟dom 节点中属性值为 context 的对应值。
walkVMNode(node:VMNode,context:Dictionary):VMNode{
console.log("====================== warlking ===============================")
if(node != null){
console.log("v node name = " + node.tagName);
if(node.attrs != undefined){
for( let attr of node.attrs){
console.log("====================== arrt warlking ===============================")
if()
var obj:Dictionary = context;
Object.keys(obj)
.forEach(function(item){
console.log(item);
if(attr.attrVal == item){
attr.attrVal = obj[item]
}
})
console.log(attr);
console.log("====================== attr warlking ===============================")
}
}
if(node.children != undefined && node.children.length > 0){
for(let child of node.children){
this.walkVMNode(child,context);
}
}
}
return node;
console.log("====================== warlking ===============================")
}
通过遍历 Dom 找出我们自定义属性,v-(.)* ,然后在处理及进行一些操作
if(/^z-(.)+/.test(attr.attrName) ){
attr.attrName = attr.attrName.split(":")[1];
}
随后得加强一下,
正则表达式
函数式编程
-
递归
-
typescript