好用的 Vue 状态管理模式:浅谈 Vuet 在实际应用中解决的问题

2017-08-21 08:54:45 +08:00
 1340641314

父子组件通信

Vuet 提供了模块化的状态管理,通过对一个组件的注入,再向其子组件进行分发,使得我们可以在任何一个子组件,通过模块的方法对当前模块的状态进行更新,再由和 vuet 连接的父组件对子组件进行单向数据流动。这样我们就可以轻易的解决了父子组件的通信问题,也使得状态测试变得异常简单。

状态测试



    import test from 'ava'
    
    // 假设这是我们应用程序的代码 start
    import Vue from 'vue'
    import Vuet from 'vuet'
    
    Vue.use(Vuet)
    
    const vuet = new Vuet({
        modules: {
            test: {
                data() {
                    return {
                        count: 0
                    }
                },
                plus() {
                    this.count++
                },
                delay() {
                    return new Promise((resolve, reject) => {
                        setTimeout(() => {
                            this.count = 1000
                            resolve()
                        }, 100)
                    })
                }
            }
        }
    })
    
    new Vue({
        vuet
    })
    // 假设这是我们应用程序的代码 end
    
    // 接下来我们可以写 vuet 的状态测试
    test('test', async t => {
        const vtm = vuet.getModule('test')
    
        t.is(vtm.count, 0)
    
        vtm.plus()
        t.is(vtm.count, 1)
    
        await vtm.delay()
        t.is(vtm.count, 1000)
    })



上面是一个简单的状态测试的例子,在实际项目中,还应该包含很多 http 请求,我们可以使用axios模块来和服务器进行交互,好处就是它也支持在 node 环境中运行,这样我们编写 http 请求相关的状态测试变成了可能。在如今版本快递迭代的大环境中,写测试几乎变成了一种很稀罕的事情,前端的测试更是少之又少。往往一个页面中,又拆分成很多子组件,这使得测试的工作量成指数级增长,面临着需求的频繁改动而无能为力。而 Vuet 的状态测试更类似于单元测试,和组件的依赖较低,组件只会存在调用 Vuet 模块的方法或者读取状态,在组件频繁的改动中,而 Vuet 的改动相对会较小,所以状态测试便会存在一定的价值。

规则

在生活中,我们每天都会进行着一些重复的工作,比如每天起床之后都会刷牙、洗脸、吃早餐,这些重复而单调的工作,在 Vuet 中则可以教给规则来处理。 比如: 页面 url 发生改变,重新请求一下数据, 模块的状态发生变化时,使用localStorage做持久化处理, 组件初始化时,请求一下数据, 组件销毁时,重置一下状态, 每隔一段时间,帮我请求一下数据, 等等...... 我们可以将这些简单重复的工作,封装成一个规则,然后可以使用这个规则去更新模块的状态



    export default {
      rule ({ path }) {
        return {
          destroyed () {
            this.$vuet.getModule(path).reset()
          }
        }
      }
    }


上面是一个非常简单的例子,它的工作就是在组件销毁时,重置模块的状态,以节省内存的占用。如果需要,我们还可以优化这个规则,在组件初始化时从localStorage中还原状态,在组件销毁时使用localStorage存储状态,然后在重置状态。

总结

Vuet 可以很好的解决了 Vue.js 中组件通信的问题,而且合理的运用规则,可以让我们事半功倍。 Vuet 官网:传送门

3570 次点击
所在节点    分享创造
22 条回复
Hilong
2017-08-21 09:19:26 +08:00
没看懂。。。😂
sirm2z
2017-08-21 09:40:57 +08:00
戳中了原生 vue 的什么痛点~
1340641314
2017-08-21 09:43:59 +08:00
@Hilong 哈哈
jin5354
2017-08-21 09:44:52 +08:00
解决了啥 vuex 没解决的问题?
SourceMan
2017-08-21 09:46:19 +08:00
可以把它跟 vuex 比较吗?
如果可以,它比 vuex 的优势在哪里?
1340641314
2017-08-21 09:52:35 +08:00
@sirm2z
解决了父子通信,
能够有效的实现状态测试,
使用规则更新状态,使得代码更易于维护。
1340641314
2017-08-21 09:54:22 +08:00
@jin5354 vuex 相对于 vuet 写起来更加复杂,除了模块系统之外,还支持规则系统。能将大量相似的操作,封装成规则去驱动模块的更新。
1340641314
2017-08-21 09:58:02 +08:00
@SourceMan vuet 的定位并不是取代 vuex,它是为了减少重复的工作而生,同时它也使用状态的维护变得更简单。相比 vuex 把属性、方法一个个注入到组件中,vuet 更注重将整个模块注入到组件中,更倾向于使用规则来处理模块的更新。
1340641314
2017-08-21 10:03:08 +08:00
假设在一个场景中,我们希望模块的状态更新后,能存储到`localStorage `中,等用户下次访问的时候,还原状态。
如果使用 vuex 实现的话,我们需要在更新状态的同时,使用`localStorage`进行存储,手动使用`localStorage`进行取出。
然而在 vuet 中,它更支持你使用一种规则来定义这个模块的行为,监听模块的改变,自动存储,自动取出。

这是我写的一个[vuet-store]( https://github.com/medatc/vuet/tree/dev/packages/vuet-store),能够更好的理解 vuet 的作用:
1340641314
2017-08-21 10:03:34 +08:00
otakustay
2017-08-21 10:36:34 +08:00
vuex 要用 localStorage 不是应该写个中间件通过特定的 Action (或者所有 Action )来做吗,哪会手动去写代码存储和取出的
1340641314
2017-08-21 11:07:42 +08:00
@otakustay 没有,它只能在一个方法调用时,手动操作。其实我想表达的是,vuet 可以开发一个规则,简单到一个 vuet 模块的状态发生更改,由这个规则去存储和取出。而不是写在调用的方法里面去做操作
xuebi1109
2017-08-21 13:45:13 +08:00
@1340641314 看了 github 的 demo 深刻认同,如果有更加经典的使用场景 demo 的话大家会更有深刻的体会,希望继续维护下去,我准备下个项目试一试,解决的痛点我也认同,确实体验比 vuex 好,不过我担心的就是烂尾问题,希望继续迭代下去, 赞!
1340641314
2017-08-21 14:52:11 +08:00
@xuebi1109 这个现在只是开始,以后会发展成支持 react、vue、小程序。也就是说将业务的状态写在里面,在迁移到各种框架、小程序平台之类的,只需要一个连接器即可。状态的更新后,通知一下 Vue、React 之类的更新页面而已
1340641314
2017-08-21 15:00:10 +08:00
@xuebi1109 如果你觉得有好的经典 demo,可以告诉我,哈哈。表达能力欠佳其实,文章还是没有能够表达我内心深处的想法
codermagefox
2017-08-21 21:32:43 +08:00
我能理解为自动挡的 Vuex 吗?
xuebi1109
2017-08-22 10:06:38 +08:00
@1340641314 弄个好的案例, 写篇文章对比在使用 vuex 的时候是这样的,在对比用 vuet 这样做的话优雅很多,在我看来目前 vuex 要不停的去写 mutation 很繁琐,目前我看来 vuet 还可以将单个功能内聚到一个单例里面之后在移植到其他平台确实牛逼。
1340641314
2017-08-22 10:18:01 +08:00
@xuebi1109 嗯,有道理,这几天有时间的话,就写一篇。接下来有时间,会试着实现 react 版本的 vuet,如果这一步完成了,再接下来就会整合 vue 版本的 vuet 和 react 版本的 vuet,使用连接器对各种框架进行适配
1340641314
2017-08-22 10:19:12 +08:00
@codermagefox 不能,其实和 vuex 很不一样,它们唯一的共同点就是是一个全局的状态管理,未来 vuet 要发展的目标不仅仅只是 vue,而是一个横跨各种框架 js 状态管理模式
1340641314
2017-08-22 10:23:36 +08:00
最终的发展目标,react、vue、微信小程序、支付宝小程序,等等之类,通过 vuet 的连接器,由它们将状态渲染成页面展示给用户,这样有一个非常大的好处就是状态测试变得简单,迁移到各种平台也会变得非常简单。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/384438

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX