Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。包含的功能有:css
用 Vue.js + Vue Router 建立单页应用,是很是简单的。使用 Vue.js ,咱们已经能够经过组合组件来组成应用程序,当你要把 Vue Router 添加进来,咱们须要作的是,将组件 (components) 映射到路由 (routes),而后告诉 Vue Router 在哪里渲染它们html
安装vue
npm i vue-router -S
ios在main.js中vue-router
import Vue from 'vue' import VueRouter from 'vue-router' Vue.use(VueRouter) 复制代码
推荐使用:vue add router 添加插件(记得提早提交)vuex
router.jsnpm
import Vue from 'vue'
//1.导入
import Router from 'vue-router'
import Home from './views/Home.vue'
import About from './views/About.vue'
//2.模块化机制 使用Router
Vue.use(Router)
//3.建立路由器对象
const router = new Router({
routes:[{
path: '/home',
component: Home
},
{
path: '/about',
component: About
}
]
})
export default router;
复制代码
main.js编程
import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
new Vue({
// 4.挂载根实例
router,
render: h => h(App)
}).$mount('#app')
复制代码
作好以上配置以后json
App.vueaxios
<template>
<div id="app">
<div id="nav">
<!-- 使用router-link组件来导航 -->
<!-- 经过传入to属性指定链接 -->
<!-- router-link默认会被渲染成一个a标签 -->
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link> |
</div>
<!-- 路由出口 -->
<!-- 路由匹配的组件将被渲染到这里 -->
<router-view/>
</div>
</template>
复制代码
打开浏览器.,切换Home和About超连接,查看效果
在配置路由的时候,给路由添加名字,访问时就能够动态的根据名字来进行访问
const router = new Router({
routes:[{
path: '/home',
name:"home",
component: Home
},
{
path: '/about',
name:'about'
component: About
}
]
})
复制代码
要连接到一个命名路由,能够给 router-link
的 to
属性传一个对象:
<router-link :to="{name:'home'}">Home</router-link> |
<router-link :to="{name:'about'}">About</router-link> |
复制代码
咱们常常须要把某种模式匹配到的全部路由,全都映射到同个组件。例如,咱们有一个 User
组件,对于全部 ID 各不相同的用户,都要使用这个组件来渲染。那么,咱们能够在 vue-router
的路由路径中使用“动态路径参数”(dynamic segment) 来达到这个效果
User.vue
<template>
<div>
<h3>用户页面</h3>
</div>
</template>
<script>
export default {
};
</script>
<style lang="scss" scoped>
</style>
复制代码
路由配置
const router = new Router({
routes:[
{
path: '/user/:id',
name: 'user',
component: User,
},
]
})
复制代码
<router-link :to="{name:'user',params:{id:1}}">User</router-link> |
复制代码
访问
查看效果
当匹配到路由时,参数值会被设置到this.$route.params,能够在每一个组件中使用,因而,咱们能够更新 User
的模板,输出当前用户的 ID:
<template>
<div>
<h3>用户页面{{$route.params.id}}</h3>
</div>
</template>
复制代码
提醒一下,当使用路由参数时,例如从 /user/1 导航到
/user/2`,原来的组件实例会被复用。由于两个路由都渲染同个组件,比起销毁再建立,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用。
复用组件时,想对路由参数的变化做出响应的话,你能够简单地 watch (监测变化) $route
对象:
/*使用watch(监测变化) $route对象 watch: { $route(to, from) { console.log(to.params.id); } }, */
// 或者使用导航守卫
beforeRouteUpdate(to,from,next){
//查看路由的变化
//必定要调用next,否则就会阻塞路由的变化
next();
}
复制代码
const router = new Router({
routes:[
//....
// 匹配不到理由时,404页面显示
{
path: '*',
component: () => import('@/views/404')
}
]
})
复制代码
当使用通配符路由时,请确保路由的顺序是正确的,也就是说含有通配符的路由应该放在最后。路由 { path: '*' }
一般用于客户端 404 错误
当使用一个通配符时,$route.params
内会自动添加一个名为 pathMatch
参数。它包含了 URL 经过通配符被匹配的部分:
{
path: '/user-*',
component: () => import('@/views/User-admin.vue')
}
this.$route.params.pathMatch // 'admin'
复制代码
有时候,同一个路径能够匹配多个路由,此时,匹配的优先级就按照路由的定义顺序:谁先定义的,谁的优先级就最高。
相似像地址上出现的这种:http://localhos:8080/page?id=1&title=foo
const router = new Router({
routes:[
//....
{
name:'/page',
name:'page',
component:()=>import('@/views/Page.vue')
}
]
})
复制代码
<router-link :to="{name:'page',query:{id:1,title:'foo'}}">User</router-link> |
复制代码
访问http://localhos:8080/page?id=1&title=foo查看Page
Page.vue
<template>
<div>
<h3>Page页面</h3>
<h3>{{$route.query.userId}}</h3>
</div>
</template>
<script>
export default {
created () {
//查看路由信息对象
console.log(this.$route);
},
}
</script>
<style lang="scss" scoped>
</style>
复制代码
例子是从 /
重定向到 /home
:
const router = new Router({
mode: 'history',
routes: [
// 重定向
{
path: '/',
redirect: '/home'
}
{
path: '/home',
name: 'home',
component: Home
},
]
})
复制代码
重定向的目标也能够是一个命名的路由:
const router = new VueRouter({
routes: [
{ path: '/', redirect: { name: 'name' }}
]
})
复制代码
别名
{
path: '/user/:id',
name: 'user',
component: User,
alias: '/alias'
}
复制代码
起别名,仅仅起起别名 用户访问http://loacalhost:8080/alias的时候,显示User组件
别名”的功能让你能够自由地将 UI 结构映射到任意的 URL,而不是受限于配置的嵌套路由结构。
在组件中使用 $route
会使之与其对应路由造成高度耦合,从而使组件只能在某些特定的 URL 上使用,限制了其灵活性。
使用 props
将组件和路由解耦:
取代与 $route 的耦合
{
path: '/user/:id',
name: 'user',
component: User,
props:true
},
复制代码
User.vue
<template>
<div>
<h3>用户页面{{$route.params.id}}</h3>
<h3>用户页面{{id}}</h3>
</div>
</template>
<script>
export default{
//....
props: {
id: {
type: String,
default: ''
},
},
}
</script>
复制代码
props也能够是个函数
{
path: '/user/:id',
name: 'user',
component: User,
props: (route)=>({
id: route.params.id,
title:route.query.title
})
}
复制代码
User.vue
<template>
<div>
<h3>用户页面{{id}}-{{title}}</h3>
</div>
</template>
<script>
export default {
// ...
props: {
id: {
type: String,
default: ''
},
title:{
type:String
}
},
};
</script>
复制代码
除了使用 <router-link>
建立 a 标签来定义导航连接,咱们还能够借助 router 的实例方法,经过编写代码来实现。
注意:在 Vue 实例内部,你能够经过 router 访问路由实例。所以你能够调用 this.router.push。
声明式 | 编程式 |
---|---|
<router-link :to="..."> |
router.push(...) |
该方法的参数能够是一个字符串路径,或者一个描述地址的对象。例如
// 字符串
this.$router.push('home')
// 对象
this.$router.push({ path: 'home' })
// 命名的路由
this.$router.push({ name: 'user', params: { userId: '123' }})
// 带查询参数,变成 /register?plan=private
this.$.push({ path: 'register', query: { plan: 'private' }})
复制代码
前进后退
// 在浏览器记录中前进一步,等同于 history.forward()
router.go(1)
// 后退一步记录,等同于 history.back()
router.go(-1)
// 前进 3 步记录
router.go(3)
// 若是 history 记录不够用,那就默默地失败呗
router.go(-100)
router.go(100)
复制代码
实际生活中的应用界面,一般由多层嵌套的组件组合而成。一样地,URL 中各段动态路径也按某种结构对应嵌套的各层组件
/user/1/profile /user/1/posts
+------------------+ +-----------------+
| User | | User |
| +--------------+ | | +-------------+ |
| | Profile | | +------------> | | Posts | |
| | | | | | | |
| +--------------+ | | +-------------+ |
+------------------+ +-----------------+
复制代码
router.js
{
path: '/user/:id',
name: 'user',
component: User,
props: ({params,query})=>({
id: params.id,
title:query.title
}),
children:[
// 当 /user/:id/profile 匹配成功,
// Profile 会被渲染在 User 的 <router-view> 中
{
path:"profile",
component: Profile
},
// 当 /user/:id/posts 匹配成功,
// Posts 会被渲染在 User 的 <router-view> 中
{
path: "posts",
component: Posts
}
]
}
复制代码
在 User
组件的模板添加一个 <router-view>
:
<template>
<div>
<h3>用户页面{{$route.params.id}}</h3>
<h3>用户页面{{id}}</h3>
<router-view></router-view>
</div>
</template>
复制代码
App.vue
<template>
<div id='app'>
<!-- 嵌套理由 -->
<router-link to="/user/1/profile">User/profile</router-link> |
<router-link to="/user/1/posts">User/posts</router-link> |
</div>
</template>
复制代码
有时候想同时 (同级) 展现多个视图,而不是嵌套展现,例如建立一个布局,有 sidebar
(侧导航) 和 main
(主内容) 两个视图,这个时候命名视图就派上用场了
{
path: '/home',
name: 'home',
//注意这个key是components
components: {
default: Home, //默认的名字
main: ()=>import('@/views/Main.vue'),
sidebar: () => import('@/views/Sidebar.vue')
}
},
复制代码
App.vue
<router-view/>
<router-view name='main'/>
<router-view name='sidebar'/>
复制代码
“导航”表示路由正在发生改变。
beforeEach
守卫。beforeRouteUpdate
守卫 (2.2+)。beforeEnter
。beforeRouteEnter
。beforeResolve
守卫 (2.5+)。afterEach
钩子。beforeRouteEnter
守卫中传给 next
的回调函数。你可使用router.beforeEach
注册一个全局前置守卫
const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
// ...
})
复制代码
有个需求,用户访问在浏览网站时,会访问不少组件,当用户跳转到/notes
,发现用户没有登陆,此时应该让用户登陆才能查看,应该让用户跳转到登陆页面,登陆完成以后才能够查看个人笔记的内容,这个时候全局守卫起到了关键的做用
有两个路由 /notes
和/login
router.vue
const router = new VueRouter({
routes:[
{
path: '/notes',
name: 'notes',
component: () => import('@/views/Notes')
},
{
path: "/login",
name: "login",
component: () => import('@/views/Login')
},
]
})
// 全局守卫
router.beforeEach((to, from, next) => {
//用户访问的是'/notes'
if (to.path === '/notes') {
//查看一下用户是否保存了登陆状态信息
let user = JSON.parse(localStorage.getItem('user'))
if (user) {
//若是有,直接放行
next();
} else {
//若是没有,用户跳转登陆页面登陆
next('/login')
}
} else {
next();
}
})
复制代码
Login.vue
<template>
<div>
<input type="text" v-model="username">
<input type="password" v-model="pwd">
<button @click="handleLogin">提交</button>
</div>
</template>
<script>
export default {
data() {
return {
username: "",
pwd: ""
};
},
methods: {
handleLogin() {
// 1.获取用户名和密码
// 2.与后端发生交互
setTimeout(() => {
let data = {
username: this.username
};
//保存用户登陆信息
localStorage.setItem("user", JSON.stringify(data));
// 跳转个人笔记页面
this.$router.push({ name: "notes" });
}, 1000);
},
}
};
</script>
复制代码
App.vue
<!-- 全局守卫演示 -->
<router-link to="/notes">个人笔记</router-link> |
<router-link to="/login">登陆</router-link> |
<button @click="handleLogout">退出</button>
复制代码
export default {
methods: {
handleLogout() {
//删除登陆状态信息
localStorage.removeItem("user");
//跳转到首页
this.$router.push('/')
}
},
}
复制代码
你能够在路由组件内直接定义如下路由导航守卫:
beforeRouteEnter
beforeRouteUpdate
(2.2 新增)beforeRouteLeave
<template>
<div>
<h3>用户编辑页面</h3>
<textarea name id cols="30" rows="10" v-model="content"></textarea>
<button @click="saveData">保存</button>
<div class="wrap" v-for="(item,index) in list" :key="index">
<p>{{item.title}}</p>
</div>
</div>
</template>
<script>
export default {
data() {
return {
content: "",
list: [],
confir: true
};
},
methods: {
saveData() {
this.list.push({
title: this.content
});
this.content = "";
}
},
beforeRouteLeave(to, from, next) {
// 导航离开该组件的对应路由时调用
// 能够访问组件实例 `this`
if (this.content) {
alert("请确保保存信息以后,再离开");
next(false);
} else {
next();
}
}
};
</script>
复制代码
给须要添加权限的路由设置meta字段
{
path: '/blog',
name: 'blog',
component: () => import('@/views/Blog'),
meta: {
requiresAuth: true
}
},
{
// 路由独享的守卫
path: '/notes',
name: 'notes',
component: () => import('@/views/Notes'),
meta: {
requiresAuth: true
}
},
复制代码
// 全局守卫
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
// 须要权限
if(!localStorage.getItem('user')){
next({
path:'/login',
query:{
redirect:to.fullPath
}
})
}else{
next();
}
} else {
next();
}
})
复制代码
login.vue
//登陆操做
handleLogin() {
// 1.获取用户名和密码
// 2.与后端发生交互
setTimeout(() => {
let data = {
username: this.username
};
localStorage.setItem("user", JSON.stringify(data));
// 跳转到以前的页面
this.$router.push({path: this.$route.query.redirect });
}, 1000);
}
复制代码
有时候,进入某个路由后,须要从服务器获取数据。例如,在渲染用户信息时,你须要从服务器获取用户的数据。咱们能够经过两种方式来实现:
当你使用这种方式时,咱们会立刻导航和渲染组件,而后在组件的 created
钩子中获取数据。这让咱们有机会在数据获取期间展现一个 loading 状态,还能够在不一样视图间展现不一样的 loading 状态。
<template>
<div class="post">
<div v-if="loading" class="loading">Loading...</div>
<div v-if="error" class="error">{{ error }}</div>
<div v-if="post" class="content">
<h2>{{ post.title }}</h2>
<p>{{ post.body }}</p>
</div>
</div>
</template>
复制代码
export default {
name: "Post",
data() {
return {
loading: false,
post: null,
error: null
};
},
// 组件建立完后获取数据,
// 此时 data 已经被 监视 了
created() {
// 若是路由有变化,会再次执行该方法
this.fetchData();
},
watch: {
$route: "fetchData"
},
methods: {
fetchData() {
this.error = this.post = null;
this.loading = true;
this.$http.get('/api/post')
.then((result) => {
this.loading = false;
this.post = result.data;
}).catch((err) => {
this.error = err.toString();
});
}
}
};
复制代码
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的全部组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化
vue add vuex
复制代码
store.js
import Vue from 'vue'
import Vuex from 'vuex'
//确保开头调用Vue.use(Vuex)
Vue.use(Vuex)
export default new Vuex.Store({
state: { //this.$store.state.count
count:0
},
getters:{
evenOrOdd:(state)=>{ //this.$store.getters.evenOrOdd
return state.count % 2 ===0 ? '偶数': '奇数'
}
},
mutations: {
increment(state){ //this.$store.commit('increment')
state.count++
},
decrement(state){ //this.$store.commit('decrement')
state.count--
}
},
actions: {
increment({commit}){ //this.$store.dispatch('increment')
// 修改状态的惟一方式是提交mutation
commit('increment');
},
decrement({ commit }) { //this.$store.dispatch('decrement')
commit('decrement');
},
incrementAsync({commit}){ //this.$store.dispatch('incrementAsync')
return new Promise((resolve, reject) => {
setTimeout(() => {
commit('increment');
resolve(10);
}, 1000);
})
}
}
})
复制代码
咱们能够在组件的某个合适的时机经过this.$store.state
来获取状态对象,以及经过this.$store.commit
方法触犯状态变动
this.$store.commit('increment');
复制代码
当一个组件须要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,咱们可使用 mapState
辅助函数帮助咱们生成计算属性,让你少按几回键
// 在单独构建的版本中辅助函数为 Vuex.mapState
import { mapState } from 'vuex'
export default {
// ...
computed: mapState({
// 箭头函数可以使代码更简练
count: state => state.count,
// 传字符串参数 'count' 等同于 `state => state.count`
countAlias: 'count',
// 为了可以使用 `this` 获取局部状态,必须使用常规函数
countPlusLocalState (state) {
return state.count + this.localCount
}
})
}
复制代码
当映射的计算属性的名称与 state 的子节点名称相同时,咱们也能够给 mapState
传一个字符串数组。
computed: mapState([
// 映射 this.count 为 store.state.count
'count'
])
复制代码
对象展开运算符
mapState
函数返回的是一个对象。咱们如何将它与局部计算属性混合使用呢?一般,咱们须要使用一个工具函数将多个对象合并为一个,以使咱们能够将最终对象传给 computed
属性。可是自从有了对象展开运算符,极大地简化写法
computed:{
...mapState({
"count"
})
}
复制代码
mapGetters
辅助函数仅仅是将 store 中的 getter 映射到局部计算属性:
import { mapGetters } from 'vuex'
export default {
// ...
computed: {
...mapGetters([
'evenOrOdd'
])
},
}
复制代码
若是你想将一个 getter 属性另取一个名字,使用对象形式:
mapGetters({
// 把 `this.doneEvenOrOdd` 映射为 `this.$store.getters.evenOrOdd`
doneEvenOrOdd: 'evenOrOdd'
})
复制代码
Mutation
更改 Vuex 的 store 中的状态的惟一方法是提交 mutation。Vuex 中的 mutation 很是相似于事件:每一个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是咱们实际进行状态更改的地方,而且它会接受 state 做为第一个参数:
你能够在组件中使用 this.$store.commit('xxx')
提交 mutation,或者使用 mapMutations
辅助函数将组件中的 methods 映射为 store.commit
调用(须要在根节点注入 store
)。
import { mapMutations } from 'vuex'
export default {
// ...
methods: {
...mapMutations('counter',[
'increment',
'decrement',
]),
}
}
复制代码
Action
Action 相似于 mutation,不一样在于:
import { mapMutations } from 'vuex'
export default {
// ...
methods: {
...mapActions('counter',[
'incrementAsync'
])
}
}
复制代码
提交方式
//在组件内部
// 以载荷形式分发
this.$store.dispatch('incrementAsync', {
amount: 10
})
// 以对象形式分发
this,.$store.dispatch({
type: 'incrementAsync',
amount: 10
})
复制代码
因为使用单一状态树,应用的全部状态会集中到一个比较大的对象。当应用变得很是复杂时,store 对象就有可能变得至关臃肿。
为了解决以上问题,Vuex 容许咱们将 store 分割成模块(module)。每一个模块拥有本身的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行一样方式的分割:
作一个购物车案例
有两个模块cart
和products
建立store文件夹
|---store
├── index.js
└── modules
├── cart.js
└── products.js
复制代码
cart.js
若是但愿你的模块具备更高的封装度和复用性,你能够经过添加 namespaced: true
的方式使其成为带命名空间的模块
当模块被注册后,它的全部 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。
export default {
//使当前模块具备更高的封装度和复用性
namespaced: true,
state: {
...
},
getters: {
...
},
mutations: {
...
},
actions: {
...
},
}
复制代码
products.js
export default {
//使当前模块具备更高的封装度和复用性
namespaced: true,
state: {
...
},
getters: {
...
},
mutations: {
...
},
actions: {
...
},
}
复制代码
index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
import cart from './modules/cart';
import products from './modules/products';
export default new Vuex.Store({
modules:{
cart,
products,
}
})
//this.$store.state.cart //获取cart的状态
//this.$store.state.products //获取products的状态
复制代码
完整购物车案例
mock数据
新建vue.config.js
const products = [
{ id: 1, title: 'iphone11', price: 600, inventory: 10 },
{ id: 2, title: 'iphone11 pro', price: 800, inventory: 5 },
{ id: 3, title: 'iphone11 max', price: 1600, inventory: 6 },
]
module.exports = {
devServer: {
before(app, server) {
app.get('/api/products', (req, res) => {
res.json({
products:products
})
})
}
}
}
复制代码
cart.js
export default {
//使当前模块具备更高的封装度和复用性
namespaced: true,
state: {
items: [],
},
getters: {
//获取购物车中的商品
cartProducts: (state, getters, rootState) => {
return state.items.map(({ id, quantity }) => {
const product = rootState.products.products.find(product => product.id === id)
return {
title: product.title,
price: product.price,
quantity
}
})
},
// 购物车总价格
cartTotalPrice: (state, getters) => {
return getters.cartProducts.reduce((total, product) => {
return total + product.price * product.quantity
}, 0)
}
},
mutations: {
pushProductToCart(state, { id }) {
state.items.push({
id,
quantity: 1
})
},
incrementItemQuantity(state, { id }) {
const cartItem = state.items.find(item => item.id === id);
cartItem.quantity++;
},
},
actions: {
//添加商品到购物车
addProductToCart({ commit, state }, product) {
// 若是有库存
if (product.inventory > 0) {
const cartItem = state.items.find(item => item.id === product.id);
if (!cartItem) {
commit('pushProductToCart', { id: product.id });
} else {
commit('incrementItemQuantity', cartItem);
}
//提交products模块中decrementProductInventory方法
//让商品列表的库存数量减1
commit('products/decrementProductInventory', { id: product.id }, { root: true })
}
}
},
}
复制代码
products.js
import Axios from "axios";
export default {
//使当前模块具备更高的封装度和复用性
namespaced: true,
state: {
products: []
},
getters: {
},
mutations: {
setProducts(state, products) {
state.products = products;
},
//减小商品库存的方法
decrementProductInventory(state, { id }) {
const product = state.products.find(product => product.id === id)
product.inventory--
}
},
actions: {
//获取全部商品的方法
getAllProducts({ commit }) {
Axios.get('/api/products')
.then(res => {
console.log(res.data.products);
commit('setProducts',res.data.products)
})
.catch(err => {
console.log(err);
})
}
},
}
复制代码
Products.vue
<template>
<div>
<h3>商铺</h3>
<ul>
<li v-for='product in products' :key = 'product.id'>
{{product.title}} - {{product.price | currency}}
<br>
<button :disabled='!product.inventory' @click='addProductToCart(product)'>添加到购物车</button>
</li>
</ul>
<hr>
</div>
</template>
<script>
import { mapState,mapActions } from "vuex";
export default {
name: "ProductList",
data() {
return {};
},
computed: {
products(){
return this.$store.state.products.products
}
},
methods: {
...mapActions('cart',[
'addProductToCart'
])
},
created() {
this.$store.dispatch("products/getAllProducts");
}
};
</script>
<style scoped>
</style>
复制代码
Cart.vue
<template>
<div>
<h2>个人购物车</h2>
<i>请增长商品到您的购物车.</i>
<ul>
<li
v-for="product in products"
:key="product.id"
>{{product.title}}-{{product.price | currency}} x {{product.quantity}}
</li>
</ul>
<p>总价格:{{total | currency}}</p>
</div>
</template>
<script>
import { mapGetters,mapState } from "vuex";
export default {
name: "shoppingcart",
computed:{
...mapGetters('cart',{
products:'cartProducts',
total:'cartTotalPrice'
})
}
};
</script>
<style scoped>
</style>
复制代码
Vuex 能够帮助咱们管理共享状态,并附带了更多的概念和框架。这须要对短时间和长期效益进行权衡。
若是您不打算开发大型单页应用,使用 Vuex 多是繁琐冗余的。确实是如此——若是您的应用够简单,您最好不要使用 Vuex。一个简单的 store 模式就足够您所需了。可是,若是您须要构建一个中大型单页应用,您极可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为天然而然的选择。引用 Redux 的做者 Dan Abramov 的话说就是:
Flux 架构就像眼镜:您自会知道何时须要它
日志插件
Vuex 自带一个日志插件用于通常的调试:
import createLogger from 'vuex/dist/logger'
const store = new Vuex.Store({
plugins: [createLogger({
collapsed: false, // 自动展开记录的 mutation
})]
})
复制代码
要注意,logger 插件会生成状态快照,因此仅在开发环境使用。
还有2件事拜托你们
一:求赞 求收藏 求分享 求留言,让更多的人看到这篇内容
二:欢迎添加个人我的微信
备注“资料”, 300多篇原创技术文章,海量的视频资料便可得到
备注“加群”,我会拉你进技术交流群,群里大牛学霸具在,哪怕您作个潜水鱼也会学到不少东西
本文由练识课堂发布!