1 vue 虛擬dom
虛擬dom簡單來說就是一個普通的JavaScript對象,包含tag,props,children三個屬性。。。
<div id="app">
<p className="text">lxc</p>
</div>
// 上邊的HTML代碼轉為虛擬DOM如下:
{
tag:"div",
props:{
id:"app"
},
children:[
{
tag:"p",
props:{
className:"text"
},
children:[
"lxc"
]
}
]
}
// 該對象就是所謂的虛擬dom,因為dom對象是屬性結構,所以使用JavaScript對象就可以簡單表示。而原生dom有許多屬性、事件,即使創建一個空div也要付出昂貴的代價。
// 而虛擬dom提升性能的點在於DOM發生變化的時候,通過diff算法對比,計算出需要更改的DOM,只對變化的DOM進行操作,而不是更新整個視圖。。。
2. vue 中的h函數
h函數就是vue中的createElement方法,這個函數作用就是創建虛擬dom,追蹤dom變化的。。
// 在vue腳手架中,我們經常會看到這樣一段代碼:
const app = new Vue({
··· ···
render:function(createElement){
return createElment(App)
}
})
// 這個render方法也可以寫成這樣:
const app = new Vue({
··· ···
render:function(createElement){
return createElment(App)
}
})
// 在看一個例子:寫一個main.jsx文件
function getVDOM(){
return (
<div id="app">
<p className="text">hello world</p>
</div>
)
}
// 使用bable編譯之后:
function getVDOM(){
return h("div",{
id: "app"
},h("p",{
className: "text"
},"hello world"))
}
// 上邊代碼:最終html代碼會被編譯成h函數的渲染形式。返回的是一個虛擬DOM對象,通過diff算法,來追蹤自己要如何改變真實DOM。
function h(tag,props,...children){//h函數,返回一個虛擬dom對象
return {
tag,
props:props || {},
children:children.flat()//扁平化數組,降至一維數組
}
}
// 我們在看下官方文檔所說的createElement函數,它返回的實際上不是一個DOM元素,更准確的名字是:createNodeDescription(直譯為——創建節點描述),
// 因為它所包含的信息會告訴vue頁面上需要渲染什么樣的節點,包括其子節點的描述信息。我們把這樣的節點叫做:“虛擬節點(virtual node)”,
// 也常簡寫為:“VNode”。(看了以上的案例相信在看剛這段話思路會更加清晰)
createElment參數(也就是h函數):
我們還是以官方文檔的解釋來講,createElment函數接受三個參數,分別是:
參數一:tag(標簽名)、組件的選項對象、函數(必選);
參數二:一個對象,標簽的屬性對應的數據(可選);
參數三:子級虛擬節點,字符串形式或數組形式,子級虛擬節點也需要使用createElement構建。
// 在模板中渲染
<div id="app">
{{name}}
<p>{{age}}</p>
</div>
//在render函數中渲染
render:function(createElement){
return createElement("div",{id:"app"},[this.name,createElement("p",this.age)])
}
// 上邊代碼,值得注意的是,如果父元素有文本內容,在render函數中寫的時候,內容寫在參數三——數組的第一個參數中。
再來一個官方文檔例子:
// 在模板中渲染
<ul v-if="items.length">
<li v-for="item in items">{{item.name}}</li>
</ul>
<p v-else>No items</p>
// 在render函數中渲染
data:{
items:[{name:"l"},{name:"x"},{name:"c"}]
},
render:function(createElement){
if(this.items.length){
return createElement("ul",this.items.map(function(ele){
return createElement("li",ele.name)
}))
}else{
return createElment("p","No items")
}
}