Vue中簡單的虛擬DOM是什麼樣

1. 一個簡單的虛擬DOM長什麼樣

其實當今前端框架不少用到瞭虛擬DOM的技術,但各傢有各傢的實現。這裡我們先看下比較簡單的虛擬DOM庫snabbdom的虛擬DOM長什麼樣

我們假設有html如下,其實也就是所謂的真實DOM

<div class="message">Hello World</div>

那麼snabbdom對應的虛擬DOM是長以下這個樣子的:

{
    "sel": "div",
    "data": {
        "class": "message"
    },
    "text": "Hello World"
}

這樣看來一個虛擬DOM其實就是一個json文件,裡面的內容也不難理解,猜都能猜出來:

  • sel: 標簽名
  • data: 標簽屬性
  • text: 標簽之間的文本內容

從這裡就不難理解虛擬DOM和真實DOM的關系,虛擬DOM就是一個用來描述真實DOM節點的Javascript對象。

虛擬DOM除瞭可以描述單一的一個真實DOM節點,還能描述一顆DOM數。

比如有html如下:

<div id="container">
  <div class="message">Hello World</div>
</div>

對應的虛擬DOM將會是

{
    "sel": "div",
    "data": {
        "id": "container"
    },
    "children": [
        {
            "sel": "div",
            "data": {
                "class": "message"
            },
            "text": "Hello World"
        }
    ]
}

虛擬DOM對象裡面多瞭個children的數組選項,裡面的內容就是前面html中的子節點。

2. Vue中的虛擬DOM長什麼樣

還是以最簡單的html節點為例子

<div class="message">Hello World</div>

vue中的虛擬DOM將會是如下這個樣子的

{
  tag: "div",
  data: {
      "staticClass": "message"
  }
  children: [
    {
      text: "Hello World",
      ...
    },
  ],
  ...
}

Vue中的虛擬DOM比snabbdom的虛擬DOM復雜,會多出很多屬性,我這裡就不一一列出來瞭,上面隻是顯示瞭一些我覺得和snabbdom的虛擬DOM差不多的屬性。

兩個虛擬DOM看上去差不多,隻是:

  • 標簽名這裡用tag而非sel
  • 標簽之間的文本在vue中用一個文本虛擬子節點來表示,而不是像snabbdom那樣直接放到自身的text中

3. Vue中的虛擬DOM實現

在Vue中,虛擬DOM是通過VNode這個類來實現的。

export default class VNode {
  tag: string | void;
  data: VNodeData | void;
  children: ?Array<VNode>;
  text: string | void;
  elm: Node | void;
  ns: string | void;
  context: Component | void; // rendered in this component's scope
  key: string | number | void;
  componentOptions: VNodeComponentOptions | void;
  componentInstance: Component | void; // component instance
  parent: VNode | void; // component placeholder node
  // strictly internal
  raw: boolean; // contains raw HTML? (server only)
  isStatic: boolean; // hoisted static node
  isRootInsert: boolean; // necessary for enter transition check
  isComment: boolean; // empty comment placeholder?
  isCloned: boolean; // is a cloned node?
  isOnce: boolean; // is a v-once node?
  asyncFactory: Function | void; // async component factory function
  asyncMeta: Object | void;
  isAsyncPlaceholder: boolean;
  ssrContext: Object | void;
  fnContext: Component | void; // real context vm for functional nodes
  fnOptions: ?ComponentOptions; // for SSR caching
  devtoolsMeta: ?Object; // used to store functional render context for devtools
  fnScopeId: ?string; // functional scope id support
  constructor(
    tag?: string,
    data?: VNodeData,
    children?: ?Array<VNode>,
    text?: string,
    elm?: Node,
    context?: Component,
    componentOptions?: VNodeComponentOptions,
    asyncFactory?: Function
  ) {
    this.tag = tag;
    this.data = data;
    this.children = children;
    this.text = text;
    this.elm = elm;
    this.ns = undefined;
    this.context = context;
    this.fnContext = undefined;
    this.fnOptions = undefined;
    this.fnScopeId = undefined;
    this.key = data && data.key;
    this.componentOptions = componentOptions;
    this.componentInstance = undefined;
    this.parent = undefined;
    this.raw = false;
    this.isStatic = false;
    this.isRootInsert = true;
    this.isComment = false;
    this.isCloned = false;
    this.isOnce = false;
    this.asyncFactory = asyncFactory;
    this.asyncMeta = undefined;
    this.isAsyncPlaceholder = false;
  }
}

其中包含瞭我們上面示例看到的最重要的tag,data,children等描述一個DOM結構的選項,還有很多Vue實現需要用到的選項,這裡就不一一解析,什麼時候用到什麼時候分析吧,先有個概念就好瞭。

4. createTextVNode

從VNode的構造函數可以看到其接受的參數比較多,為瞭方便使用,vue為創建VNode節點提供瞭一些函數的封裝,其中我們最常用的就是創建一個文本節點。

export function createTextVNode(val: string | number) {
  return new VNode(undefined, undefined, undefined, String(val));
}

對應的真實DOM

<div>Hello world</div>

到此這篇關於Vue中簡單的虛擬DOM是什麼樣的文章就介紹到這瞭,更多相關Vue虛擬DOM內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: