學習筆記:Render函數
Render函數
Vue2
與Vue1
最大的區別就在於Vue2
使用了虛擬DOM
來更新DOM
節點,提升渲染性能。
Vue2
與Vue1
最大的區別就在於Vue2
使用了虛擬DOM
來更新DOM
節點,提升渲染性能。
-
Vue2
與Vue1
最大的區別就在於Vue2
使用了虛擬DOM
來更新DOM
節點,提升渲染性能。
Vue2
與Vue1
最大的區別就在於Vue2
使用了虛擬DOM
來更新DOM
節點,提升渲染性能。
虛擬DOM
React和Vue2都使用了虛擬DOM技術,虛擬DOM並不是真正意義上的DOM,而是一個輕量級的JavaScript對象,在狀態發生變化時,虛擬DOM會進行Different運算,來更新只需要被替換的DOM,而不是全部重繪。
與DOM操作相比,虛擬DOM是基於JavaScript計算的,所以開銷會小很多。
在Vue2中,虛擬DOM就是通過一種VNode類表達,每個DOM元素或組件對對應一個VNode對象。
VNodeData
節點解析:
-
children
子節點,數組,也是VNode類型。 -
text
當前節點的文本,一般文本節點或註釋節點會有該屬性。 -
elm
當前虛擬節點對應的真實的DOM節點。 -
ns
節點的namespace
-
content
編譯作用域 -
functionalContext
函數化組件的作用域 -
key
節點的key
屬性,用於作爲節點的標識,有利於patch
的優化 -
componentOptions
創建組件實例時會用到的選項信息。 -
child
當前節點對應的組件實例。 -
parent
組件的佔位節點。 -
raw
原始html
-
isStatic
靜態節點的標識 -
isRootInset
是否作爲根節點插入,被<transition>
包裹的節點,該屬性的值爲false
。 -
isConment
當前節點是否是註釋節點。 -
isCloned
當前節點是否爲克隆節點。 -
isOnce
當前節點是否有v-once
指令。
VNode主要可以分爲以下幾類:
-
TextVNode
文本節點。 -
ElementVNode
普通元素節點。 -
ComponentVNode
組件節點。 -
EmptyVNode
沒有內容的註釋節點。 -
CloneVNode
克隆節點,可以是以上任意類型的節點,唯一的區別在於isCloned
屬性爲true
。
Render函數通過createElement
參數來創建虛擬DOM,結構精簡。其中,訪問slot
的用法,使用場景集中在Render函數。
<p data-height="265" data-theme-id="0" data-slug-hash="wXozpg" data-default-tab="html,result" data-user="whjin" data-embed-version="2" data-pen-title="Vue-render函數" class="codepen">See the Pen Vue-render函數 by whjin (@whjin) on CodePen.</p>
<script async src="https://static.codepen.io/ass...;></script>
createElement
用法
基本參數
createElement
構成了Vue虛擬DOM的模板,它有3個參數:
createElement(
//{String | Object | Function}
//一個HTML標籤,組件選項,或一個函數
//必須return上面其中一個
'div',
//{Object}
//一個對應屬性的數據對象,可選
//可以在template中使用
//{String | Array}
//子節點(VNode),可選
[
createElement('h1','hello world'),
createElement(MyComponent,{
props:{
someProp:'foo'
}
}),
'bar'
]
);
第一個參數必選,可以是一個HTML標籤,也可以是一個組件或函數;第二個是可選參數,數據對象,在template
中使用。第三個是子節點,也是可選參數,用法一直。
之前在template
中都是在組件的標籤上使用v-bind:class
、v-bind:style
、v-on:click
這樣的指令,在Render函數都將其寫在了數據對象中。
約束
所有的組件樹中,如果VNode是組件或含有組件的slot
,nameVNode必須唯一。
在Render函數裏創建了一個cloneVNode
的工廠函數,通過遞歸將slot
所有子節點都克隆了一份,並對VNode的關鍵屬性也進行復制。
使用JavaScript代替模板功能
在Render函數中,不再需要Vue內置的指令,比如v-if
、v-for
。無論要實現什麼功能,都可以使用原生JavaScript。
<p data-height="265" data-theme-id="0" data-slug-hash="eKgVgQ" data-default-tab="html,result" data-user="whjin" data-embed-version="2" data-pen-title="render--v-for" class="codepen">See the Pen render--v-for by whjin (@whjin) on CodePen.</p>
<script async src="https://static.codepen.io/ass...;></script>
map()
方法時快速改變數組結構,返回一個新數組。map
常和filter
、sort
等方法一起使用,它們返回的都是新數組。
Render函數裏沒有與v-model
對應的API,需要自己來實現邏輯。
<p data-height="265" data-theme-id="0" data-slug-hash="BVpYdd" data-default-tab="html,result" data-user="whjin" data-embed-version="2" data-pen-title="Vue-render-API" class="codepen">See the Pen Vue-render-API by whjin (@whjin) on CodePen.</p>
<script async src="https://static.codepen.io/ass...;></script>
v-model
就是prop:value
和event:input
組合使用的一個語法糖,雖然在Render裏寫起來比較複雜,但是可以自由控制,深入到更底層。
對於事件修飾符和按鍵修飾符,基本需要自己實現:
修飾符 | 對應的句柄 |
---|---|
.stop |
event.stopPropagation() |
.prevent |
event.preventDefault() |
.self |
if(event.target!==event.currentTarget) return |
.ente 、.13
|
if(event.keyCode!==13) return 替換13位需要的keyCode
|
.ctrl 、.alt 、.shift 、.meta
|
if(!event.ctrlKey) return 根據需要替換ctrlKey 位altKey 、shiftKey 或metaKey
|
對於事件修飾符.capture
和.once
,Vue提供了特殊的前綴,可以直接寫在on
的配置裏。
修飾符 | 前綴 |
---|---|
.capture |
! |
.once |
~ |
.capture.once 或.once.capture
|
~! |
寫法如下:
on: {
'!click': this.doThisInCapturingMode,
'~keyup': this.doThisOnce,
'~!mouseover': this.doThisOnceInCapturingMode
}
簡單模擬聊天發送內容的場景:
<p data-height="265" data-theme-id="0" data-slug-hash="ZRLrPN" data-default-tab="html,result" data-user="whjin" data-embed-version="2" data-pen-title="Vue-模擬聊天發送內容" class="codepen">See the Pen Vue-模擬聊天發送內容 by whjin (@whjin) on CodePen.</p>
<script async src="https://static.codepen.io/ass...;></script>
在Render函數中會大量使用slot
,在沒有使用slot
時會顯示一個默認的內容,這部分需要自己實現。
this.$slots.default
等於undefined
,就說明父組件中沒有定義slot
,這是可以自定義顯示的內容。