一、路由vue-router
後端路由:對於普通的網站,所有的超鏈接都是URL地址,URL地址對應服務器上的資源;
前端路由:對於單頁面應用程序,主要通過URL中的hash(#)來實現頁面跳轉,HTTP請求中不會包含hash相關的內容。
插件下載:https://github.com/vuejs/vue-router,https://unpkg.com/vue-router/dist/vue-router.js
在Vue後面加載vue-router,它會自動安裝。
<script src="lib/vue.js"></script>
<script src="lib/vue-router.js"></script>
1、路由的基本使用
<div id="app">
<!-- 點擊a鏈接,修改url地址,Vue實例上的router監聽到url地址的改變,展示對應組件 -->
<!-- <a href="#/foo">Go To Foo</a> -->
<!-- <a href="#/bar">Go To Bar</a> -->
<!-- <router-link>默認會被渲染成一個<a>標籤,通過傳入to屬性指定鏈接地址 -->
<router-link to="/foo">Go To Foo</router-link>
<router-link to="/bar">Go To Bar</router-link>
<!-- 路由出口,路由匹配到的組件將渲染在這裏 -->
<router-view></router-view>
</div>
<script>
// 1.定義(路由)組件
const Foo={template:'<div>foo</div>'};
const Bar={template:'<div>bar</div>'};
// 2.定義路由
// path:監聽的路由鏈接地址。component:要展示的組件,是一個模板對象,不能是組件名
const routes=[
{path:'/foo',component:Foo},
{path:'/bar',component:Bar}
];
// 3.創建router實例,配置路由
const router=new VueRouter({
routes // 相當於routes:routes
});
// 4.創建Vue實例,註冊路由
const vm=new Vue({
el:'#app',
router // 註冊路由,監聽url地址的變化,展示對應組件
});
</script>
2、重定向和別名
重定向:當用戶訪問/a時,url將會被替換成/b,然後匹配路由爲/b,如用於使根路徑重定向爲顯示某個組件。重定向通過routes配置來完成。
const routes=[
{path:'/',redirect:'/foo'}, // 重定向
{path:'/foo',component:Foo}
];
別名:/a的別名是/b意味着,當用戶訪問/b時,url保持爲/b,但路由匹配爲/a,和訪問/a一樣。
const routes=[
{path:'/a',component:A,alias:'/b'}
];
3、<router-link>
tag:使用tag屬性指定router-link渲染的標籤類型,默認值'a'。還是會監聽點擊,觸發導航。
linkActiveClass:這是路由構造函數中的選項,設置鏈接激活時使用的CSS類名,默認值"router-link-active"。通過該類名可設置路由高亮的樣式。
4、編程式導航
除了使用<router-link>創建a標籤來定義導航鏈接,還可以藉助router的實例方法,通過編寫代碼來實現。
想要導航到不同的URL,使用router.push方法(在Vue實例內部使用this.$router.push),點擊<router-link>時,該方法會在內部調用。
router.push('home') // 字符串
router.push({path:'home'}) // 對象
router.push({name:'user',params:{userId:123}}) // 命名的路由
router.push({path:'register',query:{plan:'private'}}) // 帶查詢參數,變成 /register?plan=private
router.push方法會向history棧添加一個新的記錄,當用戶點擊瀏覽器後退按鈕時,則回到之前的URL。
router.go(n)方法的參數是一個整數,表示在history記錄中向前或者後退多少步,類似window.history.go(n)。
5、路由組件傳參
(1)? & $route.query
使用查詢字符串給路由傳遞參數,不需要修改路由規則的path屬性。
<router-link to="/foo?id=10&name=cong">Go To Foo</router-link>
const foo={
template:'<div>Foo--{{$route.query.id}}--{{$route.query.name}}</div>',
created(){
console.log(this.$route.query.id);
}
}
(2)/ : $route.params
<router-link to="/foo/10/cong">Go To Foo</router-link>
const foo={
template:'<div>Foo--{{$route.params.id}}--{{$route.params.name}}</div>',
created(){
console.log(this.$route.params.id);
}
}
const routes=[
{path:'/foo/:id/:name',component:foo}
];
(3)props
6、嵌套路由
<div id="app">
<router-link to="/user">User</router-link>
<router-view></router-view>
</div>
<template id="user">
<div>
<h3>最高級路由</h3>
<router-link to="/user/profile">Profile</router-link> <!-- 嵌套<router-link> -->
<router-view></router-view> <!-- 嵌套<router-view> -->
</div>
</template>
<script>
const User={
template:'#user'
};
const Profile={ // 嵌套路由的組件
template:'<div>被嵌套的路由</div>'
};
const router=new VueRouter({
routes:[
{
path:'/user',
component:User,
children:[ // 用children定義嵌套路由
{path:'profile',component:Profile} // 沒有/,以/開頭的嵌套路徑會被當作根路徑
]
}
]
});
const vm=new Vue({
el:'#app',
router
});
</script>
7、命名視圖
有時想同級展示多個視圖,而不是嵌套展示。可以在界面中擁有多個單獨命名的視圖,而不是隻有一個單獨的出口。如果router-view沒有設置名字,默認爲default。
一個視圖使用一個組件渲染,因此對於同個路由,多個視圖就需要多個組件。使用components配置(帶上s)。
<div id="app">
<router-view></router-view>
<router-view name="left"></router-view>
<router-view name="main"></router-view>
</div>
<script>
const router=new VueRouter({
routes:[
{path:'/',components:{
default:header,
left:leftBox,
main:mainBox
}
}
]
});
</script>
二、狀態管理vuex
中文官網:https://vuex.vuejs.org/zh/ GitHub:https://github.com/vuejs/vuex
1、狀態管理模式
Vuex是一個專爲Vue.js應用程序開發的狀態管理模式(公共數據管理工具)。它採用集中式存儲管理應用的所有組件的狀態(共享的數據),並以相應的規則保證狀態以一種可預測的方式發生變化(整個程序中的任何組件直接獲取或修改公共數據)。
// 組件
new Vue({
// state
data(){
return {
count:0
}
},
// view
template:`<div>{{count}}</div>`,
// actions
methods:{
increment(){
this.count++
}
}
})
狀態自管理應用(組件)包含:state,驅動應用的數據源;view,以聲明方式將state映射到視圖;actions,響應在view上的用戶輸入導致的狀態變化。但是,當應用遇到多個組件共享狀態時,單向數據流的簡潔性很容易被破壞,如多個視圖依賴於同一狀態(傳參繁瑣)、來自不同視圖的行爲需要變更同一狀態。
把組件的共享狀態抽取出來,以一個全局單例模式管理,任何組件都能獲取狀態或者觸發行爲。
雖然Vuex可以幫助管理共享狀態,但也附帶了更多的概念和框架。如果不打算開發大型單頁應用,使用Vuex可能是繁瑣冗餘的,一個簡單的store模式就足夠了。但如果需要構建一箇中大型單頁應用,更好地在組件外部管理狀態則需要Vuex 。
2、安裝與創建store
在Vue之後引入vuex會進行自動安裝。
Vuex依賴Promise,如果瀏覽器並沒有實現Promise(如IE),可以使用一個polyfill的庫(es6-promise),可以通過CDN將其引入,之後window.Promise會自動可用。
<script src="/path/to/vue.js"></script>
<script src="/path/to/vuex.js"></script>
<script src="https://cdn.jsdelivr.net/npm/es6-promise@4/dist/es6-promise.auto.js"></script>
每一個Vuex應用的核心是store(倉庫),基本上是一個容器,包含着應用中大部分的狀態 (state)。Vuex使用單一狀態樹,用一個對象就包含了全部的應用層級狀態,作爲一個“唯一數據源 (SSOT)”而存在。每個應用僅包含一個store實例。
Vuex和單純的全局對象不同,vuex的狀態存儲是響應式的,若store中的狀態發生變化,相應的組件也會得到高效更新;改變store中的狀態的唯一途徑是顯式地提交(commit)mutation,爲了更明確地追蹤到狀態的變化。
創建一個store,僅提供一個初始state對象和一些mutation、getters。
在根實例中註冊store選項,可將狀態從根組件注入到每一個子組件中(需調用Vue.use(Vuex)),子組件通過this.$store訪問。
const store=new Vuex.Store({
state:{
count:0
},
mutations:{
increment(state){
state.count++
}
},
getters:{
optCount:state=>{
return 'count值是:'+state.count
}
}
})
const vm=new Vue({
el:"#app",
store // 將store掛載到vm實例,任何組件都可以使用store存儲訪問數據
})
console.log(store.state.count);
store.commit('increment')
console.log(store.getters.optCount);
3、核心概念
(1)state
store.state獲取狀態對象。由於store中的狀態是響應式的,在組件中調用store中的狀態僅需要在計算屬性中返回即可,當然也可以用在函數中,等。
mapState輔助函數:用於一個組件獲取多個狀態,可省略store。單獨構建的版本中輔助函數爲Vuex.mapState。
import {mapState} from 'vuex'
export default{
computed:mapState({
count:state=>state.count,
// 簡寫爲count:'count'
// 簡寫爲'count' 計算屬性名稱與state的子節點名稱相同時,給mapState傳一個字符串即可
// 傳字符串參數 'count' 等同於 `state => state.count`
// 爲了使用this獲取局部狀態,必須使用常規函數,不能簡寫
countPlusLocalState(state){
return state.count+this.localCount
}
})
}
對象展開運算符:mapState函數返回的是一個對象,如果需要與局部計算屬性混合使用,可使用對象展開運算符。
computed:{
localComputed(){},
...mapState({ // 使用對象展開運算符將此對象混入到外部對象中
// ...
})
}
(2)mutation
mutation非常類似於事件,每個mutation都有一個字符串的事件類型和一個回調函數。回調函數進行狀態更改,接受state作爲第一個參數。第二個參數可選,是mutation的載荷,應該是一個對象,可以包含多個字段且更易讀。
store.commit('事件類型')方法觸發狀態變更。
store.commit('increment',{ // 方式1
amount:10
})
store.commit({ // 方式2
type:'increment',
amount:10
})
(3)getter
在store中定義getter,可以認爲是store的計算屬性,getter的返回值會根據它的依賴被緩存起來,且只有當它的依賴值發生了改變纔會被重新計算。
Getter接受state作爲其第一個參數,可以接受其它getter作爲第二個參數。
通過store.getters對象,可以以屬性的形式訪問這些值,作爲Vue的響應式系統的一部分緩存其中。在對store裏的數組進行查詢時,也可以通過讓getter返回一個函數實現給getter傳參,通過方法訪問時,每次都會去進行調用,而不會緩存結果。
getters:{
// ...
getTodoById:(state)=>(id)=>{
return state.todos.find(todo=>todo.id===id)
}
}
store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }
(4)action
(5)module
三、服務端渲染
待更新。。。