Vue 知识点

这是一篇枯燥的知识总结,希望在有需要的时候能够找到它!

Vue-Router

Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。

通过对路由route的判断来设置 active-name,open-names

在使用 menu 组件时,我们需要根据路由的 path 来默认选中某一个 tab,下面给出的就是根据 fullpath 来设置默认 tab 的好方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<Menu ref="left_menu" :theme="theme2" width="auto" active-name="currentPage" :open-names="openedSubmenuArr" accordion @on-select="changeMenu">
……(省略代码)
</Menu>
……(省略代码)
created() {
console.log("router detect:", this.$route);
let path = this.$route.fullPath.match(/^\/(.*)\//);
this.currentPage = this.$route.name;
this.openedSubmenuArr = [].concat(path);
this.$nextTick(() => {
this.$refs.left_menu.updateOpened();
this.$refs.left_menu.updateActiveName()
});
}

要有默认子路由,那父路由的名字 name 得去掉

开发过程中,在配置路由阶段,可能会遇到一下警告提示:

1
2
3
[vue-router] Named Route 'my' has a default child route.
When navigating to this named route (:to="{name: 'my'"), the default child route will not be rendered.
Remove the name from this route and use the name of the default child route for named links instead.

虽然仅仅是警告,不影响功能和显示,但是依然要解决它,避免新的问题产生。警告提示的大概意思是 要有默认子路由,那父路由的名字name得去掉,也就是说在 子路由 里如有有默认路由的话,父路由不需要设置 name 字段。具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
export default new Router({
routes: [
{
path: '/',
name: 'Login',
component: Login
},
{
path: '/admin', // => 注意父路由此处不设置 name 字段
component: Admin,
children: [
{
path: '/', // => 默认路由
redirect: '/admin/index'
}
]
}
]
})

钩子

很多情况下,我们需要在访问某个页面之前,先做一次关于 session 的检查,如果不存在 session 的话,跳转至认证页面,就需要使用如下这个钩子函数。

1
2
3
4
5
6
7
router.beforeEach((to, from, next) => {
if (store.getters.token.length === 0 && to.path !== '/login') {
next('/login')
} else {
next()
}
})

也有很多情况下,比如在加载页面过程中,顶部加载进度条,我们可以根据钩子,在开始加载时加入进度显示,路由结束时隐藏就行。

Vuex

在很多人看来,前端开发的痛点,就是状态管理,页面之间传值会导致代码的高度耦合,在接触 Vue 的过程中,自然是要了解 Vuex 的使用。类似于 redux 和 Mobx 以及 Flux 的概念,具体使用细节只要按照官方文档和教程操作就行。以下记录中间需要注意和了解的知识点:

一个小示例

我们先从一个小示例开始:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import Vuex from 'vuex'
import Vue from 'vue'

Vue.use(Vuex)

export default new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
}
}
})

接着,我们可以在业务方,通过 Action 的 dispatch 方法来调用:

1
this.$store.dispatch('increment', ...)

另外一点需要注意的是,组合 Action 的时候,官方不建议使用异步,但是根据实测结果,异步调用目前没有发现什么问题。

来看一个更加实际的购物车示例,涉及到调用异步 API分发多重 mutation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
actions: {
checkout ({ commit, state }, products) {
// 把当前购物车的物品备份起来
const savedCartItems = [...state.cart.added]
// 发出结账请求,然后乐观地清空购物车
commit(types.CHECKOUT_REQUEST)
// 购物 API 接受一个成功回调和一个失败回调
shop.buyProducts(
products,
// 成功操作
() => commit(types.CHECKOUT_SUCCESS),
// 失败操作
() => commit(types.CHECKOUT_FAILURE, savedCartItems)
)
}

mapState & mapGetters

作为 Vuex 的辅助方法,可以简化我们在业务中对 store 的引用,不必再写很多繁琐的映射。这里有一点需要在意的是:

如果你有使用 modules 使用多个模块,在调用 state 的时候,需要使用 store.state.xxx.yyy,其中 xxx 是模块名,也可以自定义模块名,yyy 就是 state 中定义的字段名;而在使用 getters 的时候,不管存在多少 modules,都是直接使用 store.getters.yyy 的方式来获取。

另外,Vuex 不仅仅提供状态同步和保存,更多时候可以作为 filter 来过滤处理脏数据,业务方无需关心原始数据,通过接口和参数,获取到自己想要的结果。

总结

未完待续。。。

请我喝杯咖啡吧~