[Vue] Vue 隨手筆記

  • 1326
  • 0
  • Vue
  • 2019-02-25

隨手筆記 Vue 的大小事

前言

此篇為隨手筆記 Vue.js 程式語言,不定時更新,此篇若有錯誤之處還請提點指教。

目前以四個項目,分類與自我釐清語言的最小性與組合性,使日後要建立軟體專案時,可快速應用。

  1. 基本概念:Vue 專屬特性
  2. 基本語法:最小化的語言結構及範例
  3. 複合語法:組合性的語言結構及範例
  4. 綜合範例:以普遍、實用的應用主題,撰寫組件範例
  5. 資料來源:由於參考資料眾多,僅附註原參考資料網址

此篇中內容#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 函數創建一個新的 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) 的函數,讓開發者可以在特定階段添加自己的代碼。

關於 Vue 中的 this

> function 中的 this 指向其最上層的 Vue Instance

>鉤子中的 this 指向調用它的 Vue Instance


2.基本語法

最小化的語言結構及範例


Vue 有本地全局兩種方式來串聯資料的響應,2.基本語法內以本地方式撰寫,如為全局會另加說明。

 2-1.項目

Vue 有哪些選項物件?
{
  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>'
})
Prop傳遞值類型

Prop 傳遞值類型 

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 寫入選項物件

Vue 最基本的核心就是,一邊綁定位置,一邊寫入數據;如此數據會渲染 DOM 的系統,使數據寫入綁定位置內。

#b1 創建一個Vue實例 JSFiddle Web

{
 el:'',    // 綁定位置
 data: {} // 寫入數據
}

 2-2.指令

透過 Vue 綁定元素提示框

透過 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

 參考資料:vue中class和style設置的相關方法

<!-- 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>
透過 Vue 寫入限制
  • 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管理可重複的元素

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>
透過 Vue 寫入渲染項目列表

> 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傳遞多筆資料

透過 Vue 寫入事件
  • 透過 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>
透過 Vue 達成雙向綁定

> v-model

 2-3.屬性

透過 Vue 寫入屬性
  • Object.freeze(),阻止修改現有的屬性,意味著響應式系統無法再追蹤變化  #c1
  • #c1 阻止資料響應 link

Vue.filter ( id,[ definition ]) 過濾器

參數:

  • { String} id
  • { Function } [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.創建 組件/指令

d1 透過 Vue 創建模板

> 本地 component

> 全局 component

 

d2 透過 Vue 自定義事件

事件名

#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 由淺入深的教學內容