隨手筆記 Vue 的大小事
前言
此篇為隨手筆記 Vue.js 程式語言,不定時更新,此篇若有錯誤之處還請提點指教。
目前以四個項目,分類與自我釐清語言的最小性與組合性,使日後要建立軟體專案時,可快速應用。
- 基本概念:Vue 專屬特性
- 基本語法:最小化的語言結構及範例
- 複合語法:組合性的語言結構及範例
- 綜合範例:以普遍、實用的應用主題,撰寫組件範例
- 資料來源:由於參考資料眾多,僅附註原參考資料網址
此篇中內容#XX後方第一個 link,為連結外部資源(JSFiddle),可點擊了解程式碼運作及自行修改程式碼;
第二個 link 為連結架設網站,可點擊後自行 console.log 控制及觀看所有 Vue 程式碼範例。
目錄
#0.1 props
#0.2 computed
#0.3 methods
#0.4 watch
#0.5 mounted
#2.0 v-bind
#3.0 v-if
#4.0 v-for
#5.0 v-on
1.基本概念
Vue 專屬特性
每個 Vue 應用都通過 Vue 函數創建一個新的 Vue 實例。
let vm = new Vue({
// 選項物件
})
- 透過 Vue Instance ( Vue 實例 ) 的選項物件加入內容
- 上方建立 vm 的 Vue Instance,為 view model 的簡稱
- view mode 來自設計模型 MVVM - model、view 與 view model
每個 Vue Indtance 在建立的過程中會經歷一些過程,例如,需要設置數據觀察,編譯模板,將實例掛載到 DOM,以及在數據更改時更新 DOM。在 Vue 初始化過程中,它會運行稱為生命週期鉤子 (Instance Liefcycle Hooks) 的函數,讓開發者可以在特定階段添加自己的代碼。
> function 中的 this 指向其最上層的 Vue Instance
>鉤子中的 this 指向調用它的 Vue Instance
2.基本語法
最小化的語言結構及範例
Vue 有本地與全局兩種方式來串聯資料的響應,2.基本語法內以本地方式撰寫,如為全局會另加說明。
2-1.項目
{
el: '#id', // CSS selector 或 HTMLElement 實例
data: {}, // Object 或 Function
props: {}, // Array<string> 或 Object
computed: {}, // { [key: string]: Function | { get: Function, set: Function } }
methods: {}, // { [key: string]: Function }
watch: {}, // { [key: string]: string | Function | Object }
mounted() {} // Function
// ...
}
props
#0.1
prop是你可以在組件上註冊的一些自定義特性。當一個值傳遞給一個prop特性的時候,它就變成了那個那個組件實例的一個屬性。為了確認prop的組件,我們為它取一個標題 [' title ']。
Vue.component('newtest',{
props:['title'],
template:'<h3>{{ title }}</h3>'
})
props:{
title:String, //傳遞值為字串類型
likes:Number, //傳遞值為數值類型
isPublished:Boolean, //傳遞值為布林值
commentIds:array, //傳遞值為陣列
author:Object //傳遞值為物件
}
#0.1.1 透過prop傳遞多筆資料 JSFiddle Web
//建立 vue
<div id="test">
//透過prop名稱為title的屬性傳遞資料
<blog-post title="My journey with Vue"></blog-post>
<blog-post title="Blogging with Vue"></blog-post>
<blog-post title="Why Vue is so fun"></blog-post>
</div>
//建立Vue
let props = new Vue({
el:'#test'
})
//建立組件
Vue.component('blog-post', {
props: ['title'],
template: '<h3>{{ title }}</h3>'
})
0.1.2 data數組內透過prop傳遞多筆資料 JSFiddle Web
<div id="test">
//顯示component
<bt v-for="item in groceryList" :door="item" :key="item.id"></bt>
</div>
// 建立component
Vue.component('bt', {
props: ['door'],
template:
`
<li>{{ door.id }}{{ door.text }}</li>
`
})
var app = new Vue({
el: '#test',
data: {
groceryList: [
{ id: 1, text: '第一顆按鈕' },
{ id: 2, text: '第二顆按鈕' },
{ id: 3, text: '第三顆按鈕' }
]
}
})
computed
#0.2
計算屬性將被混入 Vue 實例中。所有 getter 和 setter 的 this 上下自動地綁定 Vue 實例。
如果你為一個計算屬性使用箭頭函數,則 this 不會指向這個組件的實例,不過仍然可以將其實例作為函數的第一個參數來訪問。
computed:{
aDouble: vm => vm.a *2
}
#0.2.1 讀取與設定計算 JSFiddle Web
data: { a: 1 },
computed: {
// 僅讀取
aDouble: function () {
return this.a * 2
},
// 讀取和設定
aPlus: {
get: function () {
return this.a + 1
},
set: function (v) {
this.a = v - 1
}
}
}
methods
#0.3
watch
#0.4
mounted
#0.5
Vue 最基本的核心就是,一邊綁定位置,一邊寫入數據;如此數據會渲染 DOM 的系統,使數據寫入綁定位置內。
#b1 創建一個Vue實例 JSFiddle Web
{
el:'', // 綁定位置
data: {} // 寫入數據
}
2-2.指令
透過 v-bind 綁定 HTML屬性。由於此指令經常使用,便可利用縮寫符號:來使用達到 v-bind 的運作。
#b2.0 v-bind
v-bind: // 正常寫法
: // 縮寫寫法
- 用法為動態地綁定一個或多個特性,或一個組件prop到表達式。
- 在綁定class或style特性時,支持其他類型的值,如數組或對象。
- 在綁定prop時,prop必須在子組件中聲明。可以用修飾符指定不同綁定類型。
v-bind 綁定 HTML 屬性
#b2.1 鼠標顯示現在時間 JSFiddle Web
元素上 v-bind 綁定 title 元素。
<div id="app">
<!-- 綁定HTML屬性 -->
<span :title="message">
Hover your mouse over me for a few seconds
to see my dynamically bound title!
</span>
</div>
let vmBind = new Vue({
el: '#app',
data: {
// 寫入數據
message: 'You loaded this page on ' + new Date().toLocaleString()
}
})
#b2.2 超連結網址 JSFiddle
元素上 v-bind 綁定 scr 元素
#b2.3 超連結圖片位置 JSFilddle
元素上 v-bind 綁定 href 元素
v-bind 綁定 class
<!-- class 绑定 -->
<div :class="{ red: isRed }"></div>
<div :class="[classA, classB]"></div>
<div :class="[classA, { classB: isB, classC: isC }]">
#b2.4.1 元素內套用 true/false JSFiddle
元素上 v-bind 綁定 class 樣式。
<div id="app">
<!-- 元素內判斷是否顯示class樣式 -->
<p :class="{classActive: true}">元素內套用 true/false</p>
</div>
var vmBind = new Vue({
el: '#app'
})
#b2.4.2 元素內套用 data JSFiddle
元素上 v-bind 綁定 class 樣式。
<div id="app">
<!-- 利用 data -->
<p :class="{classActive: isActive}">元素內套用 data</p>
</div>
var vmBind = new Vue({
el: '#app',
data: {
/* 來判斷 Class 樣式是否顯示 */
isActive: true
}
})
v-bind 綁定 function
#b2.5
v-bind 綁定一個屬性對象
#b2.6
屬性就像是有個包覆在{ }內的名稱與內容,且同時有多組屬性以逗號分隔;{名稱:內容,名稱:內容}
<!-- 绑定一个有属性的對象 -->
<div v-bind="{ id: someProp, 'other-attr': otherProp }"></div>
v-bind prop綁定
#b2.7
*必須在 " my-component " 中聲明
<!-- prop 绑定 -->
<my-component :prop="someThing"></my-component>
v-bind $prop綁定
#b2.8
*通過 $prop 將父組件的 prop 一起傳給子組件
<!-- 將父組件,綁定為屬性,並傳遞給子組件 -->
<child-compontant v-bind="$prop"></child-component>
v-bind XLink綁定
#b2.9
<!-- XLink -->
<svg><a :xlink:special="foo"></a></svg>
v-bind 修飾符 .camel
#b2.A
- .camel 修飾符允許在使用DOM模板時,將 v-bind 屬性名稱駝峰化,例如SVG的 viewBox
- 於 vue-loader / vueify 編譯時,無須使用 .camel。
<svg :view-box.camel="viewBox"></svg>
- v-if、v-else-if、v-else 判斷指令與 Javascript 的判斷式相同。
- v-if會同時與template元素同時使用,將v-if指令寫在此元素上。
- 當v-if與v-for同時使用時,v-for的優先權比v-if更高。
#3.0 v-if
v-if data
#b3.1 v-if 來自data內判斷 JSFiddle Web
<!-- 加入data -->
<p v-if="seen">Now you see me</p>
let vmIf = new Vue({
el: '#app',
data: {
// 設定判斷
seen: true
}
})
v-if true/false
#b3.2 v-if 來自HTML內判斷 JSFiddle Web
<p v-if="true">Now you see me</p>
<p v-if="false">Can't you see me</p>
v-if 判斷條件
#b3.3 v-if 來自HTML內判斷 JSFiddle Web
<div id="app">
<p v-if="type === 'A'">Type is A</p>
<!-- 僅顯示 Type is B 的內容-->
<p v-if="type === 'B'">Type is B</p>
</div>
let vm = new Vue({
el: '#app',
data:{
type:'B'
}
})
v-else 判斷條件
#b3.4 v-else假設判斷不成立時 JSFiddle Web
只有一組判斷條件
<div id="app">
<div v-if="Math.random() > 0.5">
Now you see me
</div>
<div v-else>
Now you don't
</div>
<!-- 當Math.random()內數值大於 0.5 為 true,反之 false-->
</div>
v-else-if 判斷條件
#b3.5 v-else-if假設判斷不成立時,再判斷 JSFiddle Web
寫上 v-if 判斷條件再加上與 v-else 判斷條件,可以視為一組的判斷條件。
<div v-if="type === 'A'">
A
</div>
<div v-else-if="type === 'B'">
B
</div>
<div v-else-if="type === 'C'">
C
</div>
<div v-else>
Not A/B/C
</div>
Key屬性
#b3.6 key屬性 JSFiddle Web
以登入頁面為例,讓使用者輸入帳號與信箱之間,input的內容會間接洗掉保持清空。
<div id="app">
<template v-if="loginType === 'Username'">
<label>Username</label>
<input placeholder="請輸入帳號名稱" key="input-Username">
</template>
<template v-else>
<label>Email</label>
<input placeholder="請輸入信箱" key="input-Email">
</template>
<button @click="bt">轉換</button>
</div>
> v-for= "item in items"
#b4.0 v-for
用 v-for 把一個數組(陣列)對應到一組元素。
#b4.1 v-for 把一數組對應一元素 JSFiddle Web
v-for 指令需要使用 item in items 形式的特殊語法,items 是源數據數組且 item 是數組元素疊代(疊代是重複回饋過程的活動)的別名。針對多組不同一性質的資料作處理。
<ul id="app">
<li v-for="item in items">
{{ item.message }}
</li>
</ul>
let vm = new Vue({
el: '#app',
data:{
items:[
{ message:'Is A'},
{ message:'Is B'}
]
}
})
#b4.2 v-for 選用第二個參數(索引) JSFiddle Web
item in items 的 item 改寫為 (item,index),擁有對父作用域屬性的完全訪問權限。index 可以自動從數字 0 開始計數。
<ul id="app">
<li v-for="(item,index) in items">
{{ message }}:{{ index }}.{{ item.message }}
</li>
</ul>
let vm = new Vue({
el: '#app',
data:{
message:'This is English',
items:[
{ message:'Is A'},
{ message:'Is B'}
]
}
})
#b4.3 v-for 出一個對象(物件) JSFiddle Web
你可以將一個對象,透過 v-for 疊代出資料。針對多組同一性質的資料做處理。
<ul id="app">
<li v-for="item in object">
{{ item }}
</li>
</ul>
let vm = new Vue({
el: '#app',
data:{
object:{
FirstName:'John',
LastName:'Doe',
age:30
}
}
})
#b4.4 v-for 與 key 應用
為了給 Vue 一個提示,以便它追蹤每個節點的身份,從而重用和重新排序現有元素,需要使用每項提供一個唯一 key 屬性。理想的 key 值是每項都有的唯一 id。
<div v-for="item in items" :key="item.id">
<!-- 内容 -->
</div>
>參考 0.1.2 data數組內透過prop傳遞多筆資料
- 透過 v-on 綁定 HTML屬性,寫入事件。由於此指令經常使用,便可利用縮寫符號 @ 來使用達到 v-on 的運作。
- 用在普通元素上時,只能監聽原生 DOM 。用在自定義元素組件上時,也可以監聽子組件觸發的自定義事件。
- 在監聽原生 DOM 事件時,方法以事件為唯一的參數。如果使用內聯語句,語句可以訪問一個 $event 屬性: v-on:click="handle('ok', $event)"。
#b5.0 v-on
v-on: // 正常寫法
@ // 縮寫寫法
v-on function
v-on 綁定自行定義的 function
#b5.1 v-on function
<!-- Function 寫在 Html element 內建立 view -->
<button @click="onClick()">點我!</button>
// Function 寫在 methods 內建立 model
methods: {
onClick() {
console.log('clicked')
this.message = '觸發 onClick()'
}
#b5.1.1 鼠標點擊事件 JSFiddle Web
#b5.1.2 鼠標移入事件 JSFiddle Web
#b5.1.3 鼠標移出事件 JSFiddle Web
#b5.1.4 按鈕送出事件 JSFiddle Web
#b5.1.4.1 停止資料送出 JSFiddle Web
<!-- 防止事件冒泡 -->
<form @submit.stop="onSubmit"></form>
{
onSubmit(e){
// 停止資料送出
e.preventDefault();
}
}
#b5.1.4.2 視窗彈出訊息 JSFiddle Web
<div id="app">
<!-- greet 為下方定義 methods 的一個方法名 -->
<button @click="greet">
按鈕</button>
</div>
<script>
let vmOn = new Vue({
el:'#app',
data:{
name:'Vue.js'
},
methods:{
greet:function(){
alert('Hello' + this.name + '!')
// `event` 是原生 DOM 事件
if(event){
alert(event.target.tagName)
}
}
}
})
</script>
#b5.1.5 鍵盤鍵入事件 JSFiddle Web
>自訂鍵盤符號鍵入事件
>判斷接收鍵盤字符是哪一個
#b5.2 v-on 方法處理器
<button v-on:click="doThis"></button>
#b5.2.1 監聽事件 JSFiddle Web
可以用 v-on 指令監聽 DOM 事件,並在觸發時運行一些 Javascript代碼。
<div id="app">
<button @click="counter += 1">Add 1</button>
<p>此處為目前的數值{{ counter }}</p>
</div>
<script>
let vmOn = new Vue({
el:'#app',
data:{
counter:0
}
})
</script>
#b5.3 v-on 內聯語句
<button v-on:click="doThat('hello', $event)"></button>
#b5.3.1 v-on 內聯處理器 JSFiddle Web
除了直接綁定一個方法,也可以在內聯 Javascript 語句調用方法 :
<div id="app">
<button @click="say('hi')">Say hi</button>
<button @click="say('what')">Say what</button>
</div>
<script>
let vmOn = new Vue({
el:'#app',
methods:{
say:function(message){
alert(message)
}
}
})
</script>
#b5.3.2 v-on 內聯特殊變量 JSFiddle Web
有時也需要在內聯語句處理器中訪問原始的 DOM 事件。可以用特殊變量 $event 把它傳入方法 :
<div id="app">
<button v-on:click="fan('I Say ...', $event)">
Submit
</button>
</div>
<script>
let vmOn = new Vue({
el:'#app',
methods:{
fan:function(message,event){
if (event) event.preventDefault()
alert(message)
}
}
})
</script>
v-on 修飾符
#b5.4 v-on 修飾符
.stop - 調用 event.stopPropagation()。
.prevent - 调用 event.preventDefault()。
.capture - 添加事件診聽器時使用 capture 模式。
.self - 只當事件是從診聽器绑定的元素本身觸發時才觸發回調。
.{keyCode | keyAlias} - 只當事件是從特定鍵觸發時才觸發回調。
.native - 監聽组件根元素的原生事件。
.once - 只觸發一次回調。
.left - (2.2.0) 只當點擊鼠標左键時觸發。
.right - (2.2.0) 只當點擊鼠標右键時觸發。
.middle - (2.2.0) 只當點擊鼠標中键時觸發。
.passive - (2.3.0) 以 { passive: true } 模式添加診聽器
#b5.4.1 停止冒泡
<button @click.stop="doThis"></button>
#b5.4.2.1 阻止默認行為
<button @click.prevent="doThis"></button>
#b5.4.2.2 阻止默認行為,沒有表達式
<form @submit.prevent></form>
#b5.4.3 鍵修飾符,鍵別名
<input @keyup.enter="onEnter">
#b5.4.4 鍵修飾符,鍵代碼
<input @keyup.13="onEnter">
#b5.4.5 點擊回調只會觸發一次
<button v-on:click.once="doThis"></button>
#b5.5 對象語法 (2.4.0+)
<button v-on="{ mousedown: doThis, mouseup: doThat }"></button>
v-on 串聯修飾符號
#b5.5 串聯修飾符號
#b5.5.1 停止默認行為與沒有表達式
<button @click.stop.prevent="doThis"></button>
>延伸,計數事件觸發次數
#b5.6 鼠標按鈕修飾符
這些修飾符會限制處理函數僅響應特定的鼠標按鈕。
v-on 子組件上監聽自定義事件
<my-component @my-event="handleThis"></my-component>
<!-- 內聯語句 -->
<my-component @my-event="handleThis(123,$event)"></my-component>
<!-- 組件中的原生事件 -->
<my-component @click.native="onClick"></my-compontent>
> v-model
2-3.屬性
Object.freeze()
,阻止修改現有的屬性,意味著響應式系統無法再追蹤變化 #c1- #c1 阻止資料響應 link
Vue.filter ( id,[ definition ]) 過濾器
參數:
|
用法: 註冊或獲取全局過濾器。 |
可自訂過濾器,用於一般常見的文件格式。於貨幣、符號與文字格式等。
<!-- 在雙花括號中 -->
{{ message | capitalize }}
<!-- 在 `v-bind` 中 -->
<div v-bind:id="rawId | formatId"></div>
你可以在一組件的選項中定義本地的過濾器:
#c1.0.0
filters: {
capitalize: function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
}
或者在創建 Vue 實例之前全局定義過濾器:
#c1.1.0
Vue.filter('capitalize', function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
})
new Vue({
// ...
})
註冊與取得過濾器:
#c1.2.0
#註冊
Vue.filter('my-filter',function(value){
#返回處理的值
}
#getter 獲取,返回已註冊的過濾器
var myFilter = Vue.filter('my-filter')
https://cn.vuejs.org/v2/guide/computed.html
2-4.創建 組件/指令
> 本地 component
> 全局 component
事件名
#d2.0 事件名
不同於組件和 prop,事件名不存在任何自動化的大小寫轉換。而觸發的事件名需要完全匹配監聽這個事件所使用的名稱。例如:
<my-component v-on:my-event="doSomething"></my-component>
// v-on 中的 my-event 為事件名
事件名命名方式以 kebab-case 的方式命名。
O官方建議使用 :my-code
// 此為 keba-case (短橫線命名)
X不建議使用 :myCode
// 此為 camelCased (駝峰式命名)
參考文章: vue组件中camelCased (駝峰式) 命名與 kebab-case(短橫線命名)
#d2.1 將原生事件綁定到組件
#d2.1.1組件上配合修飾符監聽原生事件
如果想要在一個組件的根元素上直接監聽一個原生事件。這時,你可以使用 v-on 的 .native 修飾符。
<base-input v-on:focus.native="onFocus"></base-input>
#d2.1.2 組件使用在 input 上監聽原生事件 JSFiddle Web
不過以上的方式是使用在 input 元素上,必須使用 Vue 提供的一個 $listeners 屬性,它是一個對象,裡面包括了作用在這個組件上的所有監聽器。例如:
{
focus: function (event) { /*...*/ },
input: function (value) { /*...*/ }
}
有了這個 $listeners 屬性,你就可以配合 v-on="$listeners" 將所有的事件監聽器指向這個組件的某個特定子元素。對於類似 <input> 的你希望它可以配合 v-model 工作的組件來說,這些監聽器創建一個類似下述 inputListeners 的計算屬性通常是非常有用的 。
如此 <base-input> 組件是一個完全透明的包裹器了,也就是說它完全像一個普通 <input> 元素一樣使用:所有跟它相同的特性和監聽的都可以工作。
2-5.生命週期鉤子
...
3.複合語法
複合語法:組合性的語言結構及範例
- #c1 點擊單向切換網址 JSFidlle (v-bind v-on) #b2.2 #b5.1.1
- #c2 點擊雙向切換網址 JSFiddle (methods v-bind v-if v-on) #b0.3 #b2.2 #b3.1 #b5.1.1
- #c3 點擊單向切換圖片 JSFiddle (v-bind v-on) #b2.3 #5.1.1
- #c4 點擊雙向切換圖片 JSFiddle (methods v-bind v-if v-on) #b0.3 #b2.3 #b3.1 #b5.1.1
- #c5 點擊切換單樣式 JSFiddle (v-bind v-on) #b2.4.2 #b5.1.1
- #c6 點擊切換雙樣式 JSFiddle (methods v-on v-if v-on) #b0.3 #b2.4.2 #b3.1 #b5.1.1
- #c7 點擊切換燈泡明滅 JSFiddle web (methods v-bind v-on) #b0.3 #b2.4.2 #b5.1.1
- #c8 點擊切換三種色板 JSFiddle (v-bind v-on)#b2.1 #b2.4.2 #b5.1.1
4.綜合範例
以普遍、實用的應用主題,撰寫組件範例
4-1.狀態與除錯
有時在撰寫語法時,會遇到 {{ }}
double curly braces 的語法會跟後端有衝突,在 Vue Instance 上加入delimiters: ['${', '}']
避免錯誤發生:
#d1.0 避免語法與後端發生錯誤 JSFiddle Web
<div id="app">
<!-- 正常呈現數據 -->
<p>${ message }</p>
</div>
let vm = new Vue({
el: '#app',
// 自訂符號
delimiters: ['${', '}'],
data: {
message: 'Hello Vue.js!'
}
})
4-2.數據排序
#d2.0 顯示過濾/排序結果 JSFiddle Web
有時,我們想要顯示一組數據的過濾或排序副本,而不實際改變或重置原始數據。這種情況下,可以創建返回過濾或排序數組的計算屬性。
<!-- 將 evenNumbers 屬性,疊代入 n -->
<li v-for="n in evenNumbers">{{ n }}</li>
data: {
numbers: [ 1, 2, 3, 4, 5 ]
},
computed: {
evenNumbers: function () {
#返回計算數值
return this.numbers.filter(function (number) {
#返回除以2的餘數為零的數值
return number % 2 === 0
})
}
}
5.資料來源
Name | Url | Directions |
---|---|---|
Vue 官方網站 | link | Vue 基礎操作與介紹 |
用概念理解 Vue.js | link | 由淺入深的教學內容 |