# Vue ## Vue 與其他框架的差異? tag: `輕量`、`入門容易` * 資料綁定&操作網頁元件 * 關注在狀態與畫面的同步 * 易方便和其他函式庫&工具鏈使用 ## 實體物件 ### 掛載方式 掛載對象可以是 CSS Selector 也可以是 DOM 物件 **透過 $mount 掛載** ```javascript const vm = new Vue({ data: { message: 'Hello World!' } }); vm.$mount('#app'); ``` **透過 options `el` attribute 掛載** ```javascript const vm = new Vue({ el: '#app' }) ``` ## 實體核心 Options ```javascript const vm = new Vue({ //options }); vm.$mount('#app'); ``` ### data 作為定義實體的屬性,回傳的狀態以 `Key-Value` 的形式 Vue 會自動將 data 內的屬性都加上 `getter` `setter` 來監控狀態更新 :::danger 如果以 _ 或 $ 命名的屬性將不會被加上 getter & setter ::: ```javascript const vm = new Vue({ data: { message: 'Apple' } }); vm.$mount('#app'); ``` 透過 {{ }} 文字模板的方式,就可將 `data` 的內容 Render 至畫面 ```htmlembedded <div id="app"> {{ message }} </div> ``` Vue 實體被建立後就會自動為實體加上 `$data` 屬性,就可以透過 `vm.$data.xxx` 進行操作 ```javascript const vm = new Vue({ data: { message: 'Apple' } }); vm.$mount('#app'); vm.$data.message = 'banana'; ``` ==共用污染== 如果 Vue 物件直接使用了同一個 Object 則容易會有污染問題 ```javascript const obj = { Name: 'Apple' } const vm1 = new Vue({ el: '#app', data: obj }) const vm2 = new Vue({ el: '#app', data: obj }) ``` 若使用 `vm2.$data.Name` 更改 Value,則會一起更動到 可以使用解構 `{...obj}` 來避免此種情形 ### template 可直接使用 template 屬性來決定 HTML 內容 一個 template 只會有一層元素,且必須要有根元素 ```javascript const vm = new Vue({ el: '#app', template: '<div>Hello {{ Name }}</div>', data: { name: 'Apple' } }) ``` ### methods 負責處理邏輯 ```htmlembedded <div id="app"> {{ getNameLength() }} </div> ``` ```javascript const vm = new Vue({ el: '#app', data: { name: 'Apple' } methods:{ getNameLength: function(){ return this.name.length } } }) ``` ### computed 負責處理計算邏輯 ```htmlembedded <div id="app"> {{ getTotal }} </div> ``` ```javascript const vm = new Vue({ el: '#app', data: { count: 1, price: 5 } methods:{ getTotal: function(){ return this.count * this.price; } } }) ``` #### computed & method 兩者不同之處 `computed` 會監控自己關注的屬性並將結果進行暫存,不會重複執行 `method` 則每次呼叫就會執行 `computed` 無法帶入參數 `method` 可帶入參數 `computed` 可以透過 set 更改自己關注的屬性本身 ### filters 處理純粹的加工,將相同的輸入丟入,永遠都會回傳相同的輸出,並且不對任何該函數以外的任何作用域產生影響。 使用 pipe 在文字模板內進行表示 pipe 前方作為 parameter 傳入 filters function 裏 ```htmlembedded <div id="app"> {{ name | getLowerCase }} </div> ``` ```javascript const vm = new Vue({ el: '#app', data: { name: 'Apple' } filters:{ getLowerCase: (value) => { return value.toLowerCase(); } } }) ``` ## 指令 ### 屬性綁定 v-bind 透過 v-bind 可以針對 HTML 元素的 Attribute 進行資料綁定 ```htmlembedded <div id="app"> <span v-bind:title="message">Hover On Text</span> <input v-bind:value="count()" /> </div> ``` ```javascript const appData = { message: "Apple 測試", number: 1 }; const vm = new Vue({ el: "#app", data: { ...app }, methods: { count: function(){ return this.number + 1 } }, }); ``` ![](https://i.imgur.com/V73Nxzr.png) ==更簡易的縮寫方式== 在屬性前方直接加上 `:` 就可將 Attribute 改為 v-bind 綁定的 Attribute ```htmlembedded <div id="app"> <span :title="message">Hover On Text</span> <input :value="count()" /> </div> ``` ### 表單綁定 v-model v-model 可以與表單元素進行雙向綁定,進行更新元素內容 ```htmlembedded <div id="vmodel"> <input v-model="message" /> <span>表單內容: {{ message }}</span> </div> ``` ```javascript const app = { message: "Apple 測試", number: 1 }; var vmodel = new Vue({ el: "#vmodel", data: { ...app } }); ``` ![](https://i.imgur.com/apVg7HU.png) #### 修飾子 `.lazy` 在 onBlur 時才會更新 data `.num` 將 text 轉型為 number `.trim` 將 text 前後空白移除 ### 模板綁定 v-text / v-html / v-pre / v-once #### v-text 除了使用 `{{ }}` 作為文字模板,也可以透過 v-text 來處理模板 ```htmlembedded <div id="vmodel"> <input v-model="message" /> <span v-text="message"></span> </div> ``` ```javascript const app = { message: "Apple 測試", number: 1 }; var vmodel = new Vue({ el: "#vmodel", data: { ...app } }); ``` 與 `{{ }}` 最大不同之處是 `v-text` 會將 HTML 標籤內的 Inner Text 覆蓋 #### v-html 與 `v-text` 不同,概念上很像 JavaScript 裡的 `innerText` & `innterHTML` `v-html` 會將內容的 HTML 語法進行渲染 ```htmlembedded <div id="vmodel"> <div v-html="title"></div> </div> ``` ```javascript const app = { title: "<h1>Apple 讚</h1>", }; var vmodel = new Vue({ el: "#vmodel", data: { ...app } }); ``` ![](https://i.imgur.com/CX2VW1y.png) #### v-once 內容只會渲染第一次,不會隨著資料更新 #### v-pre 加上指令 v-pre 後,就不會解析 `{{ }}` 的資訊 ### 樣式綁定 可以透過剛才的 `v-bind` 與 `class` `style` 進行簡單的樣式控制 ```htmlembedded <div id="vclass"> <div :class="{ 'active': isActive }"></div> </div> ``` ```css .active { color: 'blue' } ``` ```javascript const app = { isActive: true, }; var vclass = new Vue({ el: "#vclass", data: { ...app } }); ``` ### 事件綁定 v-on #### v-on `v-on` 為 Vue 與事件進行綁定的指令,也可縮寫為 `@event` ```htmlembedded <div id="von"> <span>Now Count : {{ count }}</span> <button @click="add()"></button> </div> ``` ```javascript const app = { count: 1, }; var vclass = new Vue({ el: "#von", data: { ...app }, methods:{ sum: function(){ return this.count++; } } }); ``` #### event 物件 v-on 在 method 沒有參數時會預設將 event 做為參數帶入 ```htmlembedded <div id="von"> <span>Now Count : {{ count }}</span> <button @click="sum"></button> </div> ``` ```javascript const app = { count: 1, }; var vclass = new Vue({ el: "#von", data: { ...app }, methods:{ sum(event){ console.log(event); // event object Button return this.count++; } } }); ``` 有參數時使用 $event 即可帶入 ```htmlembedded <div id="von"> <span>Now Count : {{ count }}</span> <button @click="sum(amount, $event)"></button> </div> ``` ```javascript const app = { count: 1, amount: 10 }; var vclass = new Vue({ el: "#von", data: { ...app }, methods:{ sum(amount, event){ console.log(event); // event object Button return this.count + amount; } } }); ``` #### 修飾子 `.stop` 阻止事件冒泡,形同 `event.stopPropagation()` `.prevent` 阻止預設事件行為,形同 `event.preventDefault()` `.capture` 捕獲事件,由上而下執行 `.self` 只觸發由事件本身產生的行為,子元素傳遞的不會觸發 `.once` 事件只觸發一次 `.passive` 被動事件監聽,告訴瀏覽器該元素是否可以被 prevent #### 鍵盤修飾子 `.enter` `.meta` `.ctrl` `.page-down` `.exact` 判斷確定是由該鍵盤按鍵 #### 滑鼠修飾子 `.left` `.middle` `.right` ### 條件綁定 v-if / v-show #### v-show `v-show` 主要控制元素顯示與隱藏 控制隱藏的方式是使用 `display: none` #### v-if 直接動態刪減元素,元素會直接新增或消失 可以搭配 `v-else-if` `v-else` 若有多重相同條件需要一起判斷時可以使用 `<template></template>` ```htmlembedded <div id="vif"> <template v-if="value === 'A'"> <span>Apple</span> <span>Arrange</span> </template> <template v-else> <span>Book</span> <span>Bamboo</span> </template> </div> ``` ```javascript const app = { value: 'A' }; var vclass = new Vue({ el: "#vif", data: { ...app } }); ``` :::info Vue 為了提高網頁渲染效率,在渲染畫面時會先使用已存在的元素 ::: 但有的時候元素身為不同的個體卻被當成同一個,因此可以使用 `key` 有 `key` 屬性的元素將會被重新渲染 ### 陣列渲染 v-for ```htmlembedded <div id="vfor"> <ul> <li v-for="item in arr"></li> <li v-for="(index, item) in arr"></li> </ul> </div> ``` ```javascript const app = { arr: ['apple, banana, orange'] }; var vclass = new Vue({ el: "#vfor", data: { ...app } }); ```