首先这一手骚操作要感谢@ahonn,确实这几天学习dva,我自己都觉得自己有点烦了。但是老哥好耐心,真心感谢。

直接上正题吧不磨磨唧唧的了!

dva是什么

这还用说吗,坦克啊!双命特性,大招是通过机甲自爆产生大范围爆炸,本体只有100血,可以反…啊!!!别打我啊!

好吧可能阿里的工程师也喜欢玩守望先锋,而且我清晰记得dva这个框架就是守望大火的时候诞生的,而且还有一个协同工具叫路霸吧。(看来阿里的工程师都不喜欢当C…)

dva是针对react的框架,实际上就是关于redux的一个封装。首先是让本来很难理解和使用的redux变得相对容易理解和操作。另外一个就是因为数据集中管理,并且推荐使用无状态组件,操作者只需要关心数据的走向。

从dva得到了启示

毕竟阿里前端工程师,Ahonn是真的喜欢阿里的东西…最近跟他聊天也比较深入了解“为什么我们需要dva”。

后来我一个闪念:dva会不会就是一个数据库模型,实际上redux对我们来说就是一个数据库,前端没有状态,不干涉数据,实际上就是我们常说的只关心增删改查?

那么dva实际上还是对reduxredux-sagaredux-thunk的封装,但对于vue来说简直就是先天优势,因为对于vuex来说已经相当于redux + redux-saga了。从这里也直接萌生了一个想法:vuex + stateless component = 1/2 dva ?

对启示更清晰的思考

首先现在的dva,把数据都封装在model中,一个model对应一个redux,state, reducer概念得以保留,引入effectsubscriptions概念。

首先副作用的目的是,通过异步操作例如网络请求或者一些需要异同步配合的操作,然后去驱使reducer更新state,因为在流中,只有reducer有权利去动statesubscriptions就是一个订阅的概念,在我看来就是一个初始化,或者说是一个接受状态的概念。

那么为什么说vuex有先天优势?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// dva model
export default {
namespace: "users",
state: {},
reducers: {},
effects: {},
subscriptions: {}
}

// vuex
export default new Vuex.Store({
modules: {
users: {
namespaced: true,
state: {},
mutations: {},
actions: {}
}
}
})

如果你要无限逼近dva是什么感觉?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// users.js
export default {
namespaced: true,
state: {},
mutations: {},
actions: {}
}

//store.js
export default new Vuex.Store({
modules: {
users
}
})

由于 vue/vuex 对于规则还是相对宽松,但理是理法是法,约定俗成mutations是用来做同步的工作,可以用来操作stateactions用来做异步工作,通知mutations去操作state。所以这里是不是就有一种新的概念?

1
2
3
4
5
state <=> state
mutation <=> reducer
action <=> effect

_ <=> subscription

对没错,订阅怎么办?

在dva的例子中,看一下示例的订阅是做了什么工作?

1
2
3
4
5
6
7
8
9
subscriptions: {
setup({ dispatch, history }) {
return history.listen(({ pathname, query }) => {
if (pathname === '/users') {
dispatch({ type: 'fetch', payload: query })
}
})
},
}

所以关于这个简单订阅,我们完全可以直接用vue-router,而其中刚好有一个概念我们可以直接使用 —— 导航守卫

针对vue的操作

老样子,我们是怎么理解dva的model,就怎么理解vuex的store。首先statereducer跟vuex的定义是完全对等的,不需要多理解。effects是使用generator函数来解决异同步问题的,那好办啊,都2018年了,我们直接用async/await就行了。而且我们之前关于api都是使用promise,而且用的也是axios,所以这部分可以说是无缝切换。

那么关于订阅,直接使用vue-router的导航守卫对路由监控,另外在必要的时候还能使用meta。当然导航守卫并不是只能用在全局上,也可以注入到组件中,所以我们注入到页面组件即可。

接下来就是无状态组件问题了,vue默认是状态组件,而且无状态组件也没有react来的方便。

react想要无状态组件,无非就是一个函数就结束战斗了。vue也有一个概念叫函数式组件,也就是无状态,这种组件在使用上就已经不是很方便了。

vue的函数式组件就必须使用render函数不能用template模板,一直到vue2.5才可以在<template functional>使用。但我尝试了一下,手感并不好,所以还是只能用 jsx + vue 这种搭配来操作。不过vue的无状态组件也不像react那么好理解,它依然是一个Object

1
2
3
4
5
6
7
8
9
10
11
{
functional: true// 你只不过是通过这个开关来切换组件状态
methods: {
...mapActions('spacename', {
add: 'create'
})
}
render() {
return <h1>{props.msg}</h1>
}
}

而且在实际使用中,实际上因为vue的概念,你还是没办法在所有组件完全不使用无状态组件(已经除去表单组件)。不过也无伤大雅了。

所以通过这个操作,也能近似的得到了dva的那种感觉。前端的工作只需要直观的反馈你的数据动向和状态,要那么复杂干什么?