vuex是什么?
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
为什么要用vuex?
1.进行统一的状态管理,解决不同组件共享数据的问题。
2.不同视图需要变更同一状态的问题。
3.使用vuex之后,状态变化更加清晰
如何使用vuex?
1.安装引入 npm install vuex --save
2.注册到vue中
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
3.实例化vuex的store
export default new Vuex.Store({
state: {},
getters: {},
mutations: {},
actions: {},
modules: {}
})
4.挂载在vue实例上
new Vue({
store,
render: h => h(App)
}).$mount('#app')
5.在组件中就可以通过this.$store对vuex进行操作。
state 存放初始数据
state: {
count: 1
},
- 组件中去取state的值,通过this.$store.state
- 或者可以通过计算属性取得,mapState辅助函数,可以简化操作:
import {mapState} from "vuex";
computed: {
...mapState({
// 传字符串参数 'count' 等同于 `state => state.count`
count: 'count',
// 箭头函数可使代码更简练
count: state => state.count,
})
},
getters 对state中的数据进行初加工(派生),类似vue中的computed,进行缓存
state: {
arr: [1, 2, 3, 4]
},
getters: {
// 参数一:state 参数二:其他 getter
changeArr(state,getters) {
return state.arr.map(item => item + 1)
}
},
注意,getter 在通过属性访问时是作为 Vue 的响应式系统的一部分缓存其中的。
- 取getters中的值,通过this.$store.getters,
- 或者通过计算属性取,getters也有辅助函数mapGetters, 用法和mapState一致。
import {mapGetters} from 'vuex'
// 1、
...mapGetters([
'changeCount',
// ...
])
// 2、
...mapGetters({
changeCount: 'changeCount'
// ...
})
mutations 更改 Vuex 的 store 中的状态的唯一方法是提交 mutation 同步修改
//定义mutation
state: {
count: 1,
},
mutations: {
// 参数一:state 参数二:传入额外的参数
increment(state, payload) {
state.count = payload.count
},
},
//调用mutation
// 1、普通方式
this.$store.commit('increment', {count: 10})
// 2、对象风格的提交方式
this.$store.commit({
type: 'increment',
count: 10
})
- 在组件中提交 Mutation
你可以在组件中使用 this.$store.commit(‘xxx’) 提交 mutation,或者使用 mapMutations 辅助函数将组件中的 methods 映射为 store.commit 调用(需要在根节点注入 store)。
import { mapMutations } from 'vuex'
methods:{
...mapMutations([
'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment', {count: 10})`
]),
...mapMutations({
add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')`
}),
},
this.increment({count: 10})
this.add({count: 10})
actions action类似于mutation,不同的是action可以包含异步操作 action不能直接修改state,如果想修改state的话,需要触发mutation
//定义action
state: {
count: 0
},
mutations: {
increment (state,payload) {
state.count = payload.count
}
},
actions: {
// 第一个参数通过context(上下文环境)可以触发mutation,触发action,获取state、getter等操作
// 第二个参数就是我们传递过来的参数
incrementAsync(context, payload) {
setTimeout(() => {
context.commit('increment', payload)
}, 1000);
}
}
//调用action
// 1、普通方式
this.$store.dispatch('incrementAsync', {count: 10})
// 以对象形式分发
this.$store.dispatch({
type: 'incrementAsync',
count: 10
})
在组件中提交 action
你在组件中使用 this.$store.dispatch(‘xxx’) 分发 action,或者使用 mapActions 辅助函数将组件的 methods 映射为 store.dispatch 调用(需要先在根节点注入 store):
import { mapActions } from 'vuex'
methods: {
...mapActions([
'incrementAsync', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment', {count: 10})`
]),
...mapActions({
add: 'incrementAsync' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
}),
},
this.incrementAsync({count: 10})
this.add({count: 10})
modules
定义module
// index.js中手动引入modules
import app from './modules/app'
modules: {
app
}
<!-- app.js -->
const app = {
state: {
num: 10
},
// 默认state就是有命名空间,
// 如果想给mutation和action也加上命名空间的话,这里设置模块的namespaced:true
getters: {},
mutations: {
changeNum(state, payload) {
state.num = payload.num
}
},
actions: {}
}
export default app
调用module
// 使用命名空间
this.$store.commit("app/changeNum", {num: 10})
// 未使用
this.$store.commit("changeNum", {num: 10})
vuex持久化存储
在开发的过程中, vuex数据刷新页面会初始化。像用户信息(名字,头像,token)需要vuex中存储且需要浏览器本地存储来实现持久化存储。
安装 npm install vuex-persistedstate --save
引入 import createPersistedState from ‘vuex-persistedstate’
使用
export default new Vuex.Store({
plugins: [
createPersistedState(),
],
// 默认存储到localStorage,如果想要存储到sessionStorage,配置如下
plugins: [
// 把vuex的数据存储到sessionStorage
createPersistedState({
storage: window.sessionStorage,
}),
],
// 持久化所有的state,如果想要存储指定的state,配置如下
plugins: [
// 把vuex的数据存储到sessionStorage
createPersistedState({
storage: window.sessionStorage,
reducer(val) {
return {
// 只存储state中的count
count: val.count
}
}
}),
],
})
导航守卫(路由守卫)
什么是导航守卫
vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。这里有很多方式植入路由导航中:全局的,单个路由独享的,或者组件级的。
全局前置守卫
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/about',
name: 'about',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
}
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
router.beforeEach((to, from,next) => {
// ...
// 返回 false 以取消导航
return false
})
当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于等待中。
每个守卫方法接收三个参数:
to: 即将要进入的目标
from: 当前导航正要离开的路由
next:next 是函数
注意:确保 next 函数在任何给定的导航守卫中都被严格调用一次。它可以出现多于一次,但是只能在所有的逻辑路径都不重叠的情况下,否则钩子永远都不会被解析或报错
全局后置钩子
你也可以注册全局后置钩子,然而和守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身:
router.afterEach((to, from, failure) => {
// console.log(failure)
console.log(to,from,failure)
})
// 它们对于分析、更改页面标题、声明页面等辅助功能以及许多其他事情都很有用。
路由独享的守卫
你可以在路由配置上直接定义 beforeEnter 守卫:这些守卫与全局前置守卫的方法参数是一样的。
const router = new VueRouter({
routes: [
{
path: '/about',
component: About,
beforeEnter: (to, from, next) => {
// ...再进入当前路由之前要发生的事
}
// 路由元信息,作标识用(当路径path太长,可以用meta)
meta:{
isLogin:true
}
}
]
})
路由标识meta