vue基礎(學習官方文件)
基礎
介紹
是什麼
- 是一套用於構建使用者介面的漸進式框架
宣告式渲染
1 2 3 4 5 6 7 8 9 |
<div id= "app" >{{ message }}</div>
var app = new Vue({
el: '#app' ,
data: {
message: 'Hello Vue!'
}
})
|
vue 例項
1 2 3 |
var vm = new Vue({
// 選項
})
|
- 一個 Vue 應用由一個通過 new Vue 建立的根 Vue 例項,以及可選的巢狀的、可複用的元件樹組成。
- 所有的 Vue 元件都是 Vue 例項,並且接受相同的選項物件 (一些根例項特有的選項除外)。
資料與方法
1 2 3 4 5 6 7 8 9 10 11 12 |
// 我們的資料物件
var data = { a: 1 }
// 該物件被加入到一個 Vue 例項中
var vm = new Vue({
data: data
})
// 獲得這個例項上的屬性
// 返回源資料中對應的欄位
// 改變 vm.a 或者 data.a 都會使檢視發生響應
vm.a == data.a // => true
|
- 注意:只有當例項被建立時 data 中存在的屬性才是響應式的。所以之後才使用的屬性一開始它為空或不存在,那麼僅需要設定一些初始值即可。
- 這裡唯一的例外是使用 Object.freeze(),這會阻止修改現有的屬性,也意味著響應系統無法再追蹤變化。
- 除了資料屬性,Vue 例項還暴露了一些有用的例項屬性與方法。它們都有字首 $,以便與使用者定義的屬性區分開來。eg: $el、$data、$watch 等。
例項生命週期鉤子
- 不要在選項屬性或回撥上使用箭頭函式,比如 created: () => console.log(this.a) 或 vm.$watch('a', newValue => this.myMethod())。因為箭頭函式是和父級上下文繫結在一起的,this 不會是如你所預期的 Vue 例項
模板語法
- Vue.js 使用了基於 HTML 的模板語法,允許開發者宣告式地將 DOM 繫結至底層 Vue 例項的資料。也可以不用模板,直接寫渲染 (render) 函式,使用可選的 JSX 語法。
文字
- 使用“Mustache”語法 (雙大括號) 的文字插值
- 通過使用 v-once 指令,你也能執行一次性地插值,當資料改變時,插值處的內容不會更新。
1 |
<span v-once>這個將不會改變: {{ msg }}</span>
|
原始 HTML(不要使用,僅供瞭解)
- 注:你的站點上動態渲染的任意 HTML 可能會非常危險,因為它很容易導致 XSS 攻擊。請只對可信內容使用 HTML 插值,絕不要對使用者提供的內容使用插值。
特性
- Mustache 語法不能作用在 HTML 特性上,遇到這種情況應該使用 v-bind 指令。
- 在布林特性的情況下,它們的存在即暗示為 true,v-bind 工作起來略有不同,如果 isButtonDisabled 的值是 null、undefined 或 false,則 disabled 特性甚至不會被包含在渲染出來的 <button> 元素中。
1 |
<button v-bind:disabled= "isButtonDisabled" >Button</button>
|
使用 JavaScript 表示式
- 對於所有的資料繫結,Vue.js 都提供了完全的 JavaScript 表示式支援。
- 注意:每個繫結都只能包含單個表示式。
1 2 3 4 5 |
<!-- 這是語句,不是表示式 -->
{{ var a = 1 }}
<!-- 流控制也不會生效,請使用三元表示式 -->
{{ if (ok) { return message } }}
|
- 注意:模板表示式都被放在沙盒中,只能訪問全域性變數的一個白名單,如 Math 和 Date 。你不應該在模板表示式中試圖訪問使用者定義的全域性變數。
引數
- 一些指令能夠接收一個“引數”,在指令名稱之後以冒號表示。eg:v-bind 與 v-on
修飾符
- 修飾符 (Modifiers) 是以半形句號 . 指明的特殊字尾,用於指出一個指令應該以特殊方式繫結。
1 |
<form v-on:submit.prevent= "onSubmit" >...</form>
|
縮寫
- v-bind (:) 與 v-on (@)
計算屬性和偵聽器
計算屬性
- 在模板中放入太多的邏輯會讓模板過重且難以維護,所以,對於任何複雜邏輯,你都應當使用計算屬性。
1 2 3 |
<div id= "example" >
{{ message.split( '' ).reverse().join( '' ) }}
</div>
|
計算屬性快取 VS 方法(快取)
- 計算屬性是基於它們的依賴進行快取的。計算屬性只有在它的相關依賴發生改變時才會重新求值。這就意味著只要 message 還沒有發生改變,多次訪問 reversedMessage 計算屬性會立即返回之前的計算結果,而不必再次執行函式。
- 每當觸發重新渲染時,呼叫方法將總會再次執行函式。
計算屬性 VS 偵聽屬性
- 不要濫用 watch,通常更好的做法是使用計算屬性而不是命令式的 watch 回撥。
計算屬性的 setter
- 計算屬性預設只有 getter ,不過在需要時你也可以提供一個 setter :
// 現在再執行 vm.fullName = 'John Doe' 時,setter 會被呼叫,vm.firstName // 和 vm.lastName 也會相應地被更新。 computed: { fullName: { // getter get: function () { return this.firstName + ' ' + this.lastName }, // setter set: function (newValue) { var names = newValue.split(' ') this.firstName = names[0] this.lastName = names[names.length - 1] } } } // ...
偵聽器
- 當需要在資料變化時執行非同步或開銷較大的操作時。(比如 watch 選項允許執行非同步操作)
class 繫結
- 字串拼接麻煩且易錯,在將 v-bind 用於 class 和 style 時,Vue.js 做了專門的增強。表示式結果的型別除了字串之外,還可以是物件或陣列。
物件語法
- 注意:v-bind:class 指令也可以與普通的 class 屬性共存
// 物件模式 <div v-bind:class="{ active: isActive, 'text-danger': hasError }"></div> // 放到 data 屬性中 <div v-bind:class="classObject"></div> // 繫結一個返回物件的計算屬性
陣列語法
<div v-bind:class="[activeClass, errorClass]"></div> <div v-bind:class="[isActive ? activeClass : '', errorClass]"></div> // 在陣列語法中也可使用物件語法 <div v-bind:class="[{ active: isActive }, errorClass]"></div> data: { activeClass: 'active', errorClass: 'text-danger', isActive: true }
用在元件上
- 當在一個自定義元件上使用 class 屬性時,這些類將被新增到該元件的根元素上面。這個元素上已經存在的類不會被覆蓋。對於帶資料繫結 class 也同樣適用。
style 繫結
物件語法
- CSS 屬性名可以用駝峰式 (camelCase) 或短橫線分隔 (kebab-case,記得用單引號括起來) 來命名:
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div> // 直接繫結一個樣式物件更好 <div v-bind:style="styleObject"></div> // 物件語法常常結合返回物件的計算屬性使用
陣列語法
- v-bind:style 的陣列語法可以將多個樣式物件應用到同一個元素上
<div v-bind:style="[baseStyles, overridingStyles]"></div>
自動新增字首
- 當 v-bind:style 使用需要新增瀏覽器引擎字首的 CSS 屬性時,如 transform,Vue.js 會自動偵測並新增相應的字首。
多重值
- 從 2.3.0 起你可以為 style 繫結中的屬性提供一個包含多個值的陣列,常用於提供多個帶字首的值
<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>
條件渲染
v-if
- 在 <template> 元素上使用 v-if 條件渲染分組
- v-else
- 使用 v-else 指令來表示 v-if 的“else 塊”
- v-else 元素必須緊跟在帶 v-if 或者 v-else-if 的元素的後面,否則它將不會被識別。
- v-else-if
- 類似於 v-else,v-else-if 也必須緊跟在帶 v-if 或者 v-else-if 的元素之後。
- 用 key 管理可複用的元素
- Vue 會盡可能高效地渲染元素,通常會複用已有元素而不是從頭開始渲染。
- Vue 提供了一種方式來表達“這兩個元素是完全獨立的,不要複用它們”。只需新增一個具有唯一值的 key 屬性
v-show
- v-show 的元素始終會被渲染並保留在 DOM 中。v-show 只是簡單地切換元素的 CSS 屬性 display。
v-if VS v-show
-
v-if 是“真正”的條件渲染,因為它會確保在切換過程中條件塊內的事件監聽器和子元件適當地被銷燬和重建。
-
v-if 也是惰性的:如果在初始渲染時條件為假,則什麼也不做——直到條件第一次變為真時,才會開始渲染條件塊。
-
相比之下,v-show 就簡單得多——不管初始條件是什麼,元素總是會被渲染,並且只是簡單地基於 CSS 進行切換。
-
一般來說,v-if 有更高的切換開銷,而 v-show 有更高的初始渲染開銷。因此,如果需要非常頻繁地切換,則使用 v-show 較好;如果在執行時條件很少改變,則使用 v-if 較好。
v-if 與 v-for 一起使用
- 當 v-if 與 v-for 一起使用時,v-for 具有比 v-if 更高的優先順序。
列表渲染
用 v-for 把一個數組對應為一組元素
- v-for 指令需要使用 item in items 形式的特殊語法
- 在 v-for 塊中,我們擁有對父作用域屬性的完全訪問許可權。v-for 還支援一個可選的第二個引數為當前項的索引。
- 也可以用 of 替代 in 作為分隔符,因為它是最接近 JavaScript 迭代器的語法
一個物件的 v-for
- 用 v-for 通過一個物件的屬性來迭代。
<ul id="v-for-object" class="demo"> <li v-for="value in object"> {{ value }} </li> </ul> // 第二個引數為鍵名,第三個引數為索引 <div v-for="(value, key, index) in object"> {{ index }}: {{ key }}: {{ value }} </div> new Vue({ el: '#v-for-object', data: { object: { firstName: 'John', lastName: 'Doe', age: 30 } } })
- 注意:在遍歷物件時,是按 Object.keys() 的結果遍歷,但是不能保證它的結果在不同的 JavaScript 引擎下是一致的。
key
- 以便 vue 能跟蹤每個節點的身份,從而重用和重新排序現有元素,你需要為每項提供一個唯一 key 屬性。理想的 key 值是每項都有的且唯一的 id。使用 v-bind 繫結動態值。
- 注意:① 建議儘可能在使用 v-for 時提供 key,除非遍歷輸出的 DOM 內容非常簡單,或者是刻意依賴預設行為以獲取效能上的提升。② 是 Vue 識別節點的一個通用機制,並不與 v-for 特別關聯。
陣列更新檢測
- 變異方法:Vue 包含一組觀察陣列的變異方法,所以它們也將會觸發檢視更新。
- push()
- pop()
- shift()
- unshift()
- splice()
- sort()
- reverse()
- 注意:會改變呼叫這些方法的原始陣列
- 替換陣列(非變異方法): 不會改變原始陣列但總是返回一個新陣列,在使用這些方法時可以使用新陣列替換舊陣列。
- concat()
- slice()
- filter()
example1.items = example1.items.filter(function (item) { return item.message.match(/Foo/) })
注意事項
- 由於 JavaScript 的限制,Vue 不能檢測以下變動的陣列:
- 當你利用索引直接設定一個項時,例如:vm.items[indexOfItem] = newValue
- 當你修改陣列的長度時,例如:vm.items.length = newLength
var vm = new Vue({ data: { items: ['a', 'b', 'c'] } }) vm.items[1] = 'x' // 不是響應性的 vm.items.length = 2 // 不是響應性的
- 解決
// Vue.set Vue.set(vm.items, indexOfItem, newValue) // Array.prototype.splice vm.items.splice(indexOfItem, 1, newValue) // 同 Vue.set vm.$set(vm.items, indexOfItem, newValue) // 第二類問題 vm.items.splice(newLength)
物件更改檢測注意事項
- 由於 JavaScript 的限制,Vue 不能檢測物件屬性的新增或刪除
var vm = new Vue({ data: { a: 1 } }) // `vm.a` 現在是響應式的 vm.b = 2 // `vm.b` 不是響應式的
- 對於已經建立的例項,Vue 不能動態新增根級別的響應式屬性。但是,可以使用 Vue.set(object, key, value) 方法向巢狀物件新增響應式屬性。
var vm = new Vue({ data: { userProfile: { name: 'Anika' } } }) Vue.set(vm.userProfile, 'age', 27) // 全域性 Vue.set 的別名 vm.$set(vm.userProfile, 'age', 27)
- 要為已有物件賦予多個新屬性,比如使用 Object.assign() 或 _.extend()。在這種情況下,你應該用兩個物件的屬性建立一個新的物件。想新增新的響應式屬性:
// 不應這樣 Object.assign(vm.userProfile, { age: 27, favoriteColor: 'Vue Green' }) // 應該這樣 vm.userProfile = Object.assign({}, vm.userProfile, { age: 27, favoriteColor: 'Vue Green' })
顯示過濾/排序結果
- 有時,我們想要顯示一個數組的過濾或排序副本,而不實際改變或重置原始資料。在這種情況下,可以建立返回過濾或排序陣列的計算屬性。
<li v-for="n in evenNumbers">{{ n }}</li>
- 在計算屬性不適用的情況下 (例如,在巢狀 v-for 迴圈中) 你可以使用一個 method 方法
<li v-for="n in even(numbers)">{{ n }}</li>
一段取值範圍的 v-for
<li v-for="n in even(numbers)">{{ n }}</li>
v-for on a <template>
- 類似於 v-if,你也可以利用帶有 v-for 的 <template> 渲染多個元素。
一個元件的 v-for
- 在自定義元件裡,你可以像任何普通元素一樣用 v-for 。
- 2.2.0+ 的版本里,當在元件中使用 v-for 時,key 現在是必須的。
- 注意:不自動將 item 注入到元件裡的原因是,這會使得元件與 v-for 的運作緊密耦合。明確元件資料的來源能夠使元件在其他場合重複使用。
- 問題:is="todo-item" 屬性?DOM 模板解析說明
事件處理
內聯處理器中的方法
- 有時也需要在內聯語句處理器中訪問原始的 DOM 事件。可以用特殊變數 $event 把它傳入方法
事件修飾符
- 在事件處理程式中呼叫 event.preventDefault() 或 event.stopPropagation() 是非常常見的需求。為了方法只有純粹的資料邏輯,而不是去處理 DOM 事件細節,,Vue.js 為 v-on 提供了事件修飾符。
- .stop
- .prevent
- .capture
- .self
- .once:不像其它只能對原生的 DOM 事件起作用的修飾符,.once 修飾符還能被用到自定義的元件事件上
- .passive: 滾動事件的預設行為 (即滾動行為) 將會立即觸發,尤其能夠提升移動端的效能。
- 注意:① 使用修飾符時,順序很重要;相應的程式碼會以同樣的順序產生。因此,用 v-on:click.prevent.self 會阻止所有的點選,而 v-on:click.self.prevent 只會阻止對元素自身的點選。② 不要把 .passive 和 .prevent 一起使用,因為 .prevent 將會被忽略,同時瀏覽器可能會向你展示一個警告。請記住,.passive 會告訴瀏覽器你不想阻止事件的預設行為。
<!-- 阻止單擊事件繼續傳播 --> <a v-on:click.stop="doThis"></a> <!-- 提交事件不再過載頁面 --> <form v-on:submit.prevent="onSubmit"></form> <!-- 修飾符可以串聯 --> <a v-on:click.stop.prevent="doThat"></a> <!-- 只有修飾符 --> <form v-on:submit.prevent></form> <!-- 新增事件監聽器時使用事件捕獲模式 --> <!-- 即元素自身觸發的事件先在此處處理,然後才交由內部元素進行處理 --> <div v-on:click.capture="doThis">...</div> <!-- 只當在 event.target 是當前元素自身時觸發處理函式 --> <!-- 即事件不是從內部元素觸發的 --> <div v-on:click.self="doThat">...</div>
按鍵修飾符
- Vue 允許為 v-on 在監聽鍵盤事件時新增按鍵修飾符:
<input v-on:keyup.13="submit"> // 常用鍵的別名 <input v-on:keyup.enter="submit">
- 全部別名 -.enter
- .tab
- .delete (捕獲“刪除”和“退格”鍵)
- .esc
- .space
- .up
- .down
- .left
- .right
- 可以通過全域性 config.keyCodes 物件自定義按鍵修飾符別名:
// 可以使用 `v-on:keyup.f1` Vue.config.keyCodes.f1 = 112
- 自動匹配按鍵修飾符(有問題)
系統修飾鍵
- 可以用如下修飾符來實現僅在按下相應按鍵時才觸發滑鼠或鍵盤事件的監聽器
- .ctrl
- .alt
- .shift
- .meta ( Windows 徽標鍵 或 command 鍵 (⌘))
- 注意:請注意修飾鍵與常規按鍵不同,在和 keyup 事件一起用時,事件觸發時修飾鍵必須處於按下狀態。
- .exact 修飾符
- 允許你控制由精確的系統修飾符組合觸發的事件。
<!-- 即使 Alt 或 Shift 被一同按下時也會觸發 --> <button @click.ctrl="onClick">A</button> <!-- 有且只有 Ctrl 被按下的時候才觸發 --> <button @click.ctrl.exact="onCtrlClick">A</button> <!-- 沒有任何系統修飾符被按下的時候才觸發 --> <button @click.exact="onClick">A</button>
- 滑鼠按鈕修飾符
- .right
- .left
- .middle
- 注:這些修飾符會限制處理函式僅響應特定的滑鼠按鈕。
為什麼在 HTML 中監聽事件
- 所有的 Vue.js 事件處理方法和表示式都嚴格繫結在當前檢視的 ViewModel 上,它不會導致任何維護上的困難。還有其他好處:
- 掃一眼 HTML 模板便能輕鬆定位在 JavaScript 程式碼裡對應的方法。
- 因為你無須在 JavaScript 裡手動繫結事件,你的 ViewModel 程式碼可以是非常純粹的邏輯,和 DOM 完全解耦,更易於測試。
- 當一個 ViewModel 被銷燬時,所有的事件處理器都會自動被刪除。你無須擔心如何自己清理它們。
表單輸入繫結
- v-model 會忽略所有表單元素的 value、checked、selected 特性的初始值而總是將 Vue 例項的資料作為資料來源。你應該通過 JavaScript 在元件的 data 選項中宣告初始值。
基礎用法
- 文字 input
- 多行文字 textarea
- 複選框 checkbox
- 單選按鈕 radio
- 選擇框 select
值繫結
- 複選鈕
- 單選按鈕
- 選擇框的選項
<!-- 當選中時,`picked` 為字串 "a" --> <input type="radio" v-model="picked" value="a"> <!-- `toggle` 為 true 或 false --> <input type="checkbox" v-model="toggle"> <!-- 當選中第一個選項時,`selected` 為字串 "abc" --> <select v-model="selected"> <option value="abc">ABC</option> </select>
- 注意:有時我們可能想把值繫結到 Vue 例項的一個動態屬性上,這時可以用 v-bind 實現,並且這個屬性的值可以不是字串。
修飾符
- .lazy:在預設情況下,v-model 在每次 input 事件觸發後將輸入框的值與資料進行同步 (除了上述輸入法組合文字時)。你可以新增 lazy 修飾符,從而轉變為使用 change 事件進行同步:
<!-- 在“change”時而非“input”時更新 --> <input v-model.lazy="msg" >
- .number:如果想自動將使用者的輸入值轉為數值型別,可以給 v-model 新增 number 修飾符
<input v-model.number="age" type="number">
- .trim:如果要自動過濾使用者輸入的首尾空白字元,可以給 v-model 新增 trim 修飾符
<input v-model.trim="msg">
在元件上使用 v-model (之後自定義輸入元件-組建基礎中)
元件基礎
基本示例
元件的複用
- 每個元件都會各自獨立維護它的 狀態。因為你每用一次元件,就會有一個它的新例項被建立
<div id="components-demo"> <button-counter></button-counter> <button-counter></button-counter> <button-counter></button-counter> </div>
- data 必須是一個函式: 一個元件的 data 選項必須是一個函式,因此每個例項可以維護一份被返回物件的獨立的拷貝。否則的話可能會影響其他所有示例。底層實現是什麼?
元件的組織
- 有兩種元件的註冊型別:全域性註冊和區域性註冊。至此,我們的元件都只是通過 Vue.component 全域性註冊的:
Vue.component('my-component-name', { // ... options ... })
- 全域性註冊的元件可以用在其被註冊之後的任何 (通過 new Vue) 新建立的 Vue 根例項,也包括其元件樹中的所有子元件的模板中。
通過 Prop 向子元件傳遞資料
- 可以使用 v-bind 來動態傳遞 prop。
單個根元素
- 每個元件必須只有一個根元素
通過事件向父級元件傳送訊息
-
呼叫內建的$emit方法並傳入事件的名字,來向父級元件觸發一個事件
-
使用事件丟擲一個值
<button v-on:click="$emit('enlarge-text', 0.1)"> Enlarge text </button> <blog-post ... v-on:enlarge-text="postFontSize += $event" ></blog-post>
- 在元件上使用 v-model
<input v-model="searchText"> // 等價於 <input v-bind:value="searchText" v-on:input="searchText = $event.target.value" > // 用在元件上 <custom-input v-bind:value="searchText" v-on:input="searchText = $event" ></custom-input> // 將其 value 特性繫結到一個名叫 value 的 prop 上 // 在其 input 事件被觸發時,將新的值通過自定義的 input 事件丟擲 Vue.component('custom-input', { props: ['value'], template: ` <input v-bind:value="value" v-on:input="$emit('input', $event.target.value)" > ` })
通過插槽分發內容<slot>
<alert-box> Something bad happened. </alert-box> Vue.component('alert-box', { template: ` <div class="demo-alert-box"> <strong>Error!</strong> <slot></slot> </div> ` })
動態元件
- 通過 Vue 的 <component> 元素加一個特殊的 is 特性來實現
解析 DOM 模板時的注意事項
- 有些 HTML 元素,諸如ul、ol、table和select,對於哪些元素可以出現在其內部是有嚴格限制的。而有些元素,諸如 li、tr 和option,只能出現在其它某些特定的元素內部。
// 這個自定義元件 <blog-post-row> 會被作為無效的內容提升到外部,並導致最終渲染結果出錯。 <table> <blog-post-row></blog-post-row> </table> // 利用 is 特性 <table> <tr is="blog-post-row"></tr> </table>
- 注意:需要注意的是如果我們從以下來源使用模板的話,這條限制是不存在的:
- 字串 (例如:template: '...')
- 單檔案元件 (.vue) <script type="text/x-template">