vue基礎(學習官方文檔)
基礎
介紹
是什麽
- 是一套用於構建用戶界面的漸進式框架
聲明式渲染
<div id="app">{{ message }}</div> var app = new Vue({ el: ‘#app‘, data: { message: ‘Hello Vue!‘ } })
vue 實例
var vm = new Vue({ // 選項 })
- 一個 Vue 應用由一個通過 new Vue 創建的根 Vue 實例,以及可選的嵌套的、可復用的組件樹組成。
- 所有的 Vue 組件都是 Vue 實例,並且接受相同的選項對象 (一些根實例特有的選項除外)。
數據與方法
// 我們的數據對象 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 指令,你也能執行一次性地插值,當數據改變時,插值處的內容不會更新。
<span v-once>這個將不會改變: {{ msg }}</span>
原始 HTML(不要使用,僅供了解)
- 註:你的站點上動態渲染的任意 HTML 可能會非常危險,因為它很容易導致 XSS 攻擊。請只對可信內容使用 HTML 插值,絕不要對用戶提供的內容使用插值。
特性
- Mustache 語法不能作用在 HTML 特性上,遇到這種情況應該使用 v-bind 指令。
- 在布爾特性的情況下,它們的存在即暗示為 true,v-bind 工作起來略有不同,如果 isButtonDisabled 的值是 null、undefined 或 false,則 disabled 特性甚至不會被包含在渲染出來的 <button> 元素中。
<button v-bind:disabled="isButtonDisabled">Button</button>
使用 JavaScript 表達式
- 對於所有的數據綁定,Vue.js 都提供了完全的 JavaScript 表達式支持。
- 註意:每個綁定都只能包含單個表達式。
<!-- 這是語句,不是表達式 --> {{ var a = 1 }} <!-- 流控制也不會生效,請使用三元表達式 --> {{ if (ok) { return message } }}
- 註意:模板表達式都被放在沙盒中,只能訪問全局變量的一個白名單,如 Math 和 Date 。你不應該在模板表達式中試圖訪問用戶定義的全局變量。
參數
- 一些指令能夠接收一個“參數”,在指令名稱之後以冒號表示。eg:v-bind 與 v-on
修飾符
- 修飾符 (Modifiers) 是以半角句號 . 指明的特殊後綴,用於指出一個指令應該以特殊方式綁定。
<form v-on:submit.prevent="onSubmit">...</form>
縮寫
- v-bind (:) 與 v-on (@)
計算屬性和偵聽器
計算屬性
- 在模板中放入太多的邏輯會讓模板過重且難以維護,所以,對於任何復雜邏輯,你都應當使用計算屬性。
<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">
vue基礎(學習官方文檔)