饭饭欧尼酱 发表于 2022-7-20 11:11:18

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环境成功了!撒花撒花!!

wwwwwllllk 发表于 2022-7-20 21:17:42

ggnb666!!!
页: [1]
查看完整版本: Vue源码学习之虚拟Dom与Diff算法(二)