1. 安裝
<script>
引入- NPM
- 命令行工具 (CLI)
2. 入門
3. 數據與方法
當一個 Vue 實例被創建時,它向 Vue 的響應式系統中加入了其 data 對象中能找到的所有的屬性。當這些屬性的值發生改變時,視圖將會產生“響應”,即匹配更新爲新的值。
// 我們的數據對象
var data = { a: 1 }
// 該對象被加入到一個 Vue 實例中
var vm = new Vue({
data: data
})
// 獲得這個實例上的屬性
// 返回源數據中對應的字段
vm.a == data.a // => true
// 設置屬性也會影響到原始數據
vm.a = 2
data.a // => 2
// ……反之亦然
data.a = 3
vm.a // => 3
使用 Object.freeze(),會阻止修改現有的屬性,也意味着響應系統無法再追蹤變化。
4. 生命週期
5. 模板語法
插值
#文本:“Mustache”語法 (雙大括號)
v-once 表示指令一次性插值
<span>Message: {{ msg }}</span>
<span v-once>這個將不會改變: {{ msg }}</span>
#原始 HTML:v-html 指令
<span v-html="rawHtml"></span>
你的站點上動態渲染的任意 HTML 可能會非常危險,因爲它很容易導致 XSS 攻擊。請只對可信內容使用 HTML 插值,絕不要對用戶提供的內容使用插值。
XSS 是一種經常出現在web應用中的計算機安全漏洞,它允許惡意web用戶將代碼植入到提供給其它用戶使用的頁面中。
#特性:v-bind
<div v-bind:id="dynamicId"></div>
#使用 JavaScript 表達式
對於所有的數據綁定,Vue.js 都提供了完全的 JavaScript 表達式支持。
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
<div v-bind:id="'list-' + id"></div>
指令
指令 (Directives) 是帶有 v- 前綴的特殊特性。指令的職責是,當表達式的值改變時,將其產生的連帶影響,響應式地作用於 DOM。
#例子
<p v-if="seen">現在你看到我了</p> <!--v-if 指令將根據表達式 seen 的值的真假來插入、移除元素-->
#參數
一些指令能夠接收一個“參數”,在指令名稱之後以冒號表示。例如,v-bind 指令可以用於響應式地更新 HTML 特性:
<a v-bind:href="url">...</a>
v-on 指令,它用於監聽 DOM 事件。
<a v-on:click="doSomething">...</a>
#修飾符
修飾符 (Modifiers) 是以半角句號 . 指明的特殊後綴,用於指出一個指令應該以特殊方式綁定。
例如,.prevent 修飾符告訴 v-on 指令對於觸發的事件調用 event.preventDefault():
<form v-on:submit.prevent="onSubmit">...</form>
縮寫
#v-bind 縮寫
<!-- 完整語法 -->
<a v-bind:href="url">...</a>
<!-- 縮寫 -->
<a :href="url">...</a>
#v-on 縮寫
<!-- 完整語法 -->
<a v-on:click="doSomething">...</a>
<!-- 縮寫 -->
<a @click="doSomething">...</a>
6. 計算屬性
對於任何複雜邏輯,你都應當使用計算屬性。
例子
<div id="example">
<p>Original message: "{{ message }}"</p>
<p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
var vm = new Vue({
el: '#example',
data: {
message: 'Hello'
},
computed: {
// 計算屬性的 getter
reversedMessage: function () {
// `this` 指向 vm 實例
return this.message.split('').reverse().join('')
}
}
})
vs 方法
// 在組件中
methods: {
reversedMessage: function () {
return this.message.split('').reverse().join('')
}
}
計算屬性是基於它們的依賴進行緩存的。計算屬性只有在它的相關依賴發生改變時纔會重新求值。
不希望有緩存,則使用方法。
vs 偵聽屬性
同爲觀察和響應數據變動的方式。
<div id="demo">{{ fullName }}</div>
偵聽屬性
(偵聽屬性很適合偵聽中間狀態,而其他情況下,計算屬性更加合適)
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar',
fullName: 'Foo Bar'
},
watch: {
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
},
lastName: function (val) {
this.fullName = this.firstName + ' ' + val
}
}
})
計算屬性(推薦)
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar'
},
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName
}
}
})
#計算屬性的 setter
計算屬性默認只有 getter ,不過在需要時你也可以提供一個 setter :
// ...
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]
}
}
}
// ...
7. 綁定HTML CLASS
對象語法
可以傳給 v-bind:class
一個對象,以動態地切換 class。
可以在對象中傳入更多屬性來動態切換多個 class。
v-bind:class
指令也可以與普通的 class 屬性共存。
可以綁定一個返回對象的計算屬性。這是一個常用且強大的模式
<div v-bind:class="classObject"></div>
//返回對象的計算屬性
data: {
isActive: true,
error: null
},
computed: {
classObject: function () {
return {
active: this.isActive && !this.error,
'text-danger': this.error && this.error.type === 'fatal'
}
}
}
//數據對象
data: {
classObject: {
active: true,
'text-danger': false
}
}
數組語法
可以把一個數組傳給 v-bind:class
,以應用一個 class 列表:
<div v-bind:class="[activeClass, errorClass]"></div>
data: {
activeClass: 'active',
errorClass: 'text-danger'
}
用在組件上
當在一個自定義組件上使用 class 屬性時,這些類將被添加到該組件的根元素上面。這個元素上已經存在的類不會被覆蓋。
8. 綁定內聯樣式
對象語法
v-bind:style 的對象語法十分直觀——看着非常像 CSS,但其實是一個 JavaScript 對象。CSS 屬性名可以用駝峯式 (camelCase) 或短橫線分隔 (kebab-case,記得用單引號括起來) 來命名:
<div v-bind:style="styleObject"></div>
data: {
styleObject: {
color: 'red',
fontSize: '13px'
}
}
數組語法
<div v-bind:style="[baseStyles, overridingStyles]"></div>
9. 條件渲染
v-if & v-else-if & v-else
用於選擇渲染的元素。
用 key 管理可複用的元素
Vue 會儘可能高效地渲染元素,通常會複用已有元素而不是從頭開始渲染。
Vue 爲你提供了一種方式來表達“這兩個元素是完全獨立的,不要複用它們”。只需添加一個具有唯一值的 key 屬性即可(不添加key,元素會被複用,如input的輸入狀態不會被清除)。
v-show
另一個用於根據條件展示元素的選項是 v-show
指令。
<h1 v-show="ok">Hello!</h1>
不同的是帶有 v-show
的元素始終會被渲染並保留在 DOM 中。v-show
只是簡單地切換元素的 CSS 屬性 display
。
v-if vs v-show
一般來說,v-if
有更高的切換開銷,而 v-show
有更高的初始渲染開銷。因此,如果需要非常頻繁地切換,則使用 v-show
較好;如果在運行時條件很少改變,則使用 v-if
較好。
v-if 與 v-for 一起使用
當 v-if
與 v-for
一起使用時,v-for
具有比 v-if
更高的優先級。
//下面代碼只返回未完成的todo
<li v-for="todo in todos" v-if="!todo.isComplete">
{{ todo }}
</li>
10. 列表渲染
用 v-for 把一個數組對應爲一組元素
v-for 指令根據一組數組的選項列表進行渲染。v-for 指令需要使用 item in items 形式的特殊語法,items 是源數據數組並且 item 是數組元素迭代的別名。
<ul id="example-2">
<li v-for="(item, index) in items">
{{ parentMessage }} - {{ index }} - {{ item.message }}
</li>
</ul>
var example2 = new Vue({
el: '#example-2',
data: {
parentMessage: 'Parent',
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
})
一個對象的 v-for
<ul id="v-for-object" class="demo">
<li v-for="(value, key, index) in object">
{{ index }}. {{ key }}: {{ value }}
</li>
</ul>
new Vue({
el: '#v-for-object',
data: {
object: {
firstName: 'John',
lastName: 'Doe',
age: 30
}
}
})
key
爲了給 Vue 一個提示,以便它能跟蹤每個節點的身份,從而重用和重新排序現有元素,你需要爲每項提供一個唯一 key 屬性(否則列表順序改變時,vue只是簡單的複用元素)。理想的 key 值是每項都有的且唯一的 id。
建議儘可能在使用 v-for 時提供 key,除非遍歷輸出的 DOM 內容非常簡單,或者是刻意依賴默認行爲以獲取性能上的提升。
數組更新檢測
#變異方法
Vue 包含一組觀察數組的變異方法,它們會觸發視圖更新。
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
#替換數組
非變異方法,例如:filter(), concat() 和 slice() 。這些不會改變原始數組,但總是返回一個新數組。
example1.items = example1.items.filter(function (item) {
return item.message.match(/Foo/)
})
#注意事項
由於 JavaScript 的限制,Vue 不能檢測以下變動的數組(1/2)及對象(3):
- 當你利用索引直接設置一個項時,例如:
vm.items[indexOfItem] = newValue
- 當你修改數組的長度時,例如:
vm.items.length = newLength
- Vue 不能檢測對象屬性的添加或刪除
解決方法:
//1.
// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
vm.$set(vm.items, indexOfItem, newValue)
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)
//2.
vm.items.splice(newLength)
//3.
var vm = new Vue({
data: {
userProfile: {
name: 'Anika'
}
}
})
//添加一個新的 age 屬性到嵌套的 userProfile 對象
Vue.set(vm.userProfile, 'age', 27)
vm.$set(vm.userProfile, 'age', 27)
//使用Object.assign()爲已有對象賦予多個新屬性
vm.userProfile = Object.assign({}, vm.userProfile, {
age: 27,
favoriteColor: 'Vue Green'
})
顯示過濾/排序結果
有時,我們想要顯示一個數組的過濾或排序副本,而不實際改變或重置原始數據。在這種情況下,可以創建返回過濾或排序數組的計算屬性。
<li v-for="n in evenNumbers">{{ n }}</li>
data: {
numbers: [ 1, 2, 3, 4, 5 ]
},
computed: {
evenNumbers: function () {
return this.numbers.filter(function (number) {
return number % 2 === 0
})
}
}
一個組件的 v-for
<div id="todo-list-example">
<form v-on:submit.prevent="addNewTodo">
<label for="new-todo">Add a todo</label>
<input
v-model="newTodoText"
id="new-todo"
placeholder="E.g. Feed the cat"
>
<button>Add</button>
</form>
<ul>
<li
is="todo-item"
v-for="(todo, index) in todos"
v-bind:key="todo.id"
v-bind:title="todo.title"
v-on:remove="todos.splice(index, 1)"
></li>
</ul>
</div>
Vue.component('todo-item', {
template: '\
<li>\
{{ title }}\
<button v-on:click="$emit(\'remove\')">Remove</button>\
</li>\
',
props: ['title']
})
new Vue({
el: '#todo-list-example',
data: {
newTodoText: '',
todos: [
{
id: 1,
title: 'Do the dishes',
},
{
id: 2,
title: 'Take out the trash',
},
{
id: 3,
title: 'Mow the lawn'
}
],
nextTodoId: 4
},
methods: {
addNewTodo: function () {
this.todos.push({
id: this.nextTodoId++,
title: this.newTodoText
})
this.newTodoText = ''
}
}
})
11. 事件處理
監聽事件
可以用 v-on
指令監聽 DOM 事件,並在觸發時運行一些 JavaScript 代碼。
<div id="example-3">
<button v-on:click="say('hi')">Say hi</button>
<button v-on:click="say('what')">Say what</button>
</div>
new Vue({
el: '#example-3',
methods: {
say: function (message) {
alert(message)
}
}
})
有時也需要在內聯語句處理器中訪問原始的 DOM 事件。可以用特殊變量 $event
把它傳入方法:
<button v-on:click="warn('Form cannot be submitted yet.', $event)">
Submit
</button>
// ...
methods: {
warn: function (message, event) {
// 現在我們可以訪問原生事件對象
if (event) event.preventDefault()
alert(message)
}
}
事件修飾符
Vue.js 爲 v-on 提供了事件修飾符。之前提過,修飾符是由點開頭的指令後綴來表示的。
.stop
.prevent
.capture
.self
.once
.passive
<!-- 阻止單擊事件繼續傳播 -->
<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 是當前元素自身時觸發處理函數 -->
<!-- 即事件不是從內部元素觸發的 -->
<div v-on:click.self="doThat">...</div>
<!-- 點擊事件將只會觸發一次 2.1.4新增-->
<a v-on:click.once="doThis"></a>
<!-- 滾動事件的默認行爲 (即滾動行爲) 將會立即觸發 2.3.0新增-->
<!-- 而不會等待 `onScroll` 完成 -->
<!-- 這其中包含 `event.preventDefault()` 的情況 -->
<div v-on:scroll.passive="onScroll">...</div>
使用修飾符時,順序很重要;相應的代碼會以同樣的順序產生。因此,用 v-on:click.prevent.self 會阻止所有的點擊,而 v-on:click.self.prevent 只會阻止對元素自身的點擊。
按鍵修飾符
Vue 允許爲 v-on
在監聽鍵盤事件時添加按鍵修飾符。
按鍵別名:
.enter
.tab
.delete
(捕獲“刪除”和“退格”鍵).esc
.space
.up
.down
.left
.right
<input v-on:keyup.enter="submit">
<!-- 縮寫語法 -->
<input @keyup.enter="submit">
系統修飾鍵
可以用如下修飾符來實現僅在按下相應按鍵時才觸發鼠標或鍵盤事件的監聽器。
.ctrl
.alt
.shift
.meta
<!-- Alt + C -->
<input @keyup.alt.67="clear">
<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>
.exact 修飾符
<!-- 即使 Alt 或 Shift 被一同按下時也會觸發 -->
<button @click.ctrl="onClick">A</button>
<!-- 有且只有 Ctrl 被按下的時候才觸發 -->
<button @click.ctrl.exact="onCtrlClick">A</button>
<!-- 沒有任何系統修飾符被按下的時候才觸發 -->
<button @click.exact="onClick">A</button>
鼠標按鈕修飾符
.left
.right
.middle
使用 v-on
有幾個好處:
- 掃一眼 HTML 模板便能輕鬆定位在 JavaScript 代碼裏對應的方法。
- 因爲你無須在 JavaScript 裏手動綁定事件,你的 ViewModel 代碼可以是非常純粹的邏輯,和 DOM 完全解耦,更易於測試。
- 當一個 ViewModel 被銷燬時,所有的事件處理器都會自動被刪除。你無須擔心如何清理它們。
12. 表單輸入綁定
你可以用 v-model
指令在表單 <input>
及 <textarea>
元素上創建雙向數據綁定。它會根據控件類型自動選取正確的方法來更新元素。
v-model
會忽略所有表單元素的 value
、checked
、selected
特性的初始值而總是將 Vue 實例的數據作爲數據來源。你應該通過 JavaScript 在組件的 data
選項中聲明初始值。
詳細:https://cn.vuejs.org/v2/guide/forms.html
13. 組件基礎
- 因爲組件是可複用的 Vue 實例,所以它們與
new Vue
接收相同的選項,例如data
、computed
、watch
、methods
以及生命週期鉤子等。僅有的例外是像el
這樣根實例特有的選項。 - 一個組件的 data 選項必須是一個函數,因此每個實例可以維護一份被返回對象的獨立的拷貝。
// 定義一個名爲 button-counter 的新組件
Vue.component('button-counter', { //通過 Vue.component 全局註冊
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})
我們可以在一個通過 new Vue
創建的 Vue 根實例中,把這個組件作爲自定義元素來使用:
<div id="components-demo"> <button-counter></button-counter></div>
new Vue({ el: '#components-demo' })
通過 Prop 向子組件傳遞數據
Prop 是你可以在組件上註冊的一些自定義特性。當一個值傳遞給一個 prop 特性的時候,它就變成了那個組件實例的一個屬性。
Vue.component('blog-post', {
props: ['title'],
template: '<h3>{{ title }}</h3>'
})
<blog-post title="My journey with Vue"></blog-post>