Vue 是一套用於構建用戶界面的漸進式框架。與其它大型框架不一樣的是,Vue 被設計爲能夠自底向上逐層應用,專一於聲明式渲染視圖層,結合豐富的生態系統和核心插件,致力於簡單靈活快速驅動SPA、MPA等大小型應用。css
本文依次介紹 雙向數據綁定、計算屬性、組件、事件機制、插件機制、前端路由、狀態管理和服務端渲染等。html
Vue.js應用的建立很簡單,經過構造函數 Vue 就能夠建立一個 Vue 的根實例,並啓動 Vue;前端
var app = new Vue({
//選項
});
複製代碼
變量 app 就表明了這個 Vue 實例,事實上幾乎全部的代碼都是一個對象,用來寫入 Vue 實例的選項內的。vue
首先,必不可少的一個選項就是el,el用於指定一個頁面中己存在的DOM元素來掛載Vue 實例,它能夠是 HTMLElement ,也能夠是CSS選擇器,好比:node
<div id='app'></div>
var app =new Vue({
el: document.getElementByld('app') // 或者是'#app'
});
複製代碼
一個 Vue 應用由一個經過 new Vue() 建立的根Vue實例,以及可選的嵌套的、可複用的組件樹組成。vue-router
當一個 Vue 實例被建立時,它將 data 對象中的全部的屬性加入到 Vue 的響應式系統中。當這些屬性的值發生改變時,視圖將會產生「響應」,即匹配更新爲新的值。vuex
建議全部會用到的數據都預先在data內聲明,這樣不至於將數據散落在業務邏輯中,難以維護。 Vue實例自己也代理了 data對象裏的全部屬性,因此能夠這樣訪問:編程
var app = new Vue({
el: '#app',
data: {
a: 2
}
});
console.log(app.a); // 2
複製代碼
除了顯式地聲明數據外,也能夠指向一個己有的變量,而且它們之間默認創建了雙向綁定,當修改其中任意一個時,另外一個也會一塊兒變化:後端
var myData = {
a: 1
};
var app =new Vue({
el: '#app',
data: myData
});
console.log(app.a) ; // 1
//修改屬性,原數據也會隨之修改
app.a = 2;
console.log(myData.a); // 2
//反之,修改原數據, Vue屬性也會修改
myData.a = 3;
console.log(app.a); // 3
複製代碼
每一個 Vue 實例建立時,都會經歷一系列的初始化過程,同時也會調用相應的生命週期鉤子, 咱們能夠利用這些鉤子,在合適的時機執行咱們的業務邏輯。api
Vue的生命週期大體分爲四個階段:
beforeCreate(此時date、method和el均沒有初始化,能夠在此加載loading) created(此時date和method初始化完成,可是DOM節點並無掛載,判斷是否有el節點,若是有則編譯template,若是沒有則使用vm.$mount建立一個默認節點,此時能夠在DOM渲染以前進行數據的初始化和method的自執行等)
beforeMount(編譯模板,而且將此時在el上掛載一個虛擬的DOM節點) mounted(編譯模板,且將真實的DOM節點掛載在el上)
beforeUpdate(在數據有更新時,進入此鉤子函數,虛擬DOM被從新建立) updated(數據更新完成時,進入此鉤子函數)
beforeDestory(組件銷燬前調用,此時將組件上的watchers、子組件和事件都移除掉) destoryed(組件銷燬後調用)
在建立時,父子組件的生命週期是: 父組件beforeCreated -> 父組件created -> 父組件beforeMounted -> 子組件beforeCreated -> 子組件created -> 子組件beforeMounted -> 子組件mounted -> 父組件mounted。
在銷燬時,父子組件的生命週期是: 父組件beforeDestory -> 子組件beforeDestoryed -> 子組件destoryed -> 父組件destoryed
總之記住,父子組件的生命週期遵循:由外到內,再由內到外。
不要在選項屬性或回調上使用箭頭函數,vue會自動綁定this的上下文環境。
Vue.js 使用了基於 HTML 的模板語法,容許開發者聲明式地將 DOM 綁定至底層 Vue 實例的數據。全部 Vue.js 的模板都是合法的 HTML ,因此能被遵循規範的瀏覽器和 HTML 解析器解析。
在底層的實現上,Vue 將模板編譯成虛擬 DOM 渲染函數。結合響應系統,Vue 可以智能地計算出最少須要從新渲染多少組件,並把 DOM 操做次數減到最少。
使用雙大括號(Mustache 語法)「{{}}」
是最基本的文本插值方法,它會自動將咱們雙向綁定的數據實時顯示出來,
<span>Message: {{ msg }}</span>
複製代碼
若是想顯示{{}}
標籤,而不進行替換,使用v-pre便可跳過這個元素和它的子元素的編譯過程,例如 :
<span v-pre>{{這裏的內容是不會被編譯的}}</span>
複製代碼
在{{}}
中,除了簡單的綁定屬性值外,還可使用JavaScript表達式進行簡單的運算、三元運算等,例如 :
<div id='app'>
{{ number / 10 ))
{{ isOK ? ’肯定’ : ’取消’ }}
{{ text.split(’,’).reverse().join(’,’) }}
</div>
複製代碼
經過使用 v-once
指令,你也能執行一次性地插值,當數據改變時,插值處的內容不會更新。但請留心這會影響到該節點上的其它數據綁定:
<span v-once>這個將不會改變: {{ msg }}</span>
複製代碼
若是你熟悉虛擬 DOM 而且偏心 JavaScript 的原始力量,你也能夠不用模板,直接寫渲染 (render)
函數,使用可選的 JSX
語法。
指令(Directives) 是帶有 v-
前綴的特殊特性。指令特性的值預期是單個 JavaScript 表達式 (v-for是例外狀況)。指令的職責是當表達式的值改變時,將其產生的連帶影響,響應式地做用於 DOM。 經常使用的指令以下:
v-cloak不須要表達式,它會在 Vue 實例結束編譯時從綁定的 HTML 元素上移除 , 常常和css的 display: none配合使用:
<div id='app' v-cloak> {{ message }}</div>
<style>
[v-cloak] {
display: none;
}
</style>
複製代碼
當網速較慢 Vue.js 文件還沒加載完時,在頁面上會顯示{ { message }}的字樣,直到 Vue 建立實例、編譯模板時, DOM 纔會被替換,因此這個過程屏幕是有閃動的,只要加上v-cloak就能夠避免了。在通常狀況下, v-cloak 是一個解決初始化慢致使頁面閃動的最佳實踐,對於簡單的項目很實用,可是在具備工程化的項目裏,項目的HTML 結構只有一個空的 div元素,剩餘的內容都是由路由去掛載不一樣組件完成的,因此再也不須要 v-cloak;
v-once 也是一個不須要表達式的指令,做用是定義它的元素或組件只渲染一次,包括元素或組件的全部子節點。首次渲染後,再也不隨數據的變化從新渲染,將被視爲靜態內容,例如:
<span v-once>{{ message }}</div>
複製代碼
v-once在業務中也不多使用,當你須要進一步優化性能時,可能會用到。
爲了輸出真正的 HTML,須要使用 v-html 指令;
var contenthtml = `<span>哈哈大笑😄</span>`;
<span v-html="contenthtml"></span>
複製代碼
你的站點上動態渲染的任意 HTML 可能會很是危險,由於它很容易致使 XSS 攻擊。請只對可信內容使用 HTML 插值,毫不要對用戶提供的內容使用插值,必要時在服務端進行提早過濾轉義。
用於條件性地渲染一塊內容,該指令是惰性的,當初始值爲false時dom節點不會進行渲染,是針對dom節點的移除和添加,例如 :
<div id='app'>
<span v-if='false'>{{ message }}</span>
</div>
// 會被渲染爲如下節點:
<div id='app'></div>
複製代碼
v-show的用法與v-if基本一致,只不過v-show是改變元素的css屬性display。當v-show 表達式的值爲 false 時, 元素會隱藏,查看 DOM 結構會看到元素上加載了內聯樣式 display: none; 例如 :
<div id='app'>
<span v-show='false'>{{ message }}</span>
</div>
// 會被渲染爲如下節點
<div id='app'>
<span style="display: none;」>哈哈大笑😄</span> </div> 複製代碼
v-show不能在<template>上使用。相比之下, v-if更適合條件不常常改變的場景,由於它切換開銷相對較大,而 v-show 適用於頻繁切換條件。
v-else 元素必須緊跟在帶 v-if 或者 v-else-if的元素的後面,不然它將不會被識別。例如 :
<span v-if='show'>{{ message.a }}</span>
<span v-else>{{ message.b }}</span>
複製代碼
當須要將一個數組遍歷或枚舉一個對象循環顯示時,就會用到列表渲染指令 v-for。它的表達式需結合 in來使用,相似 item in items 的形式,看下面的示例 :
<ul>
<li v-for=」book in books」 :key="book.id">{{ book.name }}</li>
</ul>
複製代碼
當 Vue 正在更新使用 v-for 渲染的元素列表時,它默認使用「就地更新」的策略。若是數據項的順序被改變,Vue 將不會移動 DOM 元素來匹配數據項的順序,而是就地更新每一個元素,而且確保它們在每一個索引位置正確渲染,因此須要爲每一個元素設置惟一的key。
v-bind用於動態更新 HTML 元素上的屬性,好比 id、class等;
<div id=」app」>
<a v-bind:href=」url」〉連接</a>
<img v-bind:src=」imgUrl」>
</div>
複製代碼
以上是 v-bind 最基本的用法,它在 Vue.js 組件中還有着極其重要的做用,能夠簡寫爲:
;
v-on在事件綁定上,相似原生 JavaScript 的 onclick等寫法,也是在 HTML 上進行監昕的,例如:
<button v-on:click=」counter++」>+ 1</button>
複製代碼
v-on:click的表達式能夠直接使用 JavaScript 語句,也能夠是一個在 Vue實例中 methods選項內的函數名,例如:
<button v-on:click=」handleAdd(1)」>+ 1</button>
methods: {
handleAdd: function(count) {
this.counter += count;
}
}
複製代碼
v-on:click調用的方法名後能夠不跟括號「()」 ;
Vue 提供了 一個特殊變量$event,用於訪問原生DOM事件,例以下面的實例能夠阻止連接打開;
<a href=」http://www.apple.com」 @click="handleClick ('禁止打開',$event)">
打開連接 </a>
methods: {
handleClick: function(message, event) {
event.preventDefault();
}
}
複製代碼
v-on能夠簡寫爲@
。
v-model用於表單,進行雙向數據綁定。例如:
<input type=」text」 id="name" v-model="fullname" />
<p>你好,{{fullname}} !</p>
複製代碼
Vue.js 容許你自定義過濾器,可被用於一些常見的文本格式化。過濾器能夠用在兩個地方:雙花括號插值和 v-bind 表達式。過濾器應該被添加在 JavaScript 表達式的尾部,由「管道」符號指示:
<!-- 在雙花括號中 -->
{{ message | capitalize }}
<!-- 在 `v-bind` 中 -->
<div v-bind:id="rawId | formatId"></div>
複製代碼
你能夠在一個組件的選項中定義本地的過濾器:
filters: {
capitalize: function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
}
// 或者在建立 Vue 實例以前全局定義過濾器:
Vue.filter('capitalize', function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
})
複製代碼
過濾器能夠串聯:
{{ message | filterA | filterB }}
複製代碼
過濾器是 JavaScript 函數,所以能夠接收參數:
{{ message | filterA('arg1', arg2) }}
複製代碼
這裏,filterA 被定義爲接收三個參數的過濾器函數。其中message 的值做爲第一個參數,普通字符串 'arg1' 做爲第二個參數,表達式 arg2 的值做爲第三個參數。
在一個計算屬性裏能夠完成各類複雜的邏輯,包括運算、函數調用等,只要最終返回 一個結果就能夠。計算屬性還能夠依賴多個Vue實例的數據,只要其中任一數據變化,計算屬性就會從新執行,視圖也會更新。
<span>{{fullName}}</span>
computed: {
fullName: {
get: function() {
return this.firstName + ' ' + this.lastName;
},
set: function(newValue) {
var names= newValue.split (' ') ;
this.firstName = names[O);
this.lastName = names[names.length - 1];
}
}
}
複製代碼
咱們能夠經過在表達式中調用方法來達到一樣的效果:
<span>{{getName()}}</span>
methods: {
getName: function() {
return this.firstName + ' ' + this.lastName;
}
}
複製代碼
咱們能夠將同一函數定義爲一個方法而不是一個計算屬性。兩種方式的最終結果確實是徹底相同的。然而,不一樣的是計算屬性是基於它們的響應式依賴進行緩存的。只在相關響應式依賴發生改變時它們纔會從新求值。
雖然計算屬性在大多數狀況下更合適,但有時也須要一個自定義的偵聽器。這就是爲何 Vue 經過 watch選項提供了一個更通用的方法,來響應數據的變化。當須要在數據變化時執行異步或開銷較大的操做時,這個方式是最有用的。
watch: {
message(newvalue, oldValue) {
newvalue && this.getNewMessage();
}
}
複製代碼
組件是可複用的 Vue 實例,一般一個應用會以一棵嵌套的組件樹的形式來組織:
組件 ( Component)是 Vue 最核心的功能,也是整個框架設計最精彩的地方,固然也是最難 掌握的。組件須要註冊後纔可使用,註冊有全局註冊和局部註冊兩種方式。全局註冊後, 任何 Vue 實例均可以使用。
全局註冊示例代碼以下 :
Vue.component(’my-component’, {
//選項
})
複製代碼
在 Vue 實例中,使用 components選項能夠局部註冊組件,註冊後的組件只有在該實例做用域下有效。組件中也可使用components選項來註冊組件,使組件能夠嵌套。示例代碼以下:
<div id=」app」>
<my-component></my-component>
</div>
<script>
var Child = {
template: '<div>局部註冊組件的內容</div>'
};
components: {
’my-component’: Child
}
</script>
複製代碼
Vue 組件的模板在某些狀況下會受到HTML的限制,好比<table>
內規定只容許是<tr>
、<td>
、<th>
等這些表格元素,因此在<table>
內直接使用組件是無效的。這種狀況下可使用特殊的is屬性來掛載組件,示例代碼以下 :
<div id=」app」>
<table>
<tbody is=」my-component」></tbody>
</table>
</div>
<script>
var Child = {
template: '<div>局部註冊組件的內容</div>'
};
components: {
’my-component’: Child
}
</script>
複製代碼
常見的限制元素還有<ul>、<ol>、<select>;若是使用字符串模板是不受限制的;
除了 template選項外,組件中還能夠像 Vue實例那樣使用其餘的選項,好比 data、 computed、 methods 等。可是在使用 data 時和實例稍有區別, data 必須是函數,而後將數據 return 出去, 例如:
Vue.component('my-component', {
template: '<div>{{ message }}</div>',
data: function() {
return {
message: 'aaa'
}
}
});
複製代碼
props傳遞數據、 events觸發事件和slot內容分發就構成了Vue組件的3個API來源,再復 雜的組件也是由這 3 部分構成的。
組件不只僅是要把模板的內容進行復用,更重要的是組件間要進行通訊。一般父組件的模板 中包含子組件,父組件要正向地向子組件傳遞數據或參數,子組件接收到後根據參數的不一樣來渲染不一樣的內容或執行操做。這個正向傳遞數據的過程就是經過 props 來實現的。
在組件中,使用選項 props 來聲明須要從父級接收的數據, props 的值能夠是兩種, 一種是字符串數組,一種是對象:
// 字符串數組
Vue.component ('my-component', {
props: [ ’ message ’ ] ,
template: ’<div>{{ message }}</div>’
});
// 對象形式
Vue.component ('my-component', {
props: {
//必須是數字類型
propA : Number,
//必須是字符串或數字類型
propB : [String , Number],
//布爾值,若是沒有定義,默認值就是 true
propC: {
type: Boolean,
default: true
},
//數字,並且是必傳
propD: {
type: Number,
required: true
},
//若是是數組或對象,默認值必須是一個函數來返回
propE: {
type: Array,
default: function() {
return [];
}
}
} ,
template: ’<div>{{ message }}</div>’
});
複製代碼
用集中式的事件中間件能夠作到簡單的數據傳遞,這會讓組件之間的通訊很是順利,即便是兄弟組件。由於 Vue 經過事件發射器接口執行實例,實際上你可使用一個空的 Vue 實例,經過單獨的事件中心管理組件間的通訊:
var eventHub = new Vue();
複製代碼
而後在組件中,可使用 $emit
, $on
, $off
分別來分發、監聽、取消監聽事件:
eventHub.$emit('delete', id);
eventHub.$on('delete', this.delete);
eventHub.$off('delete', this.delete)
複製代碼
Vue 實現了一套內容分發的 API,這套 API 的設計靈感源自 Web Components 規範草案,將 元素做爲承載分發內容的出口。
// 父組件
<submit-button>save</submit-button>
// 子組件
<button type="submit">
<slot>Submit</slot>
</button>
// 最終渲染
<button type="submit">
Save
</button>
複製代碼
// 父組件
<base-layout>
<template v-slot:header>
<h1>Here might be a page title</h1>
</template>
<template v-slot:default>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
</template>
<template v-slot:footer>
<p>Heres some contact info</p>
</template>
</base-layout>
// 子組件
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
// 最終渲染
<div class="container">
<header>
<h1>Here might be a page title</h1>
</header>
<main>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
</main>
<footer>
<p>Heres some contact info</p>
</footer>
</div>
複製代碼
// 父組件
<current-user>
<template v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</template>
</current-user>
// 子組件
<span>
<slot v-bind:user="user">
{{ user.lastName }}
</slot>
</span>
複製代碼
插槽對於組件意義非凡,能夠自定義拓展實現不少複雜的業務場景,且低耦合;
父子組件進行通訊最經常使用這種方式:
// 父組件
<template>
<child :updateTitle='updateTitle'></child>
</template>
<script>
export {
data: {
return {
title: '我是父組件'
}
},
methods: {
updateTitle(value) {
this.title = value;
}
}
}
</script>
// 子組件
<template>
<header>
<h1 @click="changeTitle">{{title}}</h1>
</header>
</template>
<script>
export {
props: {
title: {
type: String,
default: '我是父組件'
}
},
methods: {
changeTitle() {
this.$emit('updateTitle', '我是子組件');
}
}
}
</script>
複製代碼
父子、兄弟組件之間均可以使用這種方式:
var Event=new Vue();
Event.$emit(事件名,數據);
Event.$on(事件名,data => {});
複製代碼
$emit
負責分發事件,$on負責監聽了自定義事件,由於有時不肯定什麼時候會觸發事件,通常會在 mounted 或 created 鉤子中來監聽。
Vuex 實現了一個單向數據流,在全局擁有一個 State 存放數據,當組件要更改 State 中的數據時,必須經過 Mutation 進行,Mutation 同時提供了訂閱者模式供外部插件調用獲取 State 數據的更新。而當全部異步操做(常見於調用後端接口異步獲取更新數據)或批量的同步操做須要走 Action,但 Action 也是沒法直接修改 State 的,仍是須要經過 Mutation 來修改 State 的數據。最後,根據 State 的變化,渲染到視圖上。
通常用於比較複雜的大中型應用,一個應用只有一個store,經過插件的機制注入應用自己,下面的所有組件均可以訪問到store中的數據,便於數據的管理和追蹤變化;
$attrs
/$listeners$attrs
包含了父做用域中不被 prop 所識別 (且獲取) 的特性綁定 (class 和 style 除外)。當一個組件沒有聲明任何 prop 時,這裏會包含全部父做用域的綁定 (class 和 style 除外),而且能夠經過 v-bind="$attrs" 傳入內部組件。一般配合 interitAttrs 選項一塊兒使用。
$listeners
包含了父做用域中的 (不含 .native 修飾器的) v-on 事件監聽器。它能夠經過 v-on="$listeners" 傳入內部組件。
// 父組件
<template>
<child :foo="foo" :boo="boo" title="天道酬勤Lewis"></child>
</template>
// 子組件
<template>
<p>boo: {{ boo }}</p>
<p>child: {{ $attrs }}</p>
</template>
複製代碼
Vue2.4 提供了$attrs,$listeners來傳遞數據與事件,跨級組件之間的通信變得更簡單。 簡單來講:$attrs與$listeners 是兩個對象,$attrs 裏存放的是父組件中綁定的非 Props 屬性,$listeners裏存放的是父組件中綁定的非原生事件。
Vue2.2.0 新增 API,這對選項須要一塊兒使用,以容許一個祖先組件向其全部子孫後代注入一個依賴,不論組件層次有多深,在上下游關係成立的時間裏始終生效。一言而蔽之:祖先組件中經過 provider 來提供變量,而後在子孫組件中經過 inject來注入變量。
provide / inject API 主要解決了跨級組件間的通訊問題,不過它的使用場景,主要是子組件獲取上級組件的狀態,跨級組件間創建了一種主動提供與依賴注入的關係。
// 父組件
export default {
provide: {
name: '天道酬勤Lewis'
}
}
// 子組件
export default {
inject: ['name'],
mounted () {
console.log(this.name); // 天道酬勤Lewis
}
}
複製代碼
provide 和 inject 綁定並非可響應的,這是刻意爲之的。然而,若是你傳入了一個可監聽的對象,那麼其對象的屬性仍是可響應的。
Vue定義了四種添加事件監聽的方法:
Vue.prototype.$on = function (event, fn) {
var this$1 = this;
var vm = this;
//若是傳參event是數組,遞歸調用$on
if (Array.isArray(event)) {
for (var i = 0, l = event.length; i < l; i++) {
this$1.$on(event[i], fn);
}
} else {
(vm._events[event] || (vm._events[event] = [])).push(fn);
// 這裏在註冊事件的時候標記bool值也就是個標誌位來代表存在鉤子,而不須要經過哈希表的方法來查找是否有鉤子,這樣作能夠減小沒必要要的開銷,優化性能。
if (hookRE.test(event)) {
vm._hasHookEvent = true;
}
}
return vm
};
複製代碼
Vue.prototype.$once = function (event, fn) {
var vm = this;
function on () {
//在第一次執行的時候將該事件銷燬
vm.$off(event, on);
//執行註冊的方法
fn.apply(vm, arguments);
}
on.fn = fn;
vm.$on(event, on);
return vm
};
複製代碼
Vue.prototype.$emit = function (event) {
var vm = this;
{
var lowerCaseEvent = event.toLowerCase();
if (lowerCaseEvent !== event && vm._events[lowerCaseEvent]) {
tip(
"Event \"" + lowerCaseEvent + "\" is emitted in component " +
(formatComponentName(vm)) + " but the handler is registered for \"" + event + "\". " +
"Note that HTML attributes are case-insensitive and you cannot use " +
"v-on to listen to camelCase events when using in-DOM templates. " +
"You should probably use \"" + (hyphenate(event)) + "\" instead of \"" + event + "\"."
);
}
}
var cbs = vm._events[event];
if (cbs) {
//將類數組的對象轉換成數組
cbs = cbs.length > 1 ? toArray(cbs) : cbs;
var args = toArray(arguments, 1);
for (var i = 0, l = cbs.length; i < l; i++) {
try {
//觸發當前實例上的事件,附加參數都會傳給監聽器回調。
cbs[i].apply(vm, args);
} catch (e) {
handleError(e, vm, ("event handler for \"" + event + "\""));
}
}
}
return vm
};
複製代碼
Vue.prototype.$off = function (event, fn) {
var this$1 = this;
var vm = this;
// 若是沒有參數,關閉所有事件監聽器
if (!arguments.length) {
vm._events = Object.create(null);
return vm
}
// 關閉數組中的事件監聽器
if (Array.isArray(event)) {
for (var i = 0, l = event.length; i < l; i++) {
this$1.$off(event[i], fn);
}
return vm
}
// 具體的某個事件
var cbs = vm._events[event];
if (!cbs) {
return vm
}
// fn回調函數不存在,將事件監聽器變爲null,返回vm
if (!fn) {
vm._events[event] = null;
return vm
}
// 回調函數存在
if (fn) {
// specific handler
var cb;
var i$1 = cbs.length;
while (i$1--) {
cb = cbs[i$1];
if (cb === fn || cb.fn === fn) {
// 移除 fn 這個事件監聽器
cbs.splice(i$1, 1);
break
}
}
}
return vm
};
複製代碼
<!-- 阻止單擊事件繼續傳播 -->
<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>
複製代碼
Vue提供了插件機制,能夠在全局添加一些功能。它們能夠簡單到幾個方法、屬性,也能夠 很複雜,好比一整套組件庫。 註冊插件須要一個公開的方法 install,它的第一個參數是 Vue 構造器,第二個參數是一個可選的選項對象,示例代碼以下:
MyPlugin.install = function (Vue, options) {
//全局註冊組件(指令等功能資源相似〉
Vue.component ('component-name',{
//組件內容
}),
//添加實例方法
Vue.prototype.$Notice = function() {
//邏輯 ...
},
//添加全局方法或屬性
Vue.globalMethod = function() {
//邏輯 ...
},
//添加全局混合
Vue.mixin ({
mounted: function() {
//邏輯 ...
}
}),
//添加全局過濾器
Vue.directive('my-directive', {
bind (el, binding, vnode, oldVnode) {
// 邏輯...
}
}
})
};
// 經過 Vue.use()來使用插件:
Vue.use(MyPlugin);
// 或
Vue.use(MyPlugin, {
// 參數選項
});
複製代碼
絕大多數狀況下,開發插件主要是經過NPM發佈後給別人使用的,在本身的項目中能夠直接在入口調用以上方法 ,無須多一步註冊和使用的步驟 。
Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,讓構建單頁面應用變得易如反掌。
包含的功能有:
// 0. 若是使用模塊化機制編程,導入Vue和VueRouter,要調用 Vue.use(VueRouter)
// 1. 定義 (路由) 組件。
// 能夠從其餘文件 import 進來
const Foo = { template: '<div>foo</div>' }
const Bar = { template: '<div>bar</div>' }
// 2. 定義路由
// 每一個路由應該映射一個組件。 其中"component" 能夠是
// 經過 Vue.extend() 建立的組件構造器,
// 或者,只是一個組件配置對象。
const routes = [
{ path: '/foo', component: Foo },
{ path: '/bar', component: Bar }
]
// 3. 建立 router 實例,而後傳 `routes` 配置
// 你還能夠傳別的配置參數, 不過先這麼簡單着吧。
const router = new VueRouter({
routes // (縮寫) 至關於 routes: routes
})
// 4. 建立和掛載根實例。
// 記得要經過 router 配置參數注入路由,
// 從而讓整個應用都有路由功能
const app = new Vue({
router
}).$mount('#app')
複製代碼
vue-router 默認 hash 模式 —— 使用 URL 的 hash 來模擬一個完整的 URL,因而當 URL 改變時,頁面不會從新加載,這種模式利用監聽onhashchange事件,來實現頁面的跳轉;若是不想要很醜的 hash,咱們能夠用路由的 history 模式,這種模式充分利用 history.pushState API 來完成 URL 跳轉而無須從新加載頁面。
const router = new VueRouter({
mode: 'history',
routes: [...]
})
複製代碼
當你使用 history 模式時,URL 就像正常的 url,例如 http://yoursite.com/user/id
,也好看!
不過這種模式要玩好,還須要後臺配置支持。由於咱們的應用是個單頁客戶端應用,若是後臺沒有正確的配置,當用戶在瀏覽器直接訪問 http://oursite.com/user/id
就會返回 404,這就很差看了。
因此呢,你要在服務端增長一個覆蓋全部狀況的候選資源:若是 URL 匹配不到任何靜態資源,則應該返回同一個 index.html 頁面,這個頁面就是你 app 依賴的頁面。
Vuex 是一個專爲 Vue.js 應用程序開發的狀態管理模式。它採用集中式存儲管理應用的全部組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。
如下是一個完整的vuex理念的簡單示意:
通常爲了邏輯清晰,會按頁面對store進行module的區分,一個完整的module-store以下:
const moduleA = {
state: { ... },
mutations: { . . . },
actions: { ... ),
getters: { ... )
};
複製代碼
使用Vuex進行數據管理是有必定難度的,若是您不打算開發大型單頁應用,使用 Vuex 多是繁瑣冗餘的。確實是如此——若是您的應用夠簡單,您最好不要使用 Vuex。一個簡單的 global event bus就足夠您所需了。可是,若是您須要構建是一箇中大型單頁應用,您極可能會考慮如何更好地在組件外部管理狀態,Vuex 將會成爲天然而然的選擇。
Vue.js 是構建客戶端應用程序的框架。默認狀況下,能夠在瀏覽器中輸出 Vue 組件,進行生成 DOM 和操做 DOM。然而,也能夠將同一個組件渲染爲服務器端的 HTML 字符串,將它們直接發送到瀏覽器,最後將這些靜態標記"激活"爲客戶端上徹底可交互的應用程序。
與傳統 SPA (單頁應用程序 (Single-Page Application)) 相比,服務器端渲染 (SSR) 的優點主要在於:
Nuxt.js十分簡單易用,自然爲Vue而生(Next.js爲React而生);Nuxt.js 是一個基於 Vue.js 的通用應用框架,預設了利用Vue.js開發服務端渲染的應用所須要的各類配置。一個簡單的項目只需將 nuxt 添加爲依賴組件便可,更多細節請戳這裏;
本文整理於【Vue.js實戰】和Vue官方文檔,若有錯誤,敬請雅正😄
更多精彩內容歡迎關注個人公衆號【天道酬勤Lewis】