整理 Vue.js 筆記
v-model 資料綁定
基本上 Vue 的資料綁定,就是直接用 v-model
加上 data 裡的變數名稱,即可完成綁定。
範例
1 | <div id="app"> |
不過唯一要注意的事情,就是綁定的是什麼元素,如:input
、Checkbox
、radio
、select
..等,
我們需要依照不同的狀況綁定不同的資料格式,如下
1 | var app = new Vue({ |
由上例來看,我們需特別注意的是 HTML-checkbox 標籤
單選
的 checkbox,資料儲放的格式需為boolean
型態。多選
的 checkbox,資料儲放的格式需為array
型態。
官方:表單控件綁定
表單元素绑定 value
有時我們使用 radio
、checkbox
、selected
時,
要達成呈現文字及儲存的資料要有所不一樣的話,
我們就可以透過value
來設定,
另外若需要綁定 value
到 Vue 實例的一個動態屬性上,這時可以用v-bind
實現。
範例
1 | <!-- 當選中時,`picked` 為字符串"a" --> |
select 使用 v-for 渲染
主要重點在於賦予option
的 value 時,記得要加:
符號,如下例
1 | <select name="" id="" v-model="selected2"> |
官方:值绑定
v-model 修飾符
1 | <!-- lazy 就像 onchange 一樣,離開欄位才會觸發 --> |
官方:修飾符
複選框
主要是在 select
的標籤上,新增multiple
這個屬性即可。
1 | <select name="" id="" multiple v-model="multiSelected"> |
連結:JSBin
呈現文字的方式
簡單來說有下列幾種
- 直接輸出:
{ {message;}}
- 綁定在
HTML Tag標籤
上- 純文字:
v-text
- HTML:
v-html
- 純文字:
範例
1 | <div id="app"> |
v-bind 標籤屬性綁定
經過上面的解說與示範,
我們如何要將資料綁定在 HTML Tag標籤
HTML Tag標籤
HTML Tag標籤
上的話,
可能就很直接的使用下列的方式
1 | <img src="{{ imgSrc }}" alt=""> |
在 src 的地方,直接使用 { { imgSrc }}
就以為可以自動綁定好了。
錯誤範例
1 | <div id="app"> |
But…人生總是不如意,上例案例並無法將圖片網址正確的綁上 img 標籤
上,
正確的使用方式,應該要使用 v-bind
這功能,如下例
<img v-bind:src="imgSrc" alt="">
所以要在 img 標籤
針對 Attributes
做綁定的話,就要加上 v-bind
正確範例
1 | <div id="app"> |
圖片連結
當我們要讀取本地端的圖片時,如果直接輸入路徑時,會造成它無法正常顯示,
主要是因為 vue-loader 的編譯規則 所導致,我們可以改寫用require
方式,來取得本地端圖片的位置。
1 | <!-- 失效 --> |
How to bind img src to data in Vue > vue tempalte 中的 img 标签无法打包出来 > vue 踩坑系列——backgroundImage 路径问题
有無冒號的區別
有冒號
有冒號為 v-bind 的縮寫,所以有冒號時,這時資料是綁定一個「變數」,
所以此時 hello
就代表綁定 Vue Data 裡的 hello
變數。
1 | <!-- 有冒號 --> |
有時不一定是變數,直接寫運算式也行
1 | // 有冒號 |
無冒號
無冒號代表無綁定,所以此時 message
變數的值,就是一個 hello
的字串。
1 | <!-- 無冒號 --> |
v-for 重覆渲染
在呈現多筆資料時,可使用 v-for
功能,來實現重覆渲染畫面,
一般使用時,可使用 v-for="item in list"
,
但若有需要資料的索引值的話,可改寫為 v-for="(item, index) in list"
,
這樣就可以利用 index
取得目前的索引值。
範例
1 | <div id="app"> |
v-for :key 的用途
由於 Vue.js 在效能考量,在預設的狀況下,Vue.js 會儘量重覆使用已渲染好的元素。
若不設定 key 值,不會重新渲染元素,只會 部份更新 部份更新 部份更新。
無 key 範例
在 HTML 的綁定 li
的部份,後面並無加 :key
的設定,
然後我們在 li
裡的 input
欄位裡,分別打上 1111、2222、3333 的值後,
這時我們點擊按鈕(反轉陣列)時,你會看到資料有二種變化的情況,
{ { index }} - { { item.id }} { { item.name }}
的值,有正常的反轉變化。input
欄位,卻沒有跟著變化。
1 | <div id="app"> |
無 Key 範例:JSBin
綁定 key 範例
下面範例為有使用 :key
,可以在範例看到資料變化時,整個li
裡面的元素,也會跟著一起變化。
1 | <div id="app"> |
綁定 Key 範例:JSBin
1. 有使用
v-for
的話,建議都要配合 key
。2.
key
最好是都是 唯一值 uniqueKey。3.
key
的值可以自訂,只要不一樣即可。v-if 判斷式
由上例延伸,如果想要在某種條件下,不顯示資料的話,
我們就可以加上 v-if
來加上判斷式,
範例
條件為 年齡小於 25 歲不顯示
1 | <ul> |
不過良好的撰寫習慣的話,盡量避免 v-for配 v-if一起使用,
主要原因是會 耗效能,可以利用 computed 計算,
先過濾掉不要的的物件後,再渲染出結果。
避免 v-if 與 v-for 一起使用
最主要的原因是「效能」的考量。
情境說明:
假設我有 100 個 User(90 男、10 女),此時我只想顯示 10 女 的資料就好。
1 | <ul> |
不過上例的程式的執行,會跑 100 次 forloop 及判斷,
所以當有更新資料時,又會重新跑 100 次,這樣效能上就顯得不優。
這時我們就可以使用 computed
先將資料過濾好後,
再丟給 v-for
去渲染畫面,這樣就可以優化效能的部份。
v-if 與 v-show
- v-if:若為
flase
時,DOM 元素是不會被渲染出來,會整個消失的。 - v-show:若為
flase
時,則是使用disply:none
將元素隱藏。
v-on 事件綁定
以往我們要將某個 DOM 元素綁上事件的話,會使用 EventTarget.addEventListener()
來賦予功能,
而在 Vue
要綁上事件監聽的話,實現步驟如下
- 在 DOM 元素,宣告綁定事件
- 在 Vue 的 methods 裡,建立函式
範例
1 | <div id="app"> |
HTML 各種事件屬性:HTML Event Attributes
v-on 進階指令(修飾符)
下列介紹一些 修飾符
的使用,可協助縮短我們的程式碼。
事件修飾符
最常見的例子,就是 event.preventDefault()
或 event.stopPropagation()
,
有時我們在監聽事件時,會需要取消一些 HTML 標籤 預設的行為或是停止事件冒泡,
一般情況下,我們會像下列範例這樣撰寫
1 | reverseText(event) { |
不過在 Vue 裡,有提供我們另外的寫法,如下
說明
1 | <!--阻止單擊事件繼續傳播--> |
官方說明:事件修飾符
範例
stop - 調用 event.stopPropagation(),停止事件冒泡 (Event Bubbling)行為。
1
2
3
4
5<h6>將此範例加上 stopPropagation (防止向外尋找)</h6>
<div @click="trigger('div')">
<!-- 新增 event.stopPropagation() -->
<span @click.stop="trigger('box')"></span>
</div>stop 範例:JSBin
capture - 將監聽事件模式,更改為使用 事件捕獲 (Event Capturing) 模式,。
1
2
3
4
5
6<h6 >事件偵聽器時使用 capture 模式 (事件改為由外而內)</h6>
<div @click.capture="trigger('div')">
<span @click.capture="trigger('box')">
<button @click.capture="trigger('button')">按我</button>
</span>
</div>capture 範例:JSBin
self - 只會觸發自己綁定的 DOM 元素,不會有
Event Capturing
和Event Bubbling
,這樣就不用再新增event.stopPropagation()
。1
2
3
4
5
6<h6>事件偵聽器時使用 self 模式 (只會觸發自己範圍內的)</h6>
<div @click.self="trigger('div')">
<span @click.self="trigger('box')">
<button @click.self="trigger('button')">按我</button>
</span>
</div>self 範例:JSBin
once - 只觸發一次回調。
1
2
3
4
5
6<h6>事件偵聽器只觸發一次</h6>
<div @click.once="trigger('div')">
<span @click.once="trigger('box')">
<button @click.once="trigger('button')">按我</button>
</span>
</div>once 範例:JSBin
按鍵修飾符
以往我們在監聽鍵盤的事件時,都是使用 event.keyCode
進行判斷,如下例
1 | function runScript(e) { |
一樣 Vue 也有提供我們另外的寫法,如下
說明
1 | <!-- 只有在 `keyCode` 是 13 时调用 `vm.submit()` --> |
另外也有提供常見的按鍵別名,如:enter
、esc
、tab
…等。
1 | <!-- 同上 --> |
官方說明:按键修飾符
範例
{keyCode | keyAlias} - 只當事件是從特定鍵觸發時才觸發回調。
1
<input type="text" @keyup.13="trigger('按下Enter鍵')">
別名修飾 - .enter, .tab, .delete, .esc, .space, .up, .down, .left, .right
1
<input type="text" @keyup.enter="trigger('按下Enter鍵')">
特殊按鍵,可同時加二個修飾符,達到特殊動作才觸發事件 - .ctrl, .alt, .shift, .meta
1
<input type="text" @keyup.shift.enter="trigger('shift + Enter')">
滑鼠修飾符
- .left - (2.2.0) 只當點擊鼠標左鍵時觸發。
- .right - (2.2.0) 只當點擊鼠標右鍵時觸發。
- .middle - (2.2.0) 只當點擊鼠標中鍵時觸發。
1 | <span class="box" @click.middle="trigger('點擊鼠標-中鍵')"></span> |
v-on & v-bind 縮寫
身為專業的懶人的話,能少寫一個字就絕對不多打一個字,
下列分別介紹 v-on
和 v-bind
的縮寫。
v-on
原先的寫法 v-on:
改為 @
代表,參考下例。
1 | // 原始寫法 |
v-bind
原先的寫法 v-bind:
只留下 :
代表即可,參考下例。
1 | // 原始寫法 |
v-class 動態切換 ClassName
有時我們會針對 DOM 元素,動態的新增移除 CSS 屬性,而在 Vue 裡,我們實現的方式,
除了使用 v-bind:
綁定資料外,也需要在後面新增條件式的判斷,
這樣我們才能達到動態切換 ClassName,如下例所示
使用方式
1 | <!-- 額外新增判斷式 --> |
物件寫法
方法 1:直接寫
直接使用{ '屬性名稱': 判斷式 }
寫入,若是有多個的話,可用「逗號」隔開。方法 2:物件
有時超過二個以上的話,會大大降低可讀性, 所以將多個的'屬性名稱': 判斷式
寫在 Vue 的 Data 裡。
1 | <!-- 方法1:直接寫 --> |
程式範例:JSBin
更改 CSS 物件之判斷式
若是 CSS 採用物件寫法的話,不過當要更改判斷式
的值時,要稍微注意一下取值的寫法。
1 | <!-- 方法2:物件 --> |
程式範例:JSBin
陣列寫法
直接利用陣列的方式,將ClassName
寫進Array
裡,記得要是「字串」。
1 | <!-- 陣列 --> |
程式範例:JSBin
動態更新 CSS 陣列寫法
可透過 checkbox 的特性,可動態新增移除ClassName
是否寫進 Array
1 | <!-- 陣列 --> |
程式範例:JSBin
綁定行內樣式
:style="{ 樣式屬性 : '樣式的值' }
可以直接利用 :style
的寫法,將 CSS 屬性寫在 HTML 上面,
不過有一點要 注意 注意 再 注意
若樣式屬性有「-」字號的話,改寫為「駝峰式命名」,將「-」去除而接著後面第一個字母改大寫。
駝峰式命名:
box-shadow => boxShadow ( S 變大寫)
margin-top => marginTop ( T 變大寫)
1 | <!-- 直接寫入HTML裡 --> |
程式範例:JSBin
Computed 跟 method 差異點
因為這二者做的事情都好像可以完成,所以有時會不知該選Computed
或 Methods
?
比較表
method | computed | |
---|---|---|
使用方式 | 可傳參數 | 類變數 |
執行方式 | 每次呼叫,每次執行 | 快取 |
適用選擇 | 功能面、動作操作 | 資料格式、內容處理 |
使用方式 說明
二者的呼叫方式不太一樣
method
method呼叫方式 1
2
3
4// 方式1
this.fun();
// 方式2
this.fun('參數1', '參數2');computed
computed 屬性默認只設置 getter 函數,不過在需要時,還可以提供 setter 函數,如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16// ...
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]
}
}
}
// ...所以 computed 的呼叫方式,就是使用 getter 或 setter 二種用法,
而這樣的用法,就很像我們一般在使用JS 的變數一樣,不是取值,就是覆寫值。1
2
3
4// getter
getFullName = this.fullName;
// setter
this.fullName = '改變的值';
執行方式 說明
method
每次呼叫,每次執行,所以若呼叫 10 次,就會執行 10 次。
computed
與 method 不同的點,若是當資料沒有變動時,就不會重新計算,
所以就算呼叫 10 次,資料若沒變的話,就直接回傳 cache 給你。
如何選擇
在選擇二者時,請優先考慮 computed,若 computed 可以使用且滿足你的需求,就用 computed 來執行,
另外下列簡易區分方式
computed
若是性質比較偏向 data 的 資料格式 或 內容處理 的話,可選用
computed
。method
可以想成我們在用 JS 的
addeventlistener
,通常在某些情況下,我們會呼叫函式,幫我們處理相關事宜,如:click、mouseover…等。
Computed 跟 method 觸發時機
這裡我們從 觸發時機 來比較二者差異,這樣下次要選擇時,就可以選擇較適當作法。
Computed:其相依的
data
改變時,computed 才會重新計算。Methods:只要
data
有改變時,不管 有無相依 ,都會重新計算。
結論
- 需要每次更新,就用
Methods
- 在意效能,就用
Computed
範例
可以點擊範例裡的count
按鈕,然後看 console 顯示的訊息,
你就會知道Computed
或 Methods
觸發時機有什麼不一樣了。
1 | <div id="app"> |
範例程式:JSBin
Computed 與 Watch 的差異
觸發時機
Computed:當 methods 裡,有包含到 Vue Data 的變數的話,當變數值更新時,就會觸發 Computed 裡 method 的呼叫。
Watch:針對 Vue Data 裡,特別指定監聽某一個變數,當此變數更新時,就會觸發 Watch 裡 method 的呼叫。
說明
在一般情況下,我們通常會直接使用Computed
去監聽變數,不用Watch
是因為還需要一個個變數去綁定,
不過有時如果遇到要處理非同步或複雜的計算時,就可以考慮使用Watch
來處理事情。
Watch 範例
我想要「使用 trigger 來觸發旋轉 box、並在三秒後改變回來」,所以我特別指定監聽 trigger
這個變數是否有變更。
Watch 範例:JSBin
template 小技巧
以往我們要針對多個DOM 新增v-if
判斷時,需要一個一個新增,如下例
1 | <div v-if="showTemplate"> |
若是多個 DOM 的條件都為一樣的話,此時我們可以使用template
標籤,
將整個區塊包起來,然後在template
上,新增判斷式即可。
1 | <template v-if="showTemplate"> |
DOM 解析注意
某些 HTML 元素限制內部的元素只能是某幾種 tag,
如:table、select、ul / ol 等,若是使用 Component 時就必須特別小心。
- table => thead、tbody => tr => td
- select => option
- ul、ol => li
失效範例
雖然 select
底下的 Component my-option
的裡面是使用option
看似合理,
不過最主要是一開始 HTML 在渲染時,看到select
底下的是 my-option
標籤,
因為 HTML 認為這在select
底下是無效的標籤,所以就將my-option
標籤移除,
也因為這樣 Vue 要在解析 Component 時,已經不見了。
1 | <div id="app"> |
1 | Vue.component('my-option', { |
正確方法
若要可以正常渲染的話,就需將 Component 寫法移至 Vue 的 template 裡面,
透過這樣的方式,讓 Vue 來幫我們解析及渲染畫面。
1 | <div id="app"></div> |
1 | Vue.component('my-option', { |
資料更新的機制
一般情況下,我們要更新 Vue Data 裡面的值時,通常直接指定變數後,就賦予值給它,
不過若是要更新「物件 和 陣列」時,就要注意什麼情況會更新,什麼情況不會被更新,
下列範例主要是看 PJ 大文章說明(為什麼畫面沒有隨資料更新 - Vue 響應式原理(Reactivity)),
將一些關鍵點紀錄下來
物件更新
若是物件要更新某個屬性值的話,有下列方式
1 | const postVm = new Vue({ |
陣列更新
若針對陣列時,只有下列幾個 methods,才會觸發 Vue 去重新渲染畫面。
陣列函式:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
1 | const postsVm = new Vue({ |
Vue 生命週期
建立或移除 DOM 元素時,所經歷的事件
- beforeCreate:實體初始化。
- Created:實體建立完成。資料
$data
已可取得,但$el
屬性還未被建立。
———–↓↓↓————– - beforeMount:執行元素掛載之前。
- mounted:元素已掛載,
$el
被建立。
———–↓↓↓————– - beforeUpdate:當資料變化時被呼叫,還不會描繪 View。
- updated:DOM 的更新已經完成,View 被顯示在畫面上。
———–↓↓↓————– - activated:如果有設定
keep-alive
,這個掛鉤會被呼叫。 - deactivated:停用
keep-alive
時被呼叫。
或 - beforeDestroy:實體還可使用。
- destroyed:實體銷毀。所有綁定被解除、事件偵聽被移除、子實體也被銷毀。
範例
1 | beforeCreate() { |