虚拟dom之前我们也有了基本的了解
简单说 就是用js数据结构来描述html的dom结构树
首先 为什么要用虚拟dom啊?
官方给出的回答是 diff最小量精细化算法是发生在虚拟dom上的
也就是 我们之前说的 节点与节点比较 并不是发生在html元素上的 而是发生在js中的虚拟dom上的
就是 当节点发生变化 或者 节点依赖数据发生变化时 对比哪里不一样 才能知道怎么更新 惊动的地方最少 且 也能完成更新的目的
这个比较的过程被叫做 diff算法 而这个过程 是在js部分 对这些虚拟dom节点进行的
那我 我们现在就要想 dom是如何变为虚拟dom的呢?
但这个知识 属于模板编译原理范畴 这里 因为时间问题就不去讲解了
我们需要知道 虚拟dom是通过什么渲染的 那么 提示通过 h函数渲染的
h这个 没有什么太大含义 就是作者在编写代码时给一个函数命的名 所以 以后我们如果要做开源或者技术栈 命名规范还是挺重要的 后面别人去参考你的代码 也会反向推导你函数的命名
h函数的作用 是用来产生虚拟节点
例如 我们这样去调用h函数
h('a',{props: {href: 'https://blog.csdn.net/weixin_45966674?type=blog'}},'测试标签')
那么 这个函数 就会帮我们创建出一个这样的虚拟节点
{
'sel': 'a'
"data": {
props: {
href:'https://blog.csdn.net/weixin_45966674?type=blog'
}
},
"text": '测试标签'
}
也可以把他看成这样
<a href= "https://blog.csdn.net/weixin_45966674?type=blog">测试标签</a>
那么 我们对应看一下 也就是说 h标签的第一个参数 是你要创建一个什么标签
字符串类型
例如 “div” “p” “h1” 等等
第二个参数是一个对象
这里 首先 我们外面一个对象 {}
然后里面要先有一个字段props
这个就代表属性 它里面有时一个 json对象 对应键值就是标签属性
例如
{
props: {
href: "链接",
name: "name值"
}
}
第三个不用讲 就是标签中的内容
然后 我们这样就声明出了一个虚拟dom节点
又叫 vnode
其中v对应单词 virtual 意思就是 虚拟的
node就是节点 虚拟节点
首先 h就是来声明一个 虚拟的dom节点 至于怎么将dom节点转到h上变成虚拟dom节点 这里 涉及到模板编译原理 时间问题 就不特意去说了 后续我会更文讲解 这里 我们就好好把虚拟dom玩明白
虚拟节点主要会有以下几个属性
children 是它的子节点 子元素 为 undefined 表示没有子集
data 就是我们刚才看到的 他身上带的标签属性
elm 对应这个元素真正的dom节点 如果为 undefined 表示这个节点还没有上dom树
key 表示节点的唯一标识 特别是 我们在vue开发中循环渲染元素时 就需要在标签上加个key属性 用来区分
sel 代表用了一个什么标签 就是我们h的第一个参数 “标签名 例如 div”
text 表示文字
好 我们别光说不练
我们打开上文中 创建的案例
找到 src下的index.js
将引包之外的代码都给他干掉
然后将 src下的 index.js 代码改成这样
import {
init,
classModule,
propsModule,
styleModule,
eventListenersModule,
h,
} from "snabbdom";
//创建虚拟节点
var vonm = h("a",{props: {
href: "https://blog.csdn.net/weixin_45966674?type=blog"
}},
"测试虚拟dom");
console.log(vonm);
这里 我们须知 h函数还没有那么强 他不会真的在html的dom树上加一个节点 他只是在js中创建了一个虚拟dom节点
h函数还没有那么强大 然后 我们启动项目
打开控制台 我们用 console.log 输出的这个h生成的虚拟节点就在这里了
我们来简单看看他的几个属性
这样可那种 像一个json一样 看着就有点没什么感觉
那么 我们让他上一下页面dom树
这个时候 我们要创建一个 patch 函数
后续 我会更文 这个会比较快 去讲述patch函数 它是diff算法的一个核心函数
非常有用
本文先不讲 后续马上更文去讲
我们将src下的index.js代码修改如下
import {
init,
classModule,
propsModule,
styleModule,
eventListenersModule,
h,
} from "snabbdom";
//创建patch函数
const patch = init([
classModule,
propsModule,
styleModule,
eventListenersModule
]);
//创建虚拟节点
var vonm = h("a",{props: {
href: "https://blog.csdn.net/weixin_45966674?type=blog"
}},
"测试虚拟dom");
console.log(vonm);
//让虚拟节点上树
const container = document.getElementById('container');
patch(container,vonm);
这里 用init 传一个数组 里面是其他所有依赖 一个patch就出来了 具体的patch我后面会出文去讲 这篇 我们先弄明白h和虚拟节点
然后 我们需要获取到一个节点
通过document.getElementById获取到id为container的节点
然后第一个参数是要挂载的节点 第二个参数则是虚拟dom节点
再次运行项目 我们的虚拟节点就上去成了真的节点
而我 我们的超链接点击之后 是真的能跳转的
我们的标签属性都是自然生效
但每次 我们点击都是在当前界面打开
学了html伙伴们都知道怎么解决
我们将src下的index.js改成这样
import {
init,
classModule,
propsModule,
styleModule,
eventListenersModule,
h,
} from "snabbdom";
//创建patch函数
const patch = init([
classModule,
propsModule,
styleModule,
eventListenersModule
]);
//创建虚拟节点
var vonm = h("a",{props: {
href: "https://blog.csdn.net/weixin_45966674?type=blog",
target: "_blank"
}},
"测试虚拟dom");
console.log(vonm);
//让虚拟节点上树
const container = document.getElementById('container');
patch(container,vonm);
在props上加一个属性 target: “_blank”
这样 就在另一个界面打开了
这里 需要知道的是 我们一个节点 只能让一个虚拟dom上树 不过 你可以内嵌
我们后续下一文就会将
那么 我就先溜了 后续答应大家的会在一段时间后更新