模板語法
Vue.js使用了基于HTML的模板語法,允許開發者聲明式的將DOM綁定到底層vue實例的數據,所有vuejs的模板都是合法的HTML,所以可以被遵循規范的瀏覽器和HTML解析器解析。
在底層實現上,vue將模板編譯成虛擬dom渲染函數,結合響應系統,vue可以智能的計算出最少需要渲染多少組件,并且把dom操作次數減到最小。
如果熟悉虛擬dom并且偏愛js的原始力量,也可以不使用模板,,直接寫渲染 (render) 函數,使用可選的 JSX 語法。
什么是虛擬dom
為何需要虛擬dom
dom是很大的,頁面元素非常龐大,而且頁面的性能也是由js引起的,大部分都是由操作dom引起。
如果對前端的工作進行抽象的話,就是維護狀態和更新視圖,比如vue,前端的框架主要發展方向就是解放DOM操作的復雜性。
如何理解虛擬dom
相對于dom對象,原生的js處理起來更快,而且處理更簡單,DOM 樹上的結構、屬性信息我們都可以很容易地用 JavaScript 對象表示出來:
var element = {
tagName: 'ul', // 節點標簽名
props: { // DOM的屬性,用一個對象存儲鍵值對
id: 'list'
},
children: [ // 該節點的子節點
{tagName: 'li', props: {class: 'item'}, children: ["Item 1"]},
{tagName: 'li', props: {class: 'item'}, children: ["Item 2"]},
{tagName: 'li', props: {class: 'item'}, children: ["Item 3"]},
]
}
//以上的react代碼轉化為html如下
<ul id='list'>
<li class='item'>Item 1</li>
<li class='item'>Item 2</li>
<li class='item'>Item 3</li>
</ul>
所以我們知道,dom樹信息是可以用js來表示的,反過來,我們可以使用js對象來表示dom樹的結構,并且來構建一顆真正的dom樹。
之前提到的,狀態變更→視圖重新渲染,這里有一點變化,js結構所表示的頁面dom信息結構,狀態變更的時候,他會變化,但是此時真正的dom還沒有變化。
但是新渲染的dom樹可以與之前的dom樹進行對比,記錄兩棵樹的差異,記錄的不同就是我們真正需要對dom的操作了。把這些差異應用在真正的dom樹上,頁面就會改變了。這樣就可以做到,視圖的結構確實是全新渲染了,操作dom 的時候也是變更的不同的地方而已。
以上就是大致virtual dom的算法,
大致包括以下幾個步驟:
1.用js對象結構表示dom樹的結構,然后用這個js對象結構樹,構建一個真正的dom樹,插入到文檔當中。
2.當狀態變更的時候,重新構造一顆新的js對象樹,然后新舊樹比較兩棵樹之間的差異,然后記錄下來。
3.將記錄下來的差異應用到步驟1所構建的真正的dom樹上,視圖就更新了。
Virtual DOM 本質上就是在 JS 和 DOM 之間做了一個緩存。可以類比 CPU 和硬盤,既然硬盤這么慢,我們就在它們之間加個緩存:既然 DOM 這么慢,我們就在它們 JS 和 DOM 之間加個緩存。CPU(JS)只操作內存(Virtual DOM),最后的時候再把變更寫入硬盤(DOM)。
插值
文本
數據綁定最常見的形式就是使用“Mustache”語法 (雙大括號) 的文本插值:
<span>Message: {{ msg }}</span>
Mustache 標簽將會被替代為對應數據對象上 msg 屬性的值。無論何時,綁定的數據對象上 msg 屬性發生了改變,插值處的內容都會更新。這是響應式的。
通過v-once
指令,我們也可以進行一次性的插值,避免后續 msg 值改變的時候,后續修改內容,但請留心這會影響到該節點上的其它數據綁定:
<span v-once>這個將不會改變: {{ msg }}</span>
原始HTML
雙大括號會將數據解釋為普通文本,而非 HTML 代碼。為了輸出真正的 HTML,你需要使用 v-html
指令
雙大括號會將數據解釋為普通文本,并非 HTML 代碼,如果我們需要輸出真正的HTML代碼,就需要使用v-html
指令。
<p>Using mustaches: {{ rawHtml }}</p>
<p>Using v-html directive: <span v-html="rawHtml"></span></p>
后者中,<span>
標簽的內容會被替換成屬性值rawHtml
,直接作為新的HTML
站點上動態渲染的任意 HTML 可能會非常危險,因為它很容易導致 XSS 攻擊。請只對可信內容使用 HTML 插值,絕不要對用戶提供的內容使用插值。
特性
Mustache 語法不能作用在 HTML 特性上,遇到這種情況應該使用 v-bind 指令:
<div v-bind:id="dynamicId"></div>
這里的意思就是動態的綁定了id
<button v-bind:disabled="isButtonDisabled">Button</button>
如果 isButtonDisabled
的值是 null、undefined 或 false
,則 disabled
特性甚至不會被包含在渲染出來的 <button>
元素中。
如果是true
,那么這個button
就是disable
,不可點擊的。
使用js表達式
目前在模板中,我們一直都只綁定簡單的屬性鍵值。但實際上,對于所有的數據綁定,Vue.js 都提供了完全的 JavaScript 表達式支持。
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
<div v-bind:id="'list-' + id"></div>
這些表達式會在所屬 Vue 實例的數據作用域下作為 JavaScript 被解析。有個限制就是,每個綁定都只能包含單個表達式,所以下面的例子都不會生效。
注意:
模板表達式都被放在沙盒中,只能訪問全局變量的一個白名單,如 Math 和 Date或者用戶在data中定義的 。你不應該在模板表達式中試圖訪問用戶定義的全局變量。
指令
指令是帶有v-
前綴的特殊特性的,指令特性的值,預期是單個的js表達式,除了v-for
指令,當其中表達式的值改變時,會產生連帶影響,響應式的作用于DOM中。
<p v-if="!seen">hahahahhaha</p>
export default {
name: 'App',
data(){
return{
seen:false
}
}
}
參數
一些指令能夠接收一個參數,在指令的名稱后面用":"來表示,例如:
<a v-bind:href="url">...</a>
這里就能響應式的更新href中的url。
在這里 href 是參數,告知 v-bind 指令將該元素的 href 特性與表達式 url 的值綁定。
另外一個是 v-on
指令,這是用來監聽DOM事件的,
<p v-on:click="handleClick()">點擊</p>
export default {
name: 'App',
data(){
return{
}
},
methods:{
handleClick(){
console.log(1)
}
}
}
這里是在p標簽上綁定了click
事件,事件的方法則卸載methods
中。
并且在這里,v-on
后面的參數就是事件名稱,click,mouseover
等。
修飾符
修飾符 (Modifiers) 是以半角句號 . 指明的特殊后綴,用于指出一個指令應該以特殊方式綁定。例如,.prevent
修飾符告訴v-on
指令對于觸發的事件調用 event.preventDefault()
:
還有在按鍵事件中會用到,keyup.center
這樣的修飾符告訴按鍵按下的是center鍵,也是對事件的一個補充。
<input type="text" @keyup.enter="test()">
在接下來對 v-on
和 v-for
等功能的探索中,你會看到修飾符的其它例子。
縮寫
v-bind的縮寫
<!-- 完整語法 -->
<a v-bind:href="url">...</a>
<!-- 縮寫 -->
<a :href="url">...</a>
v-on的縮寫
<!-- 完整語法 -->
<a v-on:click="doSomething">...</a>
<!-- 縮寫 -->
<a @click="doSomething">...</a>