Vue源码学习之虚拟Dom与Diff算法(二)
本帖最后由 饭饭欧尼酱 于 2022-7-20 11:13 编辑> 本帖最后由 饭饭欧尼酱 于 2022-7-20 11:12 编辑
> 本帖最后由 饭饭欧尼酱 于 2022-7-20 11:11 编辑
# Snabbdom简介
Snabbdom是一个注重简单性、模块化、强大特性和性能的虚拟DOM库。
Vue源码借鉴了Snabbdom
github地址:(https://github.com/coconilu/Blog/issues/152)
大家如果想了解vue的虚拟DOM,首先当然就是要安装这个库了!
## 安装Snabbdom
`npm i -S snabbdom `
安装完了我们看看结构
!(data/attachment/forum/202207/20/111322eh8o2ygofsl2oylu.png)
这里我们只看build目录和src目录
展开看看!
!(data/attachment/forum/202207/20/100152n5ocszons8bp0f7o.png)
可以看到src下面存放的都是ts文件,这里就是snabbdom的Ts源码
再看看build目录下面放的什么文件
展开看看!
!(data/attachment/forum/202207/20/100340bcf16ix1gpi36qqi.png)
这里就是便于我们学习的js源码了,那么有好奇的读者会问`.d.ts`是什么啊?
`.d.ts`就是声明文件,用于保存ts文件中的具体类型。
## 安装WebPack
Snabbdom库是DOM库,当然不能在nodejs环境运行,所以我们需要搭建webpack
和webpack-dev-server开发环境,好消息是不需要安装任何loader!
这里需要注意,必须安装最新版webpack@5,不能安装webpack@4,这是因为
webpack4没有读取身份证中exports的能为,建议大家使用这样的版本:
`cnpm i -D webpack@5 webpack-cli@3 webpack-dev-server@3`
这里你不仅可以用npm 也可以用cnpm还可以用yarn反正你想怎么装怎么装,怎么开心怎么来!
大家如果安装的很慢,可以使用淘宝镜像!
`npm config set registry https://registry.npm.taobao.org`
`npm install -g cnpm --registry=https://registry.npm.taobao.org`
`yarn config set registry http://registry.npm.taobao.org`
## 配置WebPack
首先创建webpack.config.js文件
!(data/attachment/forum/202207/20/102112pmkf13scfssyy31a.png)
从官网复制配置文件:(https://www.webpackjs.com/)
!(data/attachment/forum/202207/20/102319kh5d5bta56bj744b.png)
直接CV左侧的配置文件即可,也可以直接CV我下面的代码
```javascript
const path = require('path');
module.exports = {
//入口
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
}
};
```
除此之外,我们还需要在src下面创建一个index.js作为他的入口文件
!(data/attachment/forum/202207/20/102617e3dllp6iaz7zobmd.png)
配置完入口还需要配置他的出口和端口
```javascript
const path = require('path');
module.exports = {
//入口
entry: './src/index.js',
output: {
//出口
publicPath: xuni,
//不会真正的物理生成的
filename: 'bundle.js'
},
devServer: {
//端口号
port: 8080,
//静态资源目录
contentBase: 'www',
}
};
```
这里的pbulicPath就是虚拟打包路径,也就是说文件夹不会真正的生成,而是在8080端口虚拟生成。
除此之外还需要创建一个www静态资源目录
!(data/attachment/forum/202207/20/103036rkuu9cyknnxpckzg.png)
然后我们在www静态资源目录下面创建一个`index.html`
!(data/attachment/forum/202207/20/103145ixnzthwtn4ezehhe.png)
在浏览器输入`http://localhost:8080/`即可看到我们的打包成功了!
!(data/attachment/forum/202207/20/104213op22ucbw8c6cw82c.png)
我们在www中的index.html引入我们虚拟路径下的`src="/xuni/bundle.js"`
就可以在src下的index.js书写我们的代码啦!
## 测试Snabbdom环境
CV官网文档代码
```javascript
var snabbdom = require('snabbdom');
var patch = snabbdom.init([ // Init patch function with chosen modules
require('snabbdom/modules/class').default, // makes it easy to toggle classes
require('snabbdom/modules/props').default, // for setting properties on DOM elements
require('snabbdom/modules/style').default, // handles styling on elements with support for animations
require('snabbdom/modules/eventlisteners').default, // attaches event listeners
]);
var h = require('snabbdom/h').default; // helper function for creating vnodes
var container = document.getElementById('container');
var vnode = h('div#container.two.classes', {on: {click: function () {
}}}, [
h('span', {style: {fontWeight: 'bold'}}, 'This is bold'),
' and this is just normal text',
h('a', {props: {href: '/foo'}}, 'I\'ll take you places!')
]);
// Patch into empty DOM element – this modifies the DOM as a side effect
patch(container, vnode);
var newVnode = h('div#container.two.classes', {on: {click: function () {
}}}, [
h('span', {style: {fontWeight: 'normal', fontStyle: 'italic'}}, 'This is now italic type'),
' and this is still just normal text',
h('a', {props: {href: '/bar'}}, 'I\'ll take you places!')
]);
// Second `patch` invocation
patch(vnode, newVnode); // Snabbdom efficiently updates the old view to the new state
```
管他乱不乱直接CV!
在www下面的index.html还需要加入一个ID为container的盒子
!(data/attachment/forum/202207/20/105440ftwen2e05znqbeb2.png)
当然如果用不了官方代码就用我的
```javascript
/** src/index.js */
import {
init,
classModule,
propsModule,
styleModule,
eventListenersModule,
h,
} from "snabbdom";
const patch = init([
// Init patch function with chosen modules
classModule, // makes it easy to toggle classes
propsModule, // for setting properties on DOM elements
styleModule, // handles styling on elements with support for animations
eventListenersModule, // attaches event listeners
]);
const container = document.getElementById("container");
const vnode = h("div#container.two.classes", { on: { click: () => {} } }, [
h("span", { style: { fontWeight: "bold" } }, "This is bold"),
" and this is just normal text",
h("a", { props: { href: "/foo" } }, "I'll take you places!"),
]);
// Patch into empty DOM element – this modifies the DOM as a side effect
patch(container, vnode);
const newVnode = h(
"div#container.two.classes",
{ on: { click: () => {} } },
[
h(
"span",
{ style: { fontWeight: "normal", fontStyle: "italic" } },
"This is now italic type"
),
" and this is still just normal text",
h("a", { props: { href: "/bar" } }, "I'll take you places!"),
]
);
// Second `patch` invocation
patch(vnode, newVnode); // Snabbdom efficiently updates the old view to the new state
```
最后看看运行效果
!(data/attachment/forum/202207/20/111020ky8owgstggn9pno9.png)
测试Snabbdom环境成功了!撒花撒花!! ggnb666!!!
页:
[1]