前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >1. 「snabbdom@3.5.1 源码分析」snabbdom 介绍和使用

1. 「snabbdom@3.5.1 源码分析」snabbdom 介绍和使用

作者头像
tinyant
发布2023-02-24 10:10:57
1770
发布2023-02-24 10:10:57
举报

vue@2.x 借助了snabbdom的虚拟DOM能力

snabbdom 是什么?

A virtual DOM library with focus on simplicity, modularity, powerful features and performance.

为什么需要 虚拟DOM

另外一个虚拟DOM库:virtual-dom 解释了为什么(Motivation)会出现虚拟DOM?

  1. 手动操作DOM麻烦且混乱
  2. 难以跟踪之前的状态:视图实际上是数据的反映,视图每次变更都会构成一条历史记录,这种历史记录如果是纯手动维护则会很艰难。

而事实上视图是数据的体现,如果有种方式能够让数据和视图同步,数据变化时视图自动更新而不需要手动更新(数据驱动),对于开发者来说则简化很多工作,只需要关心数据就行。

所以出现了虚拟DOM,作为数据和视图的中间媒介。数据 -> 虚拟DOM -> 真实DOM。

snabbdom的使用

官方参考,官方demo如下

代码语言:javascript
复制
import {
  init, classModule, propsModule, styleModule, eventListenersModule, h
} from "../build/index.js";

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: someFn } },
  [
    h("span", { style: { fontWeight: "bold" } }, "This is bold"), " and this is just normal text",
    h("a", { props: { href: "http://wwww.baidu.com" } },
      "_ baidu.com_1")
  ]
);

function someFn() {
  function anotherEventHandler() {
    console.log('anotherEventHandler')
  }

  const newVnode = h("div#container.two.classes",
    { on: { click: anotherEventHandler } },
    [
      h("span", { style: { fontWeight: "normal", fontStyle: "italic" } }, "This is now italic type"),
      " and this is still just normal text",
      h("a", { props: { href: "http://wwww.baidu.com" } }, "_ baidu.com_2")
    ]
  );

  // Second `patch` invocation
  patch(vnode, newVnode); // Snabbdom efficiently updates the old view to the new state
}

// Patch into empty DOM element – this modifies the DOM as a side effect
patch(container, vnode);

先是调用init方法,参数是module数组,后面会深入分析内置的各个module的作用,该函数返回一个patch函数。patch打补丁的意思对吧)方法用来将虚拟DOM同步到视图,patch函数有两个入参,分别是老的虚拟节点oldVnode和新的虚拟节点vnode。

代码语言:javascript
复制
export function init(modules, domApi, options) {
 //...
 return function patch(oldVnode, vnode) {
     //...
 }
}

调用h函数,该函数用来创建虚拟DOM,后面会看到虚拟DOM具体是什么东西。

代码语言:javascript
复制
export function h(sel, b, c) {
 //...
 return vnode(sel, data, children, text, undefined);
}

第一次调用patch函数时,由于oldVnode是真实DOM,此时会先清空该DOM的子孙,而后对比。显然是将我们上述通过h函数创建的虚拟DOM全部转化为真实DOM挂载到界面上。

此时当我们点击文本时(提供了click事件:someFn),在该点击事件的回调中:看到我们再次通过h函数创建一个新的虚拟节点,而后调用patch来对比新老虚拟节点(树),和第一次情况不同,此时的第一个入参是第一次创建的老的虚拟节点(树),此时会真正对比两颗虚拟节点树的差异,而后将差异同步到视图中。

总结

  1. 简单为什么需要虚拟DOM
  2. snabbdom的基础使用,其实就是这么简单,后面会从源码角度分析这个运作过程。

snabbdom/src 目录结构

image.png
image.png
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-01-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 为什么需要 虚拟DOM
  • snabbdom的使用
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档