每一個Vue Application必須建立一個root Vue Instance。html
<script> var vm = new Vue({ }); </script>
一個Vue實例至關於一個MVVM模式中的ViewModel。在建立Vue實例時,能夠傳入一個選項對象,包含數據、模板、掛載元素、方法、生命週期鉤子等選項。vue
Vue.js經過構造函數Vue{ option }建立一個Vue實例:node
var vm = new Vue({ option });
<div id="app"></div> <script> var vm = new Vue({ el: "#app" }); </script>
<div id="app">{{ title }}</div> <script> var vm = new Vue({ el: "#app", data: { title: "標題" } }); </script>
每一個Vue實例建立時,都會經歷一些列的初始化過程,調用相應的生命週期鉤子。npm
Vue生命週期鉤子:數組
◊ created:實例建立完成後調用,此階段完成數據監測等,但還沒有掛載,$el 還不可用。緩存
◊ mounted:el 掛載到實例後調用。app
<div id="app">{{ title }}</div> <script> var vm = new Vue({ el: "#app", data: { title: "標題" }, created: function () { console.log("Vue instance has been created!"); } }); </script>
<div id="app">{{ title }}</div> <script> var vm = new Vue({ el: "#app", data: { title: "標題" }, created() { console.log("Vue instance has been created!"); }, mounted() { console.log("mounted:" + this.$el); // <div id="app"></div> // console.log("mounted:" + this.$el.id); } }); </script>
Vue.js建立實例對象的選項中影響模板或DOM的選項:el 和 template。函數
◊ el :類型爲字符串,DOM 元素或函數。其做用是爲實例提供掛載元素。性能
◊ template:類型爲字符串。默認會將template 值替換掛載元素(即el 值對應的元素),併合並掛載元素和模板根節點的屬性。this
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>libing.vue</title> <script src="node_modules/vue/dist/vue.min.js"></script> </head> <body> <div id="app"> <h1>將被模板內容替換</h1> </div> <template id="tpl"> <div class="tpl">Todo List</div> </template> <script> var vm = new Vue({ el: "#app", template: "#tpl" }); </script> </body> </html>
渲染輸出HTML:
<body> <div class="tpl">Todo List</div> <template id="tpl"> <div class="tpl">Todo List</div> </template> <script> var vm = new Vue({ el: "#app", template: "#tpl" }); </script> </body>
Vue.js使用基於HTML的模版語法,容許聲明式地將DOM綁定至Vue實例的數據。
Vue.js的核心:採用模板語法聲明式的將數據渲染到DOM。
Vue.js 實例中經過 data 屬性定義數據,這些數據能夠在實例對應的模板中進行綁定並使用。
數據綁定:{{ }}
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>libing.vue</title> <script src="node_modules/vue/dist/vue.min.js"></script> </head> <body> <div id="app"> <h1>{{ title }}</h1> </div> <script> var vm = new Vue({ el: "#app", data: { title: "Todo List" } }); </script> </body> </html>
{{ }}:將數據中的 HTML 轉爲純文本後再進行插值。
v-html :輸出 HTML 代碼
<div id="app"> <div v-html="title"></div> </div> <script> var vm = new Vue({ el: "#app", data: { title: "<h1>Todo List</h1>" } }); </script>
不能在 Vue 模板中的 HTML 屬性上使用{{}}語法。
HTML 屬性中的值應使用 v-bind 指令。
<div id="app"> <div v-bind:title="title">Content</div> </div> <script> var vm = new Vue({ el: "#app", data: { title: "Todo List" } }); </script>
<div id="app"> {{ status ? "是" : "否" }} <div v-bind:title="status?'是':'否'">Content</div> </div> <script> var vm = new Vue({ el: "#app", data: { status: true } }); </script>
Vue.js 容許在表達式後添加可選的過濾器,以管道符 「|」 指示。
<div id="app"> <h1>{{ title | uppercase }}</h1> </div> <script> var vm = new Vue({ el: "#app", data: { title: "Todo List" }, filters: { uppercase: function (value) { return value.toUpperCase(); } } }); </script>
多個過濾器鏈式使用:
{{ name | filterA | filterB }}
傳入多個參數:
{{ name | filterA arg1 arg2}}
此時,filterA 將 name 的值作爲第一個參數,arg1,arg2 作爲第2、第三個參數傳入過濾器函數中。
Vue.js 提供全局方法Vue.filter() 註冊一個自定義過濾器,接受過濾器ID 和過濾器函數兩個參數。
過濾器註冊語法格式:
Vue.filter( id, [definition] )
示例:日期格式過濾器
引入moment.js:
npm install -S moment
import Vue from 'vue' import moment from 'moment' Vue.filter('datefmt', function (input, fmtstring) { return moment(input).format(fmtstring); }); new Vue({ el: '#app', data: { now: new Date() } })
{{ now | datefmt('YYYY-MM-DD HH:mm:ss') }}
指令是帶有 v- 前綴的特殊屬性。
指令用於在表達式的值改變時,將某些行爲應用到 DOM 上。
v-bind指令:用於響應式地更新 HTML 屬性。
v-on 指令:用於監聽 DOM 事件。
<div id="app"> <h1 v-if="status">{{ title }}</h1> </div> <script> var vm = new Vue({ el: "#app", data: { title: "Todo List", status: true } }); </script>
一些指令可以接受一個參數,參數在指令後以冒號(:)表示。
<div id="app"> <a v-bind:href="url">libingql</a> </div> <script> var vm = new Vue({ el: "#app", data: { url: "https://www.cnblogs.com/libingql" } }); </script>
修飾符:以句號 . 表示的特殊後綴,用於指出一個指定應該以特殊方式綁定。
示例:.prevent 修飾符告訴 v-on 指令對於觸發的事件調用 event.preventDefault()
<form v-on:submit.prevent="onSubmit"></form>
在 input 輸入框中使用 v-model 指令來實現雙向數據綁定。
<div id="app"> <div>{{ title }}</div> <input type="text" v-model="title" /> </div> <script> var vm = new Vue({ el: "#app", data: { title: "Todo List" } }); </script>
Vue.js 爲 v-bind
和 v-on
這兩個最經常使用的指令,提供特定簡寫。
<!-- 完整語法 --> <a v-bind:href="url"> ... </a> <!-- 簡寫 --> <a :href="url"> ... </a>
<!-- 完整語法 --> <a v-on:click="doSomething"> ... </a> <!-- 簡寫 --> <a @click="doSomething"> ... </a>
v-if指令:條件判斷
在 <template> 上使用 v-if 進行條件分組
<div id="app"> <h1 v-if="seen">Todo List</h1> <template v-if="ok"> <ul> <li>Todo Item</li> <li>Todo Item</li> <li>Todo Item</li> </ul> </template> </div> <script> var vm = new Vue({ el: "#app", data: { seen: true, ok: true } }); </script>
v-if / v-else語句塊:
<div id="app"> <h1 v-if="ok">是</h1> <h1 v-else>否</h1> </div> <script> var vm = new Vue({ el: "#app", data: { ok: true } }); </script>
v-if-else:v-if 以後的「else-if 塊」,能夠屢次鏈式地調用。
<div id="app"> <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> </div> <script> new Vue({ el: '#app', data: { type: 'C' } }); </script>
v-show:根據條件展現元素
v-show 的元素會始終渲染並保留在 DOM 中。v-show 只會切換元素的 display 這個 CSS 屬性。
<div id="app"> <h1 v-show="ok">Todo List</h1> </div> <script> var vm = new Vue({ el: "#app", data: { ok: true } }); </script>
注:v-show
沒法用於 <template>
元素,也不能和 v-else
配合使用。
v-if 是「真實」的條件渲染,由於它會確保條件塊(conditional block)在切換的過程當中,完整地銷燬(destroy)和從新建立(re-create)條件塊內的事件監聽器和子組件。
v-if 是惰性的(lazy):若是在初始渲染時條件爲 false,它不會執行任何操做 - 在條件第一次變爲 true 時,纔開始渲染條件塊。
v-show 無論初始條件如何,元素始終渲染,而且只是基於 CSS 的切換。
一般來講,v-if 在切換時有更高的性能開銷,而 v-show 在初始渲染時有更高的性能開銷。
若是須要頻繁切換,推薦使用 v-show,若是條件在運行時改變的可能性較少,推薦使用 v-if。
v-for 遍歷數組格式: item in items
其中,
items 是原始數據數組(source data array),
item 是數組中每一個迭代元素的指代別名(alias)。
<div id="app"> <ul> <li v-for="item in items">{{ item.text }}</li> </ul> </div> <script> var vm = new Vue({ el: "#app", data: { items: [{ id: 1, text: "Vue" }, { id: 2, text: "Angular" }, { id: 3, text: "React" }] } }); </script>
<div id="app"> <ul> <li v-for="item in list">{{ item.text }}</li> </ul> </div> new Vue({ el: '#app', data: { list: [{ id: 1, text: 'Vue' }, { id: 2, text: 'Angular' }, { id: 3, text: 'React' }] } });
v-for索引參數:
<li v-for="(item, index) in items">{{ index }}-{{ item.text }}</li>
其中,index從0開始。
v-for
能夠遍歷對象的屬性。
<div id="app"> <ul> <li v-for="value in item">{{ value }}</li> </ul> </div> <script> var vm = new Vue({ el: "#app", data: { item: { id: 1, text: "Vue" } } }); </script>
v-for遍歷對象屬性:兩個參數key、value
<div id="app"> <ul> <li v-for="(value, key) in item">{{ key }}:{{ value }}</li> </ul> </div> <script> var vm = new Vue({ el: "#app", data: { item: { id: 1, text: "Vue" } } }); </script>
v-for遍歷對象屬性:3個參數index、key、value,索引(index)從0開始。
<div id="app"> <ul> <li v-for="(value, key, index) in item">{{ index }}-{{ key }}:{{ value }}</li> </ul> </div> <script> var vm = new Vue({ el: "#app", data: { item: { id: 1, text: "Vue" } } }); </script>
爲便於 Vue 跟蹤每一個節點的身份,從新複用(reuse)和從新排序(reorder)現有元素,須要爲每項提供惟一的 key 屬性,從而給 Vue 一個提示。
理想的 key 值是每項都有惟一的 id。
推薦:在使用 v-for 時,儘量提供一個 key,除非迭代的 DOM 內容足夠簡單,或者是故意依賴於默認行爲來得到性能提高。
<div id="app"> <ul> <li v-for="item in items" v-bind:key="item.id">{{ item.text }}</li> </ul> </div> <script> var vm = new Vue({ el: "#app", data: { items: [{ id: 1, text: "Vue" }, { id: 2, text: "Angular" }, { id: 3, text: "React" }] } }); </script>
簡寫:
<li v-for="item in items" :key="item.id">{{ item.text }}</li>
v-for能夠在整數值範圍內迭代。
<div id="app"> <ul> <li v-for="n in 10">{{ n }}</li> </ul> </div> <script> new Vue({ el: '#app' }); </script>
在模板中使用表達式是很是方便直接的,只適用於簡單的操做,不適於加入過多的邏輯。
對於複雜的邏輯,使用 computed 屬性(computed property)。
計算屬性都以函數的形式,在Vue實例的computed選項中,最終返回計算後的結果。
<div id="app"> {{ fullName }} </div> <script> new Vue({ el: '#app', data: { firstName: "bing", lastName: "li" }, computed: { fullName: function () { return this.lastName + ' ' + this.firstName; } } }); </script>
計算屬性依賴一個或多個Vue實例的數據,只要其中任一數據變化,計算屬性就會從新執行,視圖(vm)也會更新。
<div id="app"> <table> <tr> <th>商品ID</th> <th>商品名稱</th> <th>單價</th> <th>數量</th> </tr> <tr v-for="item in products"> <td>{{ item.ID }}</td> <td>{{ item.ProductName }}</td> <td>{{ item.UnitPrice }}</td> <td> <input type="text" v-model="item.Quantity" /> </td> </tr> <tr> <td colspan="4" style="text-align: right;">總計:{{ total }}</td> </tr> </table> </div> <script> var vm = new Vue({ el: "#app", data: { products: [{ ID: 1, ProductName: "手機", UnitPrice: 1000, Quantity: 2 }, { ID: 2, ProductName: "電腦", UnitPrice: 5000, Quantity: 5 }] }, computed: { total: function () { var total = 0; for (var i = 0; i < this.products.length; i++) { total += this.products[i].Quantity * this.products[i].UnitPrice; } return total; } } }); </script>
computed 屬性默認只有 getter ,能夠在須要時提供一個 setter 。
<div id="app"> {{ fullName }} </div> <script> var vm = new Vue({ el: '#app', data: { firstName: "Bing", lastName: "Li" }, computed: { fullName: { get: function () { return this.lastName + ' ' + this.firstName; }, set: function (value) { var names = value.split(' ') this.lastName = names[0] this.firstName = names[names.length - 1] } } } }); vm.fullName = "Li Bing2018"; </script>
computed屬性會基於它所依賴的數據進行緩存。每一個 computed 屬性,只有在它所依賴的數據發生變化時,纔會從新取值(re-evaluate)。
<div id="app"> {{ now }} </div> <script> new Vue({ el: '#app', computed: { now: function () { return Date.now() } } }); </script>
method方法:每當觸發從新渲染(re-render)時,method 調用方式將老是再次執行函數。
在某些場景下,不但願有緩存,使用 method 方法替代。
<div id="app"> {{ now() }} </div> <script> new Vue({ el: '#app', methods: { now: function () { return Date.now() } } }); </script>
watch 屬性:Vue 提供的一種更加通用的方式,來觀察和響應 Vue 實例上的數據變化。
過分濫用 watch 屬性會形成一些問題,更推薦的方式是,使用 computed 屬性。
<div id="app"> <input type="text" v-model="firstName"> <input type="text" v-model="lastName"> <div>{{ fullName }}</div> </div> <script> new Vue({ el: '#app', data: { firstName: 'Bing', lastName: 'Li', fullName: 'Li Bing' }, computed: { firstName: function (val) { this.fullName = this.lastName + ' ' + val; }, lastName: function (val) { this.fullName = val + ' ' + this.firstName; } } }); </script>
<script> new Vue({ el: '#app', data: { firstName: 'Bing', lastName: 'Li', fullName: 'Li Bing' }, watch: { firstName: function () { this.fullName = this.lastName + ' ' + this.firstName; }, lastName: function () { this.fullName = this.lastName + ' ' + this.firstName; } } }); </script>
向 v-bind:class
傳入一個對象,來動態地切換 class。
<div id="app"> <div v-bind:class="{ active: isActive }"></div> </div> <script> new Vue({ el: '#app', data: { isActive: true } }); </script>
渲染:
<div class="active"></div>
active 這個 class 的存在與否,取決於 isActive 這個 data 屬性的 truthy 值。
v-bind:class 指令能夠和普通 class 屬性共存。能夠經過在對象中添加多個字段,來切換多個 class。
<div id="app"> <div class="static" v-bind:class="{ active: isActive, 'text-danger': hasError }"></div> </div> <script> new Vue({ el: '#app', data: { isActive: true, hasError: false } }); </script>
渲染:
<div class="static active"></div>
綁定對象,能夠無需內聯。
<div id="app"> <div v-bind:class="className"></div> </div> <script> new Vue({ el: '#app', data: { className: { active: true, 'text-danger': true } } }); </script>
渲染:
<div class="active text-danger"></div>
綁定返回對象的計算屬性。
<div id="app"> <div v-bind:class="className"></div> </div> <script> new Vue({ el: '#app', data: { isActive: true, hasError: true }, computed: { className: function () { return { active: this.isActive, 'text-danger': this.hasError } } } }); </script>
能夠向 v-bind:class 傳入一個數組,來與 class 列表對應。
<div id="app"> <div v-bind:class="[activeClass, errorClass]"></div> </div> <script> new Vue({ el: '#app', data: { activeClass: 'active', errorClass: 'text-danger' } }); </script>
三元表達式:
<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
數組語法中使用對象語法:
<div id="app"> <div v-bind:class="[{ active: isActive }, errorClass]"></div> </div> <script> new Vue({ el: '#app', data: { isActive: true, errorClass: 'text-danger' } }); </script>
v-bind:style 直接設置樣式
<div id="app"> <div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div> </div> <script> new Vue({ el: '#app', data: { activeColor: 'red', fontSize: 30 } }); </script>
渲染:
<div style="color: red; font-size: 30px;"></div>
綁定對象
<div id="app"> <div v-bind:style="style"></div> </div> <script> new Vue({ el: '#app', data: { style: { color: 'red', fontSize: '13px' } } }); </script>
v-bind:style 的對象語法,能夠和 computed 屬性結合使用,此 computed 屬性所對應的 getter 函數須要返回一個對象。
v-bind:style 的數組語法,能夠在同一個元素上,使用多個 style 對象。
<div id="app"> <div v-bind:style="[baseStyles, overridingStyles]"></div> </div> <script> new Vue({ el: '#app', data: { baseStyles: { color: 'red', fontSize: '30px' }, overridingStyles: { 'font-weight': 'bold' } } }); </script>
渲染:
<div style="color: red; font-size: 30px; font-weight: bold;"></div>
v-on 指令:監聽 DOM 事件,並在事件被觸發時執行 JavaScript 代碼。
<div id="app"> <button v-on:click="counter += 1">增長 1</button> <div>按鈕點擊次數:{{ counter }}次</div> </div> <script> new Vue({ el: '#app', data: { counter: 0 } }); </script>
用於處理邏輯復瑣事件
<div id="app"> <button v-on:click="greet">greet</button> </div> <script> var vm = new Vue({ el: '#app', data: { name: "Li Bing" }, methods: { greet: function (event) { // `this` 在方法裏指當前 Vue 實例 alert('Hello ' + this.name + '!') // `event` 是原生 DOM 事件 if (event) { alert(event.target.tagName) } } } }); // 能夠用 JavaScript 直接調用方法 vm.greet() // -> 'Hello Li Bing!' </script>
<div id="app"> <button v-on:click="greet('Li Bing')">greet</button> </div> <script> var vm = new Vue({ el: '#app', methods: { greet: function (name) { alert('Hello ' + name + '!'); } } }); </script>
在事件處理程序中常見調用 event.preventDefault() 或 event.stopPropagation()
v-on 提供事件修飾符,以點(.)開頭的指令後綴來表示。
◊ .stop
◊ .prevent
◊ .capture
◊ .self
◊ .once
<!-- 中止點擊事件冒泡 --> <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 是元素自身時,才觸發處理函數。 --> <!-- 也就是說,event.target 是子元素時,不觸發處理函數 --> <div v-on:click.self="doThat">...</div>
v-on:click.prevent.self 阻止全部點擊
v-on:click.self.prevent 只阻止元素自身的點擊