任何好学的技能都不值钱,加油!
下面的代码我自己觉得是挺难的,不过孰能生巧,加油!
将真实DOM转换为虚拟DOM
为什么要使用虚拟DOM?
1、提高性能(直接在页面中操作DOM,页面要不断的去更新)
2、虚拟DOM所有的操作都在内存中进行
代码
<div id="root">
<div class="c1">
<div>hello1</div>
<div>hello2</div>
<div>hello3</div>
<ul class="u1">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</div>
</div>
</div>
class VNode {
constructor(tag,data,value,type) {
this._tag = tag && tag.toLowerCase();
this._data = data;
this._value = value;
this._type = type;
this.children = [];
}
appendChild(vnode) {
this.children.push(vnode);
}
}
关于上面👆代码中class介绍
- ES6中的类,实质上就是一个函数
- 类自身指向的就是构造函数
- 类其实就是构造函数的另一种写法
class Person2 {
// 用constructor构造方法接收参数
constructor(name, age) {
this.name = name; // this代表的是实例对象
this.age = age;
}
// 类的方法,此处不能加function
say() {
return "My name is " + this.name + ", I'm " + this.age + " years old."
}
}
var obj = new Person2("Coco", 26);
console.log(obj.say()); // My name is Coco, I'm 26 years old.
构造函数的prototype属性,在ES6的class中依然存在:
constructor方法是类的构造函数的默认方法 new生成对象实例时,自动调用该方法
class Box {
constructor() {
console.log("自动调用constructor方法"); // 实例化对象时,该行代码自动执行
}
}
var obj = new Box();
DOM转换成虚拟DOM最关键的代码
/**
* 将DOM转换为虚拟DOM(这里使用的是递归的方法,但是在真正的vue源码中使用的 栈结构,使用栈存储 )
*/
function getVNode(node) {
/**
* 1、获取到节点的类型,判断是元素节点还是文本节点 1 元素节点 3 文本节点
* - 元素节点
* + 获取到元素的 name 与 attr
* + 获取到的属性是一个伪数组,将伪书组转换为对象
* - 文本节点
*/
let nodeType = node.nodeType;
let _vnode = null;
if(nodeType === 1) { // 元素节点
let nodeName = node.nodeName;
let attrs = node.attributes;
let attrObj = {};
for(let i = 0;i<attrs.length;i++) {
attrObj[attrs[i].nodeName] = attrs[i].nodeValue;
}
// 元素节点没有 value
_vnode = new VNode(nodeName,attrObj,undefined,nodeType);
// 有子元素的情况
let childNodes = node.childNodes;
for(let i = 0; i < childNodes.length; i++ ) {
let childNode = getVNode(childNodes[i]);
_vnode.appendChild(childNode);
}
} else if(nodeType === 3) { // 文本节点没有标签与属性
_vnode = new VNode(undefined,undefined,node.nodeValue,nodeType);
}
return _vnode;
}
使用
let root = document.querySelector('#root');
let vnode = getVNode(root);
console.log(vnode);
将虚拟DOM转换为DOM
/*
将虚拟DOM转化为DOM
递归会影响性能,
真正的vue源码使用的是 vue + 栈 数据类型
*/
function parse(vnode) {
let _node = null;
let type = vnode._type;
if(type === 1 ) { // 元素节点
_node = document.createElement(vnode._tag);
// 属性
let _data = vnode._data;
// console.log(Object.keys(_data)); 得到一个使用key组成的数据
Object.keys(_data).forEach(key => {
let attrName = key;
let attrValue = _data[key];
_node.setAttribute(attrName,attrValue);
})
// 含有子节点
let children = vnode.children;
children.forEach(item => {
let childNode = parse(item);
_node.appendChild(childNode);
})
} else if(type === 3) { // 文本节点
return document.createTextNode(vnode._value); // 创建一个文本节点
}
return _node;
}
let $dom = parse(vnode);
console.log($dom);
大家要加油哦!