路由與Vuex
一. VueRouter
Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,讓構建單頁面應用變得易如反掌。
1.1 安裝
<span style="color:#333333">npm install vue-router --save</span>
1.2 配置路由信息
新建一個文件夾叫做router,然後在裏面定義一個index.js文件,在該文件中配置路由信息:
<span style="color:#333333">import Vue from 'vue'
import Router from 'vue-router'
import Home from '../views/Home.vue'
import About from '../views/About.vue'
Vue.use(Router) //使用插件
export default new Router({
linkActiveClass: 'active', //選中狀態下默認添加的樣式
routes: [
{
path: '/home',
component: Home
},
{
path: '/about',
component: About
},
{
path: '/',
redirect: '/about' //根路徑默認會重定向到/about路徑
}
]
})</span>
1.3 main.js文件中的配置
<span style="color:#333333">import Vue from 'vue'
import App from './App.vue'
import axios from 'axios'
import VueAxios from 'vue-axios'
import Base from './Base.vue'
import router from './router'
Vue.use(VueAxios, axios); //順序有關係
axios.defaults.baseURL = Base.BASE_URL
new Vue({
render: h => h(App),
router
}).$mount('#app')</span>
1.4 訪問與渲染
使用<router-link>
標籤設置路徑,to屬性設置路由路徑:
<span style="color:#333333"><router-link to="/home" class="list-group-item">Home</router-link>
<router-link to="/about" class="list-group-item">About</router-link></span>
使用<router-view>
標籤,將對應的路由組件設置到這個標籤當中:
<span style="color:#333333"><router-view></router-view></span>
1.5 子路由
在路由的配置中使用children來配置子路由。
<span style="color:#333333">children: [
{
path: '/home/game',
component: Games
}
]
</span>
1.6 參數的傳遞
在使用路由的過程中,經常會碰到路由參數的傳遞,那麼傳遞方式大概有三種。
方式一:
<span style="color:#333333">路由配置:
{path:'/user/:id', component:userDetail, props:true}
路由請求:
<span style="color:#117700"><</span><span style="color:#117700">router-link</span> <span style="color:#0000cc">:to</span>=<span style="color:#aa1111">"'/user/' + user.id"</span><span style="color:#117700">></span>{{user.name}}<span style="color:#117700"></</span><span style="color:#117700">router-link</span><span style="color:#117700">></span>
取值:
在userDetail中使用 props: {id: String} 來接收數據</span>
方式二:
<span style="color:#333333">路由配置:
{path:'/user', name:'userDetail', component:userDetail}
路由請求:
<router-link :to="`/user/${user.id}`">{{user.name}}</router-link>
取值:
mounted() {
this.id = this.$route.params.id;
},
watch:{ //監聽路由的變化
$route: {
handler(val) {
this.id = val.params.id;
}
}
}</span>
方式三:
<span style="color:#333333">路由配置:
{path:'/user', name:'userDetail', component:userDetail}
路由請求:
<router-link :to="{path:'/user', query:{id:user.id}}">{{user.name}}</router-link>
取值:
mounted() {
this.id = this.$route.query.id; //用戶刷新的時候有用
},
watch:{ //監聽路由的變化
$route: {
handler(val) {
this.id = val.query.id;
}
}
}</span>
1.7 編程式路由
方式一:
<span style="color:#333333">實現跳轉:
this.$router.push({
path: '/user',
query: {id:id}
});
取值:
mounted() {
this.id = this.$route.query.id;
},
watch:{
$route: {
handler(val) {
this.id = val.query.id;
}
}
}</span>
方式二:
<span style="color:#333333">實現跳轉:
this.$router.push({
path: '/user/45'
});
取值:
props: {
id: String
}</span>
1.8 路由守衛
1.8.1全局路由守衛
在router/index.js中
<span style="color:#333333">router.beforeEach((to,from,next) =>{ //to 路由點位 其中有很多參數
next(); //相當於放行的意思 例如:next({path:'/login'}) //到登錄頁面
});</span>
1.8.2 局部路由守衛(瞭解)
<span style="color:#333333">beforeRouteEnter (to, from, next) {
// 在渲染該組件的對應路由被 confirm 前調用
// 不!能!獲取組件實例 `this`
// 因爲當守衛執行前,組件實例還沒被創建
},
beforeRouteLeave (to, from, next) {
// 導航離開該組件的對應路由時調用
// 可以訪問組件實例 `this`
}</span>
二. vuex
2.1 vuex是什麼
vuex是對vue項目進行狀態管理的js庫,對於所有的組件來說,它是一箇中央存儲,這種模式就保證了只能按照特定的模式來更改狀態。
2.2 vuex的五大核心
state
說的直白點就是存儲數據的地方。
actions
通過異步的方式更改狀態值,但是不能直接更改,需要藉助於mutations來更改。
mutations
通過直接同步的方式更改狀態。
getters
類似於計算屬性,通常是需要通過state來間接計算得到的值。
modules
一個項目中因爲模塊的原因,存在着各種不同的狀態,需要按照模塊來劃分。
2.3 安裝vuex
<span style="color:#333333">npm install vuex --save
</span>
2.4 建立store
新建一個文件夾,名字叫store,在文件夾中新建一個文件,文件名叫index.js,文件內容如下:
<span style="color:#333333">import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
//state
const state = {
todos:[{title:'工作一', complete:true}]
}
// actions
const actions = {
// 第一個參數必須是context, 第二個參數是需要的業務數據
addTodo(context, todo){
// 通過commit的方式提交個mutations, 真正實現對狀態修改的其實是mutations
context.commit('addTodo', todo)
}
}
// getter,類似於計算屬性,需要根據state來計算出其他想要的屬性
const getters = {
completedTodoNumber: state => {
return state.todos.reduce((preTotal, current) => preTotal + (current.complete ? 1 : 0), 0)
}
}
//操作
const mutations = {
//添加待辦事項,第一個參數必須是state, 第二個參數是傳遞過來的數據
addTodo(state, todo) {
state.todos.unshift(todo)
}
}
// 對外暴露Vuex.Store的對象,在其他任何組件中都可以使用 $store來進行操作
export default new Vuex.Store({
state,
mutations,
actions,
getters
})
</span>
2.5 main.js配置
<span style="color:#333333">import Vue from 'vue'
import App from './App.vue'
import store from './store'
new Vue({
store, //引入store
render: h => h(App)
}).$mount("#app");
</span>
2.6 組件中使用
<span style="color:#333333">this.$store.state.todos //獲取狀態值
this.$store.commit('addTodo', todo); //通過mutations中的方法更新狀態
this.$store.dispatch('addTodo', todo); //通過actions中的方法異步更新狀態
this.$store.getters.completedTodoNumber; //獲取getters中的屬性
</span>
2.7 映射函數調用
<span style="color:#333333">import {mapState, mapActions, mapGetters, mapMutations} from 'vuex'
computed: {
...mapState(['todos']), //擴展運算符, 在當前組件中直接使用this的方式調用
...mapGetters(['completedTodoNumber'])
},
methods: {
//引號中的內容爲actions中定義的方法名, 可以直接使用this.addTodo來調用。
...mapActions(['addTodo']),
...mapMutations(['addTodo'])
}
</span>
2.8 Modules
A. 新建一個shopping目錄,目錄下新建index.js文件,文件內容如下:
<span style="color:#333333">const state = {
todos:[{title:'工作一', complete:true}]
}
const actions = {
addTodo(context, todo){
context.commit('addTodo', todo)
},
delDone(context) {
context.commit('delDone')
},
delByIndex(context, index) {
context.commit('delByIndex', index);
}
}
const getters = {
completedTodoNumber: state => {
return state.todos.reduce((preTotal, current) => preTotal + (current.complete ? 1 : 0), 0)
}
}
//操作
const mutations = {
//添加待辦事項
addTodo(state, todo) {
state.todos.unshift(todo)
},
delDone(state) {
state.todos = state.todos.filter(todo => !todo.complete)
},
delByIndex(state, index) {
state.todos.splice(index, 1);
}
}
export default {
state,
actions,
getters,
mutations
}
</span>
B. 在store下的index.js文件中寫入如下內容:
<span style="color:#333333">import Vue from 'vue'
import Vuex from 'vuex'
import shopping from 'shopping'
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
shopping
}
})
</span>
C. 使用
<span style="color:#333333">獲取對應模塊的state值方式一:
...mapState({todos: state=>state.shopping.todos})
獲取對應模塊的state值方式二:
todos: function() {
return this.$store.state.shopping.todos;
}
</span>
至於getters、actions、mutations都被註冊到全局上,和之前的使用方式一樣。