首先这一手骚操作要感谢@ahonn,确实这几天学习dva,我自己都觉得自己有点烦了。但是老哥好耐心,真心感谢。
直接上正题吧不磨磨唧唧的了!
dva是什么
这还用说吗,坦克啊!双命特性,大招是通过机甲自爆产生大范围爆炸,本体只有100血,可以反…啊!!!别打我啊!
好吧可能阿里的工程师也喜欢玩守望先锋,而且我清晰记得dva这个框架就是守望大火的时候诞生的,而且还有一个协同工具叫路霸吧。(看来阿里的工程师都不喜欢当C…)
dva
是针对react
的框架,实际上就是关于redux
的一个封装。首先是让本来很难理解和使用的redux变得相对容易理解和操作。另外一个就是因为数据集中管理,并且推荐使用无状态组件,操作者只需要关心数据的走向。
从dva得到了启示
毕竟阿里前端工程师,Ahonn是真的喜欢阿里的东西…最近跟他聊天也比较深入了解“为什么我们需要dva”。
后来我一个闪念:dva
会不会就是一个数据库模型,实际上redux对我们来说就是一个数据库,前端没有状态,不干涉数据,实际上就是我们常说的只关心增删改查?
那么dva实际上还是对redux
,redux-saga
,redux-thunk
的封装,但对于vue来说简直就是先天优势,因为对于vuex来说已经相当于redux + redux-saga了。从这里也直接萌生了一个想法:vuex + stateless component = 1/2 dva ?
对启示更清晰的思考
首先现在的dva,把数据都封装在model
中,一个model
对应一个redux,state
, reducer
概念得以保留,引入effect
和subscriptions
概念。
首先副作用的目的是,通过异步操作例如网络请求或者一些需要异同步配合的操作,然后去驱使reducer
更新state
,因为在流中,只有reducer
有权利去动state
。subscriptions
就是一个订阅的概念,在我看来就是一个初始化,或者说是一个接受状态的概念。
那么为什么说vuex有先天优势?
// dva model
export default {
namespace: "users",
state: {},
reducers: {},
effects: {},
subscriptions: {}
}
// vuex
export default new Vuex.Store({
modules: {
users: {
namespaced: true,
state: {},
mutations: {},
actions: {}
}
}
})
如果你要无限逼近dva是什么感觉?
// users.js
export default {
namespaced: true,
state: {},
mutations: {},
actions: {}
}
//store.js
export default new Vuex.Store({
modules: {
users
}
})
由于 vue/vuex 对于规则还是相对宽松,但理是理法是法,约定俗成mutations
是用来做同步的工作,可以用来操作state
;actions
用来做异步工作,通知mutations
去操作state
。所以这里是不是就有一种新的概念?
state <=> state
mutation <=> reducer
action <=> effect
_ <=> subscription
对没错,订阅怎么办?
在dva的例子中,看一下示例的订阅是做了什么工作?
subscriptions: {
setup({ dispatch, history }) {
return history.listen(({ pathname, query }) => {
if (pathname === '/users') {
dispatch({ type: 'fetch', payload: query })
}
})
},
}
所以关于这个简单订阅,我们完全可以直接用vue-router
,而其中刚好有一个概念我们可以直接使用 —— 导航守卫
针对vue的操作
老样子,我们是怎么理解dva的model
,就怎么理解vuex的store
。首先state
和reducer
跟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
{
functional: true, // 你只不过是通过这个开关来切换组件状态
methods: {
...mapActions('spacename', {
add: 'create'
})
}
render() {
return <h1>{props.msg}</h1>
}
}
而且在实际使用中,实际上因为vue的概念,你还是没办法在所有组件完全不使用无状态组件(已经除去表单组件)。不过也无伤大雅了。
所以通过这个操作,也能近似的得到了dva的那种感觉。前端的工作只需要直观的反馈你的数据动向和状态,要那么复杂干什么?