Vue.js 組件非常類似於自定義元素。有幾個關鍵的不同:
①Vue.js 組件不需要任何補丁,並且在所有支持的瀏覽器(IE9 及更高版本)之下表現一致。Vue.js 組件也可以放在原生自定義元素之內
②Vue.js 組件提供了原生自定義元素所不具備的一些重要功能,比如組件間的數據流,自定義事件系統,以及動態的、帶特效的組件替換
通過構造函數Vue創建實例化Vue對象
var vm = new Vue({
// 選項
})
或者
擴展 Vue 構造器
var MyComponent = Vue.extend({
// 擴展選項
})
// 所有的 `MyComponent` 實例都將以預定義的擴展選項被創建
var myComponentInstance = new MyComponent()
在實例化 Vue 時,需要傳入一個選項對象,它可以包含數據、模板、掛載元素、方法、生命週期鉤子等選項。
所有的 Vue.js 組件其實都是被擴展的 Vue 實例 -->因爲擴展出來的Vue實例都會被繼承然後可以創建組件
只有這些被代理的屬性(data對象中的屬性)是響應的
注意,不要在實例屬性或者回調函數中(如vm.$watch('a', newVal => this.myMethod()))使用箭頭函數。因爲箭頭函數綁定父上下文,所以 this 不會像預想的一樣是 Vue 實例,而是 this.myMethod 未被定義。
在實例生命週期的不同階段調用,如 mounted、 updated、destroyed、created 。鉤子的 this 指向調用它的 Vue 實例
Vue.js 使用了基於 HTML 的模版語法,允許開發者聲明式地將 DOM 綁定至底層 Vue 實例的數據。在底層的實現上, Vue 將模板編譯成虛擬 DOM 渲染函數。結合響應系統,在應用狀態改變時, Vue 能夠智能地計算出重新渲染組件的最小代價並應用到 DOM 操作上。
使用 v-once 指令,你也能執行一次性地插值,當數據改變時,插值處的內容不會更新。當然要注意其他數據是否綁定在上面,要是由數據也會影響的。
雙大括號會將數據解釋爲純文本,而非 HTML 。爲了輸出真正的 HTML ,你需要使用v-html 指令
javascript表達式被{{}}包起來會在所屬 Vue 實例的數據作用域下作爲 JavaScript 被解析。有個限制就是,每個綁定都只能包含單個表達式
指令(Directives)是帶有 v- 前綴的特殊屬性。指令屬性的值預期是單一 JavaScript 表達式。指令的職責就是當其表達式的值改變時相應地將某些行爲應用到 DOM 上。 v-if 指令將根據表達式 seen 的值的真假來移除/插入 <p> 元素。<p v-if="seen">Now you see me</p>
v-bind 縮寫 <a v-bind:href="url"></a> <==> <a :href="url"></a>
v-on 縮寫 <a v-on:click="doSomething"></a> <==> <a @click="doSomething"></a>
計算屬性(定義一個屬性來獲取某個值)和method中定義相同函數名得到效果一樣。不同的是計算屬性是基於它的依賴緩存。計算屬性只有在它的相關依賴發生改變時纔會重新取值。相比而言,每當重新渲染的時候,method 調用總會執行函數。
Vue.js 提供了一個方法 $watch ,它用於觀察 Vue 實例上的數據變動。
在v-bind 用於 class 和 style 時, Vue.js 專門增強了它。表達式的結果類型除了字符串之外,還可以是對象或數組。
v-if 是一個指令,只能控制一組元素。那麼要控制多組呢?把一個 <template> 元素當做包裝元素,最終的渲染結果不會包含該元素
v-else 元素必須緊跟在 v-if 或 v-show 元素的後面——否則它不能被識別。
v-show與v-if大體一樣,不同的是有 v-show 的元素會始終渲染並保持在 DOM 中。v-show 是簡單的切換元素的 CSS 屬性 display 。注意 v-show 不支持 <template> 語法。
v-if vs. v-show探討
v-if 是真實的條件渲染,因爲它會確保條件塊在切換當中適當地銷燬與重建條件塊內的事件監聽器和子組件。
v-if 也是惰性的:如果在初始渲染時條件爲假,則什麼也不做——在條件第一次變爲真時纔開始局部編譯(編譯會被緩存起來)。
相比之下, v-show 簡單得多——元素始終被編譯並保留,只是簡單地基於 CSS 切換。
一般來說, v-if 有更高的切換消耗而 v-show 有更高的初始渲染消耗。因此,如果需要頻繁切換使用 v-show 較好,如果在運行時條件不大可能改變則使用 v-if 較好。
用 v-for 指令根據一組數組的選項列表進行渲染。 v-for 指令需要以item in items 形式的特殊語法, items 是源數據數組並且 item 是數組元素迭代的別名。
v-for 指令需要以(item,index) in items 形式的特殊語法, items 是源數據數組並且 item 是數組元素迭代的別名。index指數組的下標
可以用帶有 v-for 的 <template> 標籤來渲染多個元素塊。
自定義組件如果單單靠用 v-for是不能自動傳遞數據到組件裏,因爲組件有自己獨立的作用域。爲了傳遞迭代數據到組件裏,我們要用 props
<my-component v-for="item in items"></my-component>
不自動注入 item 到組件裏的原因是,因爲這使得組件會緊密耦合到 v-for 如何運作。
數組的變異方法
push() 、pop()、 shift()、 unshift() 、splice() 、sort() 、reverse()
有非變異(non-mutating method)方法
filter(), concat(), slice()
數組的變異方法會改變被這些方法調用的原始數組。
非變異(non-mutating method)方法這些不會改變原始數組,但總是返回一個新數組
注意事項
由於 JavaScript 的限制, Vue 不能檢測以下變動的數組(不會觸發響應式的更改數據):
①當你直接設置一個項的索引時,例如: vm.items[indexOfItem] = newValue
②當你修改數組的長度時,例如: vm.items.length = newLength
第一的解決辦法:
// Vue.set(實例對象.數組名,修改的下標,修改的新值)
Vue.set(example1.items, indexOfItem, newValue)
// Array.prototype.splice 實例對象.數組名.splice(修改的下標,1,修改的新值)
example1.items.splice(indexOfItem, 1, newValue)
第二的解決辦法:
example1.items.splice(newLength)
事件處理
在Vue實例中this代表這個Vue實例,event代表原生DOM事件
有時也需要在內聯語句處理器中訪問原生 DOM 事件。可以用特殊變量 $event 把它傳入方法
preventDefault方法是取消事件的默認動作。
在事件處理程序中調用 event.preventDefault() 或 event.stopPropagation() 是非常常見的需求。但更好的方式是:methods 只有純粹的數據邏輯,而不是去處理 DOM 事件細節。-->也就是說methods屬性中處理的是數據邏輯,DOM事件處理的換其他處
事件修飾符
Vue.js 爲 v-on 提供了 事件修飾符。通過由點(.)表示的指令後綴來調用修飾符。有如下:
.stop 、.prevent、 .capture 、.self
<!-- 阻止單擊事件冒泡 -->
<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>
<!-- 只當事件在該元素本身(而不是子元素)觸發時觸發回調 -->
<div v-on:click.self="doThat">...</div>
按鍵修飾符
Vue 允許爲 v-on 在監聽鍵盤事件時添加按鍵修飾符 如:
<!-- 只有在 keyCode 是 13 時調用 vm.submit() -->
<input v-on:keyup.13="submit">
Vue 爲最常用的按鍵提供了別名:
<!-- 同上 -->
<input v-on:keyup.enter="submit">
<!-- 縮寫語法 -->
<input @keyup.enter="submit">
全部的按鍵別名:
enter、 tab 、delete (捕獲 “刪除” 和 “退格” 鍵)、 esc 、space、 up 、down 、left、 right
可以通過全局 config.keyCodes 對象自定義按鍵修飾符別名:// 可以使用 v-on:keyup.f1Vue.config.keyCodes.f1 = 112
爲什麼在 HTML 中監聽事件?
事件監聽的方式違背了關注點分離(separation of concern)傳統理念。不必擔心,因爲所有的 Vue.js 事件處理方法和表達式都嚴格綁定在當前視圖的 ViewModel 上,它不會導致任何維護上的困難。實際上,使用 v-on 有幾個好處:
①掃一眼 HTML 模板便能輕鬆定位在 JavaScript 代碼裏對應的方法。
②因爲你無須在 JavaScript 裏手動綁定事件,你的 ViewModel 代碼可以是非常純粹的邏輯,和 DOM 完全解耦,更易於測試。
③當一個 ViewModel 被銷燬時,所有的事件處理器都會自動被刪除。你無須擔心如何自己清理它們。
表單控件綁定
用 v-model 指令在表單控件元素上創建雙向數據綁定。它會根據控件類型自動選取正確的方法來更新元素。儘管有些神奇,但 v-model 本質上不過是語法糖,它負責監聽用戶的輸入事件以更新數據,並特別處理一些極端的例子。
v-model 並不關心表單控件初始化所生成的值。因爲它會選擇 Vue 實例數據來作爲具體的值。/*我認爲:v-model綁定表單元素所屬類型的默認值*/
<!-- v-model綁定的屬性selected_option在此例子中一開始可以給一個初始值(一般爲option選項的第一項):{number:123},或者給一個null值。每當點擊選項時其綁定(v-bind)的屬性value會傳到父級中的v-model進行雙向綁定達到聯動 -->
<select v-model="selected_option">
<option v-bind:value="{ number: 123 }">123</option>
<option v-bind:value="{ number: 345 }">345</option>
<option v-bind:value="{ number: 678 }">678</option>
</select>
<span>selected_option的值爲{{selected_option}}</span>
表單修飾符
在默認情況下, v-model 在 input 事件中同步輸入框的值與數據
要想在change事件下更新數據則使用v-model.lazy 如
<!-- 在 "change" 而不是 "input" 事件中更新 -->
<input v-model.lazy="msg" >
組件
組件(Component)可以擴展 HTML 元素,封裝可重用的代碼。在較高層面上,組件是自定義元素, Vue.js 的編譯器爲它添加特殊功能。在有些情況下,組件也可以是原生 HTML 元素的形式,以 is 特性擴展。
註冊一個全局組件,你可以使用 Vue.component(tagName, options)。(設置一個全局自定義組件的話,是用Vue創建出所有的實例對象都可以用這個組件來玩) 例如:
Vue.component('my-component', {
// 選項
})
注意:要確保在初始化根實例 之前 註冊了組件
想讓某個實例使用其特有的組件,則使用局部組件
如:
<!-- 僅在父模板id爲app下可用 -->
<div id="app">
<my-component><my-component>
<!-- 父模板會將上面渲染爲<div>A custom component!</div>-->
</div>
<script type="text/javascript">
var Child = { template: '<div>A custom component!</div>'}
var vm=new Vue({
el: '#app',
components: { //<my-component>將只在父模板可用
'my-component': Child
}
})
</script>
DOM 模版解析說明
Vue 只有在瀏覽器解析和標準化 HTML 後才能獲取模版內容。尤其像這些元素 <ul> , <ol>, <table> , <select> 限制了能被它包裹的元素,<option> 只能出現在其它元素內部。
當使用自定義組件和這些受限制的元素會導致一些問題:下面是運行不成功的
<table id="app">
<my-row></my-row>
</table>
<script type="text/javascript">
var Child = { template: '<div>A custom component!</div>'}
var vm=new Vue({
el: '#app',
components: {
'my-row': Child
}
})
</script>
變通的方案是使用特殊的 is 屬性:
<table id="app">
<tr is="my-row"></tr>
</table>
<script type="text/javascript">
var Child = { template: '<div>A custom component!</div>'}
var vm=new Vue({
el: '#app',
components: {
'my-row': Child
}
})
</script>
應當注意,如果您使用來自以下來源之一的字符串模板,這些限制將不適用:
①<script type="text/x-template">
②JavaScript內聯模版字符串
③.vue 組件
因此,有必要的話請使用字符串模版。-->/*指的是template中使用字符串規定的字符串標籤*/
使用組件時,data屬性 必須是函數。否則會提示”[Vue warn]: The "data" option should be a function that returns a per-instance value in component definitions.”
構成組件
通常父子組件會是這樣的關係:組件 A 在它的模版中使用了組件 B 。它們之間必然需要相互通信:父組件要給子組件傳遞數據,子組件需要將它內部發生的事情告知給父組件。然而,在一個良好定義的接口中儘可能將父子組件解耦是很重要的。這保證了每個組件可以在相對隔離的環境中書寫和理解,也大幅提高了組件的可維護性和可重用性。
在 Vue.js 中,父子組件的關係可以總結爲 props down, events up 。父組件通過 props 向下傳遞數據給子組件,子組件通過 events 給父組件發送消息。
組件實例的作用域是孤立的。這意味着不能並且不應該在子組件的模板內直接引用父組件的數據。可以使用 props 把數據傳給子組件。
prop 是父組件用來傳遞數據的一個自定義屬性。子組件需要顯式地用 props 選項 聲明 “prop” /*子組件接收父組件的數據用props屬性*/
prop 是單向綁定的:當父組件的屬性變化時,將傳導給子組件,但是不會反過來。