在|D3|從 vue 原始碼看 new Vue 做了什麼中提到,當 new Vue 後這個 Vue 實例就有了初始化的屬性或方法。
接著要使用 Vue 實例的私有方法 _render function ,把實例渲染成一個虛擬 DOM。
了解虛擬 DOM 之後再來看 _render function。
回顧一下,瀏覽器解析 HTML 構成 DOM tree,DOM tree 結構由各個節點( node )組成。
圖片來源:google-developers
以 div 元素為例,用 console.dir 把這個 DOM 所有 properties 印出來(只截圖部分而已)。
可以看到 DOM 非常龐大,每當用原生 JS 操作 DOM 時,瀏覽器會再次構成 DOM tree 重新渲染。

Virtual DOM 不是真正的 DOM,概念是當 data 狀態發生變化,Virtual DOM 會進行 diff 運算,只重新渲染需要被取代的 DOM,非常輕量。
在 src/core/vdom/vnode.js 中
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
  }
  // DEPRECATED: alias for componentInstance for backwards compat.
  /* istanbul ignore next */
  get child (): Component | void {
    return this.componentInstance
  }
}
Virtual DOM 用 VNode Class 描述基礎的 VNode
elm: 當前虛擬節點相對應的真實 DOM 節點data: 包含 class、id等 HTML 屬性VNodeData 的定義可從下面 2 中知道
types/vnode.d.ts 中export interface VNodeData {
  key?: string | number;
  slot?: string;
  scopedSlots?: { [key: string]: ScopedSlot | undefined };
  ref?: string;
  refInFor?: boolean;
  tag?: string;
  staticClass?: string;
  class?: any;
  staticStyle?: { [key: string]: any };
  style?: string | object[] | object;
  props?: { [key: string]: any };
  attrs?: { [key: string]: any };
  domProps?: { [key: string]: any };
  hook?: { [key: string]: Function };
  on?: { [key: string]: Function | Function[] };
  nativeOn?: { [key: string]: Function | Function[] };
  transition?: object;
  show?: boolean;
  inlineTemplate?: {
    render: Function;
    staticRenderFns: Function[];
  };
  directives?: VNodeDirective[];
  keepAlive?: boolean;
}
舉個例子
<div id="app">
    <p class="text">{{ message }}</p>
    <ul>
        <li v-for="user of users" class="item">{{ user }}</li>
    </ul>
</div>
<scrip>
     new Vue({
        el: '#app',
        data: {
            message: 'hello',
            users: ['Tom', 'Tony', 'Tim']
        }
    })
</scrip>
node tree
{
    'tag': 'div'
    'data': {
        'attrs': { 'id': 'app' }
    },
    'children': [
        {
            'tag': 'p',
            'data': {
                'staticClass': 'text'
            }
            'text': 'hello'
        },
        {
            'tag': 'ul',
            'children': [
                {
                    'tag': 'li',
                    'data': {
                        'staticClass': 'item'
                    }
                    'text': 'Tom'
                },
                {
                    'tag': 'li',
                    'data': {
                        'staticClass': 'item'
                    }
                    'text': 'Tony'
                },
                {
                    'tag': 'li',
                    'data': {
                        'staticClass': 'item'
                    }
                    'text': 'Tim'
                }
            ]
        }
    ]
}