一.模板語法:允許開發(fā)者把DOM綁定在最底層Vue實例上。在底層實現(xiàn)上,Vue會將模板編譯成虛擬DOM渲染函數(shù),Vue可以計算出最少需要重新渲染多少組件,并減少DOM操作。
1.插值
#文本
? 數(shù)據綁定最常見的就是Mustache語法(雙大括號){{msg}}的文本插值。你也可以用v-once指令來定義一次性插值,數(shù)據改變插值處的內容也不會改變,但是請注意,這會影響到該節(jié)點的其他插值。
//html? ? ??
?
我在這里給span標簽添加了一個點擊事件,運用了v-once指令,點擊span標簽內容仍不會改變。
?
#v-html
?
雙大括號輸出的只是文本,想輸出html代碼,需要用到v-html指令
//html和js? ? ? ? ?
?
瀏覽器里,上面輸出的就是純文本,下面就是把aaa里的東西變成了html代碼再渲染到了瀏覽器上,可以看到字體變成了紅色。
!注意:你的站點上動態(tài)渲染的任意 HTML 可能會非常危險,因為它很容易導致 XSS攻擊。請只對可信內容使用 HTML 插值,絕不要對用戶提供的內容使用插值。
?
#特性
?
Mustache語法不能作用在HTML特性上,需要用v-bind指令來進行操作,
用v-bind把class綁定在div上,shtie是一個變量名,初始值等于one,div初始是one的樣式。當點擊div時,改變shtie變量的值為two,div就會變?yōu)閠wo的樣式。
//點擊前? ?
?
v-bind也可以用來綁定布爾值
<input v-bind:disabled="isButtonDisabled" /> isButtonDisabled的值如果為false、null、undefined,那么disabled不會被包含在渲染出的<input>元素中:? isButtonDisabled=false //未禁用? ???
? 這兩種寫法顯示是一樣的,可以給data中的firstName和lastName重新賦值,但是給reverseMsg重新賦值就會報錯,提示沒有setter函數(shù),在需要時也可以提供一個setter函數(shù)。
這是因為你對reverseMsg賦值時,傳入的值保存在value中,然后把value中的值被空格分割成一個數(shù)組分別賦給firstName和lastName,當firstName和lastName改變時,就又觸發(fā)計算屬性重新計算,從而改變頁面。
?
#計算屬性緩存vs方法
?
通過在表達式中調用方法也可以達到同樣的效果:
?
?
? 雖然兩個方式最后的結果是相同的,但是不同的是計算屬性是基于它們的響應式依賴緩存的,只有相關響應式依賴改變它們才會重新求值,也就是說只要msg沒有發(fā)生改變,多次訪問reverseMsg計算屬性會立即返回之前的計算結果,而不必再執(zhí)行函數(shù)。
? 相比之下,每次觸發(fā)重新渲染,調用方法將總會再次執(zhí)行函數(shù)。
? 為什么要緩存?假設有一個計算屬性A,它需要做一些非常復雜且大量的計算,然后有一個依賴于A計算屬性,如果沒有緩存,我們會不可避免的多次執(zhí)行A中的getter函數(shù)。如果你不希望有緩存,可用方法代替。
? ? ? ? ? ?#計算屬性vs偵聽屬性
?
? vue提供了一種通用的方式來觀察和響應vue實例上的數(shù)據變動:偵聽屬性watch。
? //html和js? ?
?
? 其中newVal是改變之后的值,oldVal是改變之前的值。
當有一些數(shù)據需要隨著其它數(shù)據變動而變動時,很容易濫用 watch,通常更好的做法是使用計算屬性而不是命令式的回調watch。
三. class與style綁定
操作元素的 class 列表和內聯(lián)樣式是數(shù)據綁定的一個常見需求。因為它們都是屬性,所以我們可以用 v-bind處理它們:只需要通過表達式計算出字符串結果即可。不過,字符串拼接麻煩且易錯。因此,在將 v-bind用于class和style時,Vue做了專門的增強。表達式結果的類型除了字符串之外,還可以是對象或數(shù)組。
1. 綁定HTML Class
#對象語法
? 我們給v-bind:class綁定一個對象,來動態(tài)切換css:
<div v-bind:class="{ active:isActive }">
現(xiàn)在active這個class的存在與否就取決于isActive的真值了。
你可以在對象傳遞更多屬性來動態(tài)切換多個class,此外v-bind:class也可以和普通class共存:
//HTML和js? ??
?
? 當 isTwo 和 isError 變化,class列表也相應的更新。例如isError的值變?yōu)閠rue,class列表將變?yōu)閏lass=“one two button-text”。
綁定的對象不用內聯(lián)定義在模塊里:
//HTML和js? ? ?
?
? 兩種寫法渲染是相同的,也可以在這里綁定一個返回對象的計算屬性,這是個常用且強大的模式:
?
?
#數(shù)組語法
我們可以傳一個數(shù)組給v-bind:class,以應用一個class列表:
//html和JS? ??
?
也可以運用三元表達式,<div? v-bind : class =" [ isActive ? active : ' ' ,errorClass ] "></div>。
這樣寫始終添加errorClass,但只有isActive為真值時才添加active。不過當有多個條件class時,這樣寫太繁瑣,所有數(shù)組語法也可以使用對象語法:
<div? v-bind : class= " [ { active : isActive } ,errorClass ] ">
#用在組件上
當在一個自定義組件上使用?class
?屬性時,這些類將被添加到該組件的根元素上面。這個元素上已經存在的類不會被覆蓋。
? //父組件??
?
? 我這里是將組件拆出去,然后在父組件里引用子組件。以上面為例,bbb相當于一個包在子組件外的div,是子組件的容器,就算沒有定義類名,這個div還是會存在。
對于帶數(shù)據綁定也同樣適用:
<myComponent? v-bind : class = " { active : isActive } "></myComponent>? ? ? 當isActive為真值時,active將被渲染。
2. 綁定內聯(lián)樣式
#對象語法
v-bind:style的對象語法很直觀,看著非常像css,但其實是一個JavaScript對象,css屬性名可以用駝峰式命名(fontSize)或短橫線分割(font-size,記得用引號括起來:“font-size”)來命名:
?
? 直接綁定到一個樣式對象通常更好,這會讓模板更清晰:
?
同樣的,對象語法常常結合返回對象的計算屬性使用。
#數(shù)組語法
v-bind:style可以將多個樣式對象應用到一個元素上:
?
? #自動添加前綴
當?v-bind:style
?使用需要添加瀏覽器引擎前綴的 CSS 屬性時,如?transform
,Vue.js 會自動偵測并添加相應的前綴。
? #多重值
從 2.3.0 起你可以為?style
?綁定中的屬性提供一個包含多個值的數(shù)組,常用于提供多個帶前綴的值,例如:
<div :style = " { display: [ '-webkit-box','-ms-flexbox','flex' ] }"></div>
這樣寫只會渲染數(shù)組中最后一個被瀏覽器支持的值。在本例中,如果瀏覽器支持不帶瀏覽器前綴的 flexbox,那么就只會渲染?display: flex
。
?四. 條件渲染
1. v-if
v-if
?指令用于條件性地渲染一塊內容。這塊內容只會在指令的表達式返回真值的時候被渲染。
? <div v-if="awesome"> yes </div>
也可以用?v-else
?添加一個“else 塊”:
? <div v-if="awesome"> yes </div>
<div v-else> no </div>
?
#在template元素上使用v-if條件渲染分組
?
因為?v-if
?是一個指令,所以必須將它添加到一個元素上。但是如果想切換多個元素呢?此時可以把一個?<template>
?元素當做不可見的包裹元素,并在上面使用?v-if
。最終的渲染結果將不包含?<template>
?元素。
<template v-if=" ok ">
<h1>為真時</h1>
<div>這里</div>
<p>會渲染</p>
</template>
?
#v-else
你可以使用?v-else
?指令來表示?v-if
?的“else 塊”:
<div v-if=" Math.random() > 0.5 ">滿足條件時渲染</div>
<div v-else>否則渲染這里</div>
? ? ?v-else
?元素必須緊跟在帶?v-if
?或者?v-else-if
?的元素的后面,否則它將不會被識別。
?
#v-else-if
v-else-if
,顧名思義,充當?v-if
?的“else-if 塊”,可以連續(xù)使用:
<div v-if= "index === 1"> A </div>
<div v-else-if= "index === 2"> B </div>
<div v-else-if= "index === 3"> C </div>
<div v-else-if= "index === 4"> D </div>
<div v-else> 不是A/B/C/D </div>
類似于?v-else
,v-else-if
?也必須緊跟在帶?v-if
?或者?v-else-if
?的元素之后。
?
#用key管理可復用的元素
? Vue 會盡可能高效地渲染元素,通常會復用已有元素而不是從頭開始渲染。這么做除了使 Vue 變得非??熘猓€有其它一些好處。例如,如果你允許用戶在不同的登錄方式之間切換:
?
? 那么在上面的代碼中切換?loginType
?將不會清除用戶已經輸入的內容。因為兩個模板使用了相同的元素,<input>
?不會被替換掉——僅僅是替換了它的?placeholder
。
這樣也不總是符合實際需求,所以 Vue 提供了一種方式來表達“這兩個元素是完全獨立的,不要復用它們”。只需添加一個具有唯一值的?key
?屬性即可:
?
? 注意,與<input>同級 <div>?元素仍然會被高效地復用,因為它們沒有添加?key
?屬性。
?
2. v-show
另一個用于根據條件展示元素的選項是?v-show
?指令。用法大致一樣:
<div v-show=" ok ">為真時渲染</div>
不同的是帶有?v-show
?的元素始終會被渲染并保留在 DOM 中。v-show
?只是簡單地切換元素的 CSS 屬性?display
。
??!注意:v-show不支持<template>元素,也不支持v-else。
?
3. v-if 與 v-show
v-if
?是“真正”的條件渲染,因為它會確保在切換過程中條件塊內的事件監(jiān)聽器和子組件適當?shù)乇讳N毀和重建。
v-if
?也是惰性的,如果在初始渲染時條件為假,則什么也不做,直到條件第一次變?yōu)檎鏁r,才會開始渲染條件塊。
相比之下,v-show
?就簡單得多,不管初始條件是什么,元素總是會被渲染,并且只是簡單地基于 CSS 進行切換。
一般來說,v-if
?有更高的切換開銷,而?v-show
?有更高的初始渲染開銷。因此,如果需要非常頻繁地切換,則使用?v-show
?較好;如果在運行時條件很少改變,則使用?v-if
?較好。
4. v-if 與 v-show
不推薦 v-if 與 v-for 同時使用。 v-for的優(yōu)先級是高于v-if的,也就是說會先執(zhí)行v-for,然后在每個for里都會執(zhí)行一遍if。
這種優(yōu)先級機制在有些地方是比較實用的,比如需要渲染滿足條件的項:
?
? 在這個例子中,我們只想渲染為0的項,就可以利用這個機制。
?五.??列表渲染
1. 用v-for把一個數(shù)組對應為一組元素
我們可以用?v-for
?指令基于一個數(shù)組來渲染一個列表。v-for
?指令需要使用?item in items
?形式的特殊語法,其中?items
?是源數(shù)據數(shù)組,而?item
?則是被迭代的數(shù)組元素的別名。
?
? 在?v-for
?塊中,我們可以訪問所有父作用域的屬性。v-for
?還支持一個可選的第二個參數(shù),即當前項的索引。
?
?
你也可以用?of
?替代?in
?作為分隔符,因為它更接近 JavaScript 迭代器的語法:
<div? v-for=" item of items ">
2. 在v-for 里使用對象
用 v-for 遍歷對象:
?
? 第一個參數(shù)為值,第二個的參數(shù)為 property 名稱 (也就是鍵名),第三個參數(shù)作為索引。
在遍歷對象時,會按?Object.keys()
?的結果遍歷,但是不能保證它的結果在不同的 JavaScript 引擎下都一致。
3. 維護狀態(tài)
當 Vue 正在更新使用?v-for
?渲染的元素列表時,它默認使用“就地更新”的策略。如果數(shù)據項的順序被改變,Vue 將不會移動 DOM 元素來匹配數(shù)據項的順序,而是就地更新每個元素,并且確保它們在每個索引位置正確渲染。
為了給 Vue 一個提示,以便它能跟蹤每個節(jié)點的身份,從而重用和重新排序現(xiàn)有元素,你需要為每項提供一個唯一?key
?屬性:<div? v-for =" item in items "? v-bind : key =" item.id ">。
建議盡可能在使用?v-for
?時提供?key
?attribute,除非遍歷輸出的 DOM 內容非常簡單,或者是刻意依賴默認行為以獲取性能上的提升。因為它是 Vue 識別節(jié)點的一個通用機制,key
?并不僅與?v-for
?特別關聯(lián),還有其他的用途。
不要使用對象或數(shù)組之類的非基本類型值作為?v-for
?的?key
。請用字符串或數(shù)值類型的值。
4. 更新檢測
#變異方法
Vue 將被偵聽的數(shù)組的變異方法進行了包裹,所以它們也將會觸發(fā)視圖更新。這些被包裹過的方法包括:
push()? ? ? ? ?//可向數(shù)組的末尾添加一個或多個元素,并返回新的長度。
pop() ? ? ? ?//用于刪除并返回數(shù)組的最后一個元素。
shift()? ? ? ? //用于把數(shù)組的第一個元素從其中刪除,并返回第一個元素的值。
? unshift() ? ? ? //可向數(shù)組的開頭添加一個或更多元素,并返回新的長度。?
splice()? ? ? ?//向/從數(shù)組中添加/刪除項目,然后返回被刪除的項目。
sort()? ? ? ? //用于對數(shù)組的元素進行排序。
reverse()? ? ? //用于顛倒數(shù)組中元素的順序。
? #替換數(shù)組
變異方法,顧名思義,會改變調用了這些方法的原始數(shù)組。相比之下,也有非變異 (non-mutating method) 方法,例如?filter()
、concat()
?和?slice()
?。它們不會改變原始數(shù)組,而總是返回一個新數(shù)組。當使用非變異方法時,可以用新數(shù)組替換舊數(shù)組:
example1.items = example1.items.filter(function (item) {
return item.message.match(/Foo/)
})?
你可能認為這將導致 Vue 丟棄現(xiàn)有 DOM 并重新渲染整個列表。幸運的是,事實并非如此。Vue 為了使得 DOM 元素得到最大范圍的重用而實現(xiàn)了一些智能的啟發(fā)式方法,所以用一個含有相同元素的數(shù)組去替換原來的數(shù)組是非常高效的操作。
#注意事項
由于 JavaScript 的限制,Vue?不能檢測以下數(shù)組的變動:
vm.items[indexOfItem] = newValue
vm.items.length = newLength
為了解決第一類問題,以下兩種方式都可以實現(xiàn)和?vm.items[indexOfItem] = newValue
?相同的效果,同時也將在響應式系統(tǒng)內觸發(fā)狀態(tài)更新:
// Vue.set? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??// Array.prototype.splice
Vue.set(vm.items, indexOfItem, newValue)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??vm.items.splice(indexOfItem, 1, newValue)
為了解決第二類問題,你可以使用?splice
:? vm.items.splice(newLength)
5.顯示過濾/排序后的結果
有時,我們想要顯示一個數(shù)組經過過濾或排序后的版本,而不實際改變或重置原始數(shù)據。在這種情況下,可以創(chuàng)建一個計算屬性,來返回過濾或排序后的數(shù)組。
?
?
?
?
這里改變了原數(shù)組,但是因為是計算屬性,沒有setter函數(shù)不能改變它的依賴,所以number不會改變,可以正常遍歷。
?
在計算屬性不適用的情況下 (例如,在嵌套?v-for
?循環(huán)中) 你可以使用一個方法:
?
?
? 注意,這里使用的方法必須是返回一個新數(shù)組的方法,使用改變原數(shù)組但不返回新數(shù)組的方法,會無限更新循環(huán)。
6. 在v-for 里使用值范圍
v-for
?也可以接受整數(shù)。在這種情況下,它會把模板重復對應次數(shù)。
<div> <span v-for="n in 10">{{ n }} </span> </div>
7. 在<template> 上使用v-for
?
8. 在組件上使用v-for
在自定義組件上,你可以像在任何普通元素上一樣使用?v-for
?。
<myComponent v-for="item in items" :key="item.id"></myComponent>
2.2.0 的版本里,當在組件上使用?v-for
?時,key
?現(xiàn)在是必須的。
然而,任何數(shù)據都不會被自動傳遞到組件里,因為組件有自己獨立的作用域。為了把迭代數(shù)據傳遞到組件里,我們要使用 prop:
//父組件? ?
//子組件
? 把父組件中items的值傳給子組件,需要用到prop,把items綁定在子組件上,在子組件里用props接收數(shù)據。
?
六. 事件處理
1. 監(jiān)聽事件
可以用?v-on
?指令監(jiān)聽 DOM 事件,并在觸發(fā)時運行一些 JavaScript 代碼。
?
除了直接綁定到一個方法,也可以在內聯(lián) JavaScript 語句中調用方法:
有時也需要在內聯(lián)語句處理器中訪問原始的 DOM 事件??梢杂锰厥庾兞?$event
?把它傳入方法:
?
preventDefault() 方法阻止元素發(fā)生默認的行為(例如,當點擊提交按鈕時阻止對表單的提交)。
2. 事件修飾符
方法只有純粹的數(shù)據邏輯,而不是去處理 DOM 事件細節(jié)。
<!-- 阻止單擊事件繼續(xù)傳播 -->
<!-- 阻止冒泡 -->
?
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重載頁面 -->
<!-- 阻止默認事件 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修飾符可以串聯(lián) -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只有修飾符 -->
<form v-on:submit.prevent></form>
<!-- 添加事件監(jiān)聽器時使用事件捕獲模式 -->
<!-- 即元素自身觸發(fā)的事件先在此處理,然后才交由內部元素進行處理 -->
<!--?通常我們只監(jiān)聽冒泡過程。在vue中,當我們添加了事件修飾符capture后,才會變成捕獲監(jiān)聽器。 -->
<div v-on:click.capture="doThis">...</div>
<!-- 只當在 event.target 是當前元素自身時觸發(fā)處理函數(shù) -->
<!-- 即事件不是從內部元素觸發(fā)的 -->
<div v-on:click.self="doThat">...</div>
使用修飾符時,順序很重要;相應的代碼會以同樣的順序產生。因此,用?v-on:click.prevent.self
?會阻止所有的點擊,而?v-on:click.self.prevent
?只會阻止對元素自身的點擊。
Vue 還對應?addEventListener
?中的?passive
?選項提供了?.passive
?修飾符。
<!-- 滾動事件的默認行為 (即滾動行為) 將會立即觸發(fā) -->
<!-- 而不會等待 `onScroll` 完成 -->
<!-- 這其中包含 `event.preventDefault()` 的情況 -->
<div v-on:scroll.passive="onScroll">...</div>
不要把?.passive
?和?.prevent
?一起使用,因為?.prevent
?將會被忽略,同時瀏覽器可能會向你展示一個警告。請記住,.passive
?會告訴瀏覽器你不想阻止事件的默認行為。
3. 按鍵修飾符
在監(jiān)聽鍵盤事件時,我們經常需要檢查詳細的按鍵。Vue 允許為?v-on
?在監(jiān)聽鍵盤事件時添加按鍵修飾符:
? ? <!-- 只有在 `key` 是 `Enter` 時調用 `vm.submit()` -->
<input v-on:keyup.enter="submit">
也可以直接將?KeyboardEvent.key
?暴露的任意有效按鍵名轉換為 kebab-case 來作為修飾符。
<input v-on:keyup.page-down="onPageDown">
在上述示例中,處理函數(shù)只會在?$event.key
?等于?PageDown
?時被調用。
七. 表單輸入綁定
1. 基礎用法
你可以用?v-model
?指令在表單?<input>
、<textarea>
?及?<select>
?元素上創(chuàng)建雙向數(shù)據綁定。它會根據控件類型自動選取正確的方法來更新元素。盡管有些神奇,但?v-model
?本質上不過是語法糖。它負責監(jiān)聽用戶的輸入事件以更新數(shù)據,并對一些極端場景進行一些特殊處理。
v-model
?會忽略所有表單元素的?value
、checked
、selected
?特性的初始值而總是將 Vue 實例的數(shù)據作為數(shù)據來源。你應該通過 JavaScript 在組件的?data
?選項中聲明初始值。
#文本
? #多行文本
?
? 在文本區(qū)域插值 (<textarea>{{text}}</textarea>
) 并不會生效,應用?v-model
?來代替。
? #復選框
單個復選框,綁定布爾值
?
?
? 多個復選框綁定同一數(shù)組
?
? #單選按鈕
?
? #選擇框
?
? 如果?v-model
?表達式的初始值未能匹配任何選項,<select>
?元素將被渲染為“未選中”狀態(tài)。在 iOS 中,這會使用戶無法選擇第一個選項。因為這樣的情況下,iOS 不會觸發(fā) change 事件。因此,更推薦像上面這樣提供一個值為空的禁用選項。
#多選(綁定到一個數(shù)組)
?
?
v-for渲染動態(tài)選項
?
? 2. 值綁定
對于單選按鈕,復選框及選擇框的選項,v-model
?綁定的值通常是靜態(tài)字符串 (對于復選框也可以是布爾值)。
? ? 但是有時我們可能想把值綁定到 Vue 實例的一個動態(tài)屬性上,這時可以用?v-bind
?實現(xiàn),并且這個屬性的值可以不是字符串。
? #單選框
?
? #選擇框選項
八. 組件基礎
1. 基本示例
vue項目目錄結構
components下的base里放的是基礎組件,business放的是業(yè)務組件。可能你的許多組件只是包裹了一個輸入框或按鈕之類的元素,是相對通用的。我們有時候會把它們稱為基礎組件,它們會在各個組件中被頻繁的用到。
在組件文件夾下創(chuàng)建vue文件,在父組件頁面里引用子組件,
?
?
? 因為組件是可復用的 Vue 實例,所以它們與?new Vue
?接收相同的選項,例如?data
、computed
、watch
、methods
?以及生命周期鉤子等。
2. 組件的復用
你可以將組件進行任意次數(shù)的復用:
?
? 每個組件都會各自獨立維護,每用一次組件,就會有一個它的新實例被創(chuàng)建。
一個組件的?data
?選項必須是一個函數(shù),因此每個實例可以維護一份被返回對象的獨立的拷貝:
data(){
return{
}
}
如果 Vue 沒有這條規(guī)則,復用組件,操作其中一個,其他相同組件就會受到影響。
3. 組件的組織
通常一個應用會以一棵嵌套的組件樹的形式來組織:
? 例如,你可能會有頁頭、側邊欄、內容區(qū)等組件,每個組件又包含了其它的像導航鏈接、博文之類的組件。
4. 通過prop向子組件傳遞數(shù)據:這個我在列表渲染里,在組件上使用v-for實際操作過一次。
5. 單個根元素:每個組件里必須在<template>里套一個<div>,然后在這個最外層<div>里寫你要實現(xiàn)的內容。
? ? 6. 監(jiān)聽子組件事件:
#子組件拋出事件
?
#父組件里調用事件
?
#組件上使用v-model
?
自定義事件也可以用于創(chuàng)建支持?v-model
?的自定義輸入組件。
<input v-model="searchText">
等價于
<input? ?v-bind:value="searchText"? ??v-on:input="searchText = $event.target.value" >
當用在組件上時,v-model
?則會這樣:
<custom-input? ?v-bind:value="searchText"? ?v-on:input="searchText = $event" ></custom-input>
為了讓它正常工作,這個組件內的?<input>
?必須:
value
?特性綁定到一個名叫?value
?的 prop 上input
?事件被觸發(fā)時,將新的值通過自定義的?input
?事件拋出? 寫成代碼后:
?
現(xiàn)在?v-model
?就應該可以在這個組件上完美地工作起來了:
<custom-input v-model="searchText"></custom-input>
? 7. 通過插槽分發(fā)內容
和 HTML 元素一樣,我們經常需要向一個組件傳遞內容,像這樣:
<myComponent>123</myComponent>
可能什么也渲染不出來,也可能會渲染出這樣的東西:
?
? ? 幸好,Vue 自定義的?<slot>
?元素讓這變得非常簡單:
?
? 只需要在子組件里,把<slot>標簽寫在你想添加的位置。這就是插槽,后面還會介紹更多。
九. 組件注冊
1.組件名:單文件組件(.vue),推薦駝峰式命名(myComponent)或跟據公司規(guī)范命名。
2.全局注冊
在注冊之后可以用在任何新創(chuàng)建的 Vue 根實例 (new Vue
) 的模板中。
創(chuàng)建一個vue文件作為組件
?
? 在main.js里引入組件路徑并創(chuàng)建組件
?
在父組件里使用組件標簽名
?
? 3. 局部注冊:本文中除了全局注冊,剩下的組件注冊都是局部注冊。
十. Prop
1.Prop大小寫
HTML 中的特性名是大小寫不敏感的,所以瀏覽器會把所有大寫字符解釋為小寫字符。這意味著當你使用 DOM 中的模板時,駝峰命名法 的 prop 名需要使用其等價的短橫線分隔命名:
props: [?' postTitle ' ]
<myComponent? post-title=" hello "></myComponent>
如果使用字符串模板,這個限制就不存在了。
2.Prop類型
現(xiàn)在我們只看到以字符串數(shù)組形式列出的prop:
props: ['title', 'likes', 'isPublished', 'commentIds', 'author']
但是,通常你希望每個 prop 都有指定的值類型。這時,你可以以對象形式列出 prop,這些屬性的名稱和值分別是 prop 各自的名稱和類型:
?
?
? 這不僅為組件提供了文檔,還會在它們遇到錯誤的類型時從瀏覽器的 JavaScript 控制臺提示用戶。
3.單向數(shù)據流
所有的 prop 都使得其父子 prop 之間形成了一個單向下行綁定:父級 prop 的更新會向下流動到子組件中,但是反過來則不行。這樣會防止從子組件意外改變父級組件的狀態(tài),從而導致你的應用的數(shù)據流向難以理解。額外的,每次父級組件發(fā)生更新時,子組? ? ? ? ? ? ? ? 件中所有的 prop 都將會刷新為最新的值。這意味著你不應該在一個子組件內部改變 prop。如果你這樣做了,Vue 會在瀏覽器的控制臺給出警告。
?
?
? 這里有兩種常見的試圖改變一個prop的情形:
1.這個 prop 用來傳遞一個初始值;這個子組件接下來希望將其作為一個本地的 prop 數(shù)據來使用。在這種情況下,最好定義一個本地的 data 屬性并將這個 prop 用作其初始值:
?
?
? 2.這個 prop 以一種原始的值傳入且需要進行轉換。在這種情況下,最好使用這個 prop 的值來定義一個計算屬性:
?
4. prop 驗證
我們可以為組件的 prop 指定驗證要求,例如你知道的這些類型。如果有一個需求沒有被滿足,則 Vue 會在瀏覽器控制臺中警告你。這在開發(fā)一個會被別人用到的組件時尤其有幫助。
為了定制 prop 的驗證方式,你可以為?props
?中的值提供一個帶有驗證需求的對象,而不是一個字符串數(shù)組。
?
?
? 當prop驗證失敗的時候,Vue將會產生一個控制臺的警告。
? type可以是下面原生構造函數(shù)中的一個:
String
Number
Boolean
Array
Object
Date
Function
Symbol
5.非prop特性:組件可以接受任意的特性,而這些特性會被添加到這個組件的根元素上
十一. 自定義事件
1.事件名
不同于組件和 prop,事件名不存在任何自動化的大小寫轉換。而是觸發(fā)的事件名需要完全匹配監(jiān)聽這個事件所用的名稱。舉個例子,如果觸發(fā)一個駝峰式名字的事件:
? this.$emit('myEvent')
則監(jiān)聽這個名字的短橫線分隔命名版本是不會有任何效果的:
? <!-- 沒有效果 -->
<myComponent? @my-event="doSomething"></myComponent>
2. 將原生事件綁定到組件
Vue 提供了一個?$listeners
?屬性,它是一個對象,里面包含了作用在這個組件上的所有監(jiān)聽器。
{
focus: function (event) { /* ... */ }
input: function (value) { /* ... */ },
}
? 有了這個?$listeners
?屬性,你就可以配合?v-on="$listeners"
?將所有的事件監(jiān)聽器指向這個組件的某個特定的子元素。
十二.? 插槽:在 2.6.0 中,我們?yōu)榫呙宀酆妥饔糜虿宀垡肓艘粋€新的統(tǒng)一的語法 (即?v-slot
?指令)。它取代了?slot
?和?slot-scope
?這兩個目前已被廢棄但未被移除且仍在文檔中的特性。
1.插槽內容
上面插槽的例子只是插入了數(shù)據,其實還可以插入組件:
?
? 如果?<myComponent>
?沒有包含一個?<slot>
?元素,則該組件起始標簽和結束標簽之間的任何內容都會被拋棄。
2.編譯作用域
當你想在一個插槽中使用數(shù)據時,例如:
?
? 該插槽跟模板的其它地方一樣可以訪問相同的實例屬性 (也就是相同的“作用域”),而不能訪問?<myComponent>
?的作用域。例如?url
?是訪問不到的:
?
? 父級模板里的所有內容都是在父級作用域中編譯的;子模板里的所有內容都是在子作用域中編譯的。
3.后備內容
有時為一個插槽設置具體的后備 (也就是默認的) 內容是很有用的,它只會在沒有提供內容的時候被渲染。
? ? 我們可能希望這個?<button>
?內絕大多數(shù)情況下都渲染文本“Submit”。為了將“Submit”作為后備內容,我們可以將它放在?<slot>
?標簽內,
現(xiàn)在當我在一個父級組件中使用該組件并且不提供任何插槽內容時,后備內容“submit”將會被渲染,
但當我們提供內容,則這個提供的內容將會被渲染從而取代后備內容:
?
? 4. 具名插槽
有時我們需要多個插槽。<slot>
?元素有一個特殊的特性:name
。這個特性可以用來定義額外的插槽,一個不帶?name
?的?<slot>
?出口會帶有隱含的名字“default”。
在向具名插槽提供內容的時候,我們可以向<div>元素上使用slot指令,并以slot參數(shù)形式提供名稱。
現(xiàn)在父組件?<div>
?元素中的所有內容都將會被傳入相應的插槽。
任何沒有被包裹在帶有?slot
的?<div>
?中的內容都會被視為默認插槽的內容。
? 也可以有另一種寫法,把slot換成v-slot,但是v-slot只能添加在一個<template>上,只有一種情況例外。
當被提供的內容只有默認插槽時,組件的標簽才可以被當作插槽的模板來使用。這樣我們就可以把?v-slot
?直接用在組件上。
注意默認插槽的縮寫語法不能和具名插槽混用,因為它會導致作用域不明確。
只要出現(xiàn)多個插槽,就要用具名插槽。
5作用域插槽
有時讓插槽內容能夠訪問子組件中才有的數(shù)據是很有用的。
//父組件中
? //子組件中
? 在添加一個slot-scope屬性,給一個scope參數(shù),在子組件里也同樣使用。
還可以有其他方法,比如,<current-user>組件里的slot想訪問傳給父級渲染的數(shù)據是不行的,
如下,為了讓?user
?在父級的插槽內容中可用,我們可以將?user
?作為?<slot>
?元素的一個特性綁定上去:
? 綁定在?<slot>
?元素上的特性被稱為插槽 prop?,F(xiàn)在在父級作用域中,我們可以給?v-slot
?帶一個值來定義我們提供的插槽 prop 的名字:
? 在這個例子中,我們選擇將包含所有插槽 prop 的對象命名為 aaa,但你也可以使用任意你喜歡的名字。
#解構插槽Prop
作用域插槽的內部工作原理是將你的插槽內容包括在一個傳入單個參數(shù)的函數(shù)里:
function (slotProps) { // 插槽內容 }
這意味著?v-slot
?的值實際上可以是任何能夠作為函數(shù)定義中的參數(shù)的 JavaScript 表達式。所以在支持的環(huán)境下 (單文件組件或現(xiàn)代瀏覽器),你也可以使用?ES2015 解構來傳入具體的插槽 prop,如下:
? 這樣可以使模板更簡潔,尤其是在該插槽提供了多個 prop 的時候。它同樣開啟了 prop 重命名等其它可能,例如將?user
?重命名為?person
:
? 甚至可以定義后備內容,用于插槽 prop 是 undefined 的情形:
注意是插槽prop是undefined,在子組件會給出警告。
#動態(tài)插槽
動態(tài)指令參數(shù)也可以用在?v-slot
?上,來定義動態(tài)的插槽名:
?
? #具名插槽縮寫
v-slot:header? ? 等價于? ? #header
和其它指令一樣,該縮寫只在其有參數(shù)的時候才可用。
?十三. 動態(tài)組件&異步組件
1. 動態(tài)組件
在不同組件之間動態(tài)切換,通過 Vue 的?<component>
?元素加一個特殊的?is
?特性來實現(xiàn):
? first 、 second 、third 是注冊的三個組件,com可以是已注冊組件的名字,或一個組件的選項對象。我這里設置的是一個組件選項的數(shù)組。
? 2.在組件上使用keep-alive
? 當在first內輸入內容,然后點擊second,再切換會first,first內輸入的內容會消失。這是因為你每次切換新標簽的時候,Vue 都創(chuàng)建了一個新的 com實例。
重新創(chuàng)建動態(tài)組件的行為通常是非常有用的,但是在這個案例中,我們更希望那些標簽的組件實例能夠被在它們第一次被創(chuàng)建的時候緩存下來。為了解決這個問題,我們可以用一個?<keep-alive>
元素將其動態(tài)組件包裹起來。
?
? 注意這個?<keep-alive>
?要求被切換到的組件都有自己的名字,不論是通過組件的?name
選項還是局部/全局注冊。
十四. 混入
1.基礎
混入 (mixin) 提供了一種非常靈活的方式,來分發(fā) Vue 組件中的可復用功能。一個混入對象可以包含任意組件選項。當組件使用混入對象時,所有混入對象的選項將被“混合”進入該組件本身的選項。
創(chuàng)建混入文件
注冊一個mixin對象,定義需要的方法或者數(shù)據
? 在需要的頁面引入并使用,混入
?
? scss文件混入
創(chuàng)建scss文件并寫入需要混入的樣式
引入需要混入的文件
?
2.選項合并
當組件和混入對象含有同名選項時,這些選項將以恰當?shù)姆绞竭M行“合并”。
比如,數(shù)據對象在內部會進行遞歸合并,并在發(fā)生沖突時以組件數(shù)據優(yōu)先。
同名鉤子函數(shù)將合并為一個數(shù)組,因此都將被調用。另外,混入對象的鉤子將在組件自身鉤子之前調用。也就是說先執(zhí)行混入對象的鉤子內的操作。
值為對象的選項,例如?methods
、components
?和?directives
,將被合并為同一個對象。兩個對象鍵名沖突時,取組件對象的鍵值對。
?
3.全局混入
混入也可以進行全局注冊。使用時格外小心!一旦使用全局混入,它將影響每一個之后創(chuàng)建的 Vue 實例。使用恰當時,這可以用來為自定義選項注入處理邏輯。
? ? ? ?在main.js中定義mixin,在需要的使用的頁面直接使用
?
4.自定義合并策略
optionMergeStrategies
?主要用于?mixin
?對于子組件和父組件如果有相同的屬性(option)時的合并策略。
自定義選項將使用默認策略,即簡單地覆蓋已有值。
#defaultStrat
var defaultStrat = function (parentVal, childVal) { return childVal === undefined ? parentVal : childVal }
源代碼很簡單,傳入兩個參數(shù)?parentVal
,?childVal
?分別對應于父組件和子組件的選項,合并的策略就是,子組件的選項不存在,才會使用父組件的選項,如果子組件的選項存在,使用子組件自身的。
#option.hook
如果父組件和子組件都設置了鉤子函數(shù)選項,那么 它們會合并到一個數(shù)組里,而且父組件的鉤子函數(shù)會先執(zhí)行,最后返回一個合并后的數(shù)組。具體見源碼里的注釋。

如果想讓自定義選項以自定義邏輯合并,可以向?Vue.config.optionMergeStrategies
?添加一個函數(shù):
Vue.config.optionMergeStrategies.myOption = function (toVal, fromVal) {
// 返回合并后的值
}
對于多數(shù)值為對象的選項,可以使用與?methods
?相同的合并策略:
var strategies = Vue.config.optionMergeStrategies
strategies.myOption = strategies.methods
十五. 自定義指令
1. 簡介:除了核心功能默認內置的指令 (v-model
?和?v-show
),Vue 也允許注冊自定義指令。有的情況下,你仍然需要對普通 DOM 元素進行底層操作,這時候就會用到自定義指令。
#全局注冊
在main.js中注冊,JQuery事件中,當元素獲得焦點時,發(fā)生 focus 事件。
? #局部注冊
如果想注冊局部指令,組件中也接受一個?directives
?的選項:
? 然后你可以在模板中任何元素上使用新的?v-focus
?屬性,如下:
?
? 2.鉤子函數(shù)
一個指令定義對象可以提供如下幾個鉤子函數(shù) (均為可選):
bind:只調用一次,指令第一次綁定到元素時調用,在這里可以進行一次性的初始化設置。
inserted:被綁定元素插入父節(jié)點時調用(僅保證父節(jié)點存在,但不一定已被插入文檔中)。
update:所在組件的 VNode 更新時調用,但是可能發(fā)生在其子 VNode 更新之前。指令的值可能發(fā)生了改變,也可能沒有。但是你可以通過比較更新前后的值來忽略不必要的模板更新 (詳細的鉤子函數(shù)參數(shù)見下)。
componentUpdated:指令所在組件的 VNode 及其子 VNode 全部更新后調用。
unbind:只調用一次,指令與元素解綁時調用。
3.鉤子函數(shù)參數(shù)
? 我只寫了一個例子,大致的都相同
? 這是官網給的例子
?
#動態(tài)指令參數(shù)
指令的參數(shù)可以是動態(tài)的。例如,在?v-mydirective:[argument]="value"
?中,argument
?參數(shù)可以根據組件實例數(shù)據進行更新!這使得自定義指令可以在應用中被靈活使用。
例如你想要創(chuàng)建一個自定義指令,用來通過固定布局將元素固定在頁面上。我們可以像這樣創(chuàng)建一個通過指令值來更新豎直位置像素值的自定義指令:
?
? 這會把該元素固定在距離頁面頂部 200 像素的位置。但如果場景是我們需要把元素固定在左側而不是頂部又該怎么辦呢?這時使用動態(tài)參數(shù)就可以非常方便地根據每個組件實例來進行更新。
?
? 4.函數(shù)簡寫
如果指向在bind與update的時候執(zhí)行指令, 那么第二個參數(shù)可以直接寫函數(shù)
Vue.directive('color-swatch', function (el, binding) {
el.style.backgroundColor = binding.value
})
5.對象字面量
如果指令需要多個值,可以傳入一個 JavaScript 對象字面量。記住,指令函數(shù)能夠接受所有合法的 JavaScript 表達式。
?
?十六. 過濾器
vue允許自定義過濾器,可被用于一些常見的文本格式化。
過濾器可以用在兩個地方:雙花括號插值和?v-bind
?表達式 。
過濾器應該被添加在 JavaScript 表達式的尾部,由“管道”符號指示:
在{{}}中:{{msg | capitalize}}? ? ? ? ? ? ? ? ?在v-bind中:<div? :id="rawId | formId" >
在一個組件的選項中定義本地的過濾器:
?
? 我這里是讓輸入的值渲染在頁面上的時候前面加上$,
在創(chuàng)建 Vue 實例之前全局定義過濾器:
?
?
? 當全局過濾器和局部過濾器重名時,會采用局部過濾器。
過濾器函數(shù)總接收表達式的值 (之前的操作鏈的結果) 作為第一個參數(shù)。在上述例子中,capitalize
?過濾器函數(shù)將會收到?message
?的值作為第一個參數(shù)。
過濾器可以串聯(lián):
{{ message | filterA | filterB }}
在這個例子中,filterA
?被定義為接收單個參數(shù)的過濾器函數(shù),表達式?message
?的值將作為參數(shù)傳入到函數(shù)中。然后繼續(xù)調用同樣被定義為接收單個參數(shù)的過濾器函數(shù)?filterB
,將?filterA
?的結果傳遞到?filterB
?中。
過濾器是 JavaScript 函數(shù),因此可以接收參數(shù):
{{ message | filterA('arg1', arg2) }}
這里,filterA
?被定義為接收三個參數(shù)的過濾器函數(shù)。其中?message
?的值作為第一個參數(shù),普通字符串?'arg1'
?作為第二個參數(shù),表達式?arg2
?的值作為第三個參數(shù)。