资讯专栏INFORMATION COLUMN

如何管理 vue 项目中的数据?

starsfun / 2604人阅读

摘要:如何管理项目的数据这个问题似乎早已经有答案了,无非就是使用,全局,整个应用维护一个超大的,界面的显示情况随着超大的变化而变化。

vuex

如何管理 vue 项目的数据?这个问题似乎早已经有答案了,无非就是使用 vuex ,全局 store,整个应用维护一个超大的 Object,界面的显示情况随着超大 Object 的变化而变化。

看起来很简单,不就维护一个 Object 嘛,实际上,要想组织好数据这块代码,必须事先对项目的数据结构理解得非常透彻,然后像设计数据库表一样把各个 module 的样子设计出来。实际上,个人觉得设计 vuex 的 module 比设计数据库表复杂得多:

1、像数据库一样设计各个业务实体的外貌,这部分设计难度应该和数据库表设计差不多;

2、维护一堆 ajax 请求状态;

3、如何优雅地复用 module。比如有一个 PersonListModule,在一个页面上有两处要用到 PersonListModule 中的列表数据:一个是要在表格控件里面展示,一个是要在下拉控件里面展示,每个控件中展示的列表数据筛选条件不一样;

4、如何同步 vuex 中的数据和服务器端数据。vuex 的超大 Object 可以看做服务器端数据在客户端内存中的一个缓存,怎么设计这个缓存的同步策略?

对于3、4两个问题,结合起来更恐怖:同步服务器端数据到 PersonListModule 的同时,还要考虑如何从 PersonListModule 中筛选出分页数据到页面展示,还要筛选出多个列表,还要考虑在什么时机重新更新“缓存”,想想就头大。

假设我们能力很强大,设计出了能完美应对上述问题的 store 方案,还有一个大问题拦着我们呢:如何保证这套设计的可扩展性?因为业务系统变化多端,不知道什么时候产品经理又有新想法了,我们得设计能很好地应对变化多端的需求吗?

为什么这么难?问题究竟出现在哪里?

vuex 的思维模式主要是从数据着手,由数据推导出界面的样子,这就需要先设计好 store 结构了。要设计好 store 结构,目测必须具备如下特质的工程师才能做好:

1、对项目业务了解非常深入;

2、具备超强的抽象思维能力;

3、经验丰富,能尽量想到设计出的 store 结构能应付哪些情况、不能应付哪些情况。

第2条的门槛实在是太高了,能做到的前端工程师估计没多少。

怎么办?

我们不应该从数据推导出界面,而应该从界面推导出数据,逐层抽象。

比如现在要仿一个新浪微博首页,页面上主要包含的数据有:分组信息、微博列表、个人信息、一些推荐信息等,那么就设计一个只针对该页面的 module ,大致结构为:

const homePageModule = {
  state: {
    groupList: [{
        id: 1,
        name: "名人明星",
        unread: 1
      },
      {
        id: 2,
        name: "同事",
        unread: 0
      }
    ],
    groupListExtraInfo: {
      // 初始显示多少个小组
      initShowCount: 5,
      loading: true
    },
    weiboList: [{
      id: 1,
      content: "

震惊部

", author: "yibuyisheng", createTime: "20170719234422" }], weiboListPageInfo: { loadingStatus: "QUIET", // 三种取值:QUIET -> 没有加载;UP -> 向上加载;DOWN -> 向下加载 // weiboList 的开始时间,可用这个时间戳做下一次的向上加载 startTime: "20170719234422", // weiboList 的结束时间,可用这个时间戳做下一次的向下加载 endTime: "20170719234422" }, self: { id: 1, nickname: "yibuyisheng", email: "yibuyisheng@163.com", avatar: "http://weibo.com/2674779523/profile?rightmod=1&wvr=6&mod=personinfo", followedCount: 405, followerCount: 235, weiboCount: 1321 }, recommendMovies: [ ... ], recommendTopics: [ ... ] ... }, mutations: { updateWeiboList(state, list) { ... } }, actions: { appendWeiboList() { ... }, prependWeiboList() { ... } } };

针对这个页面,这个结构,各个处理逻辑就具体化、特殊化了,代码写起来非常轻松。

代码复用?

假设现在有个小组页面,点进去后可以看到该小组所有成员发的微博,因为是一个新的页面,所以需要新起一个 module ,这也意味着要重复写一遍 weiboList 相关的代码,岂不蛋疼!

此时可以考虑写一个 createWeiboListModule() 函数,用于创建这种通用 module ,然后再写一个 mergeModules() 函数,把 createWeiboListModule() 函数创建出来的 module 对象和各页面特殊的 module 合并起来,样子看起来大致是这样:

mergeModules(createWeiboListModule(), {
  state: {
    ...
  },
  mutations: {
    ...
  },
  actions: {
    ...
  }
});

遇到需要复用的才抽取通用逻辑,很自然,很简单。

怎么结合 vue 组件?

上面的结构有一个很大的问题,就是不能很好地和 vue 组件结合。比如,要让微博首页和分组页面中的微博列表能复用 weiboList 相关代码,那么 weiboList 涉及到的 state、action、mutation、getter 的命名都要尽量保持一致,不然就要传一个 nameMap(命名映射)给两个页面通用的 WeiboListComponent 组件,看起来就像这样:

简直蛋疼!

好吧,那就严格约束这两个页面的 state、action、mutation、getter 命名都保持一致吧!

简直超级蛋疼!

此时可以考虑用 namespace 来解决这个问题,比如上面的 homePageModule 可以把 weiboList 拆分出来:

const store = new vuex.Store({
  ...,

  modules: {
    "page:home": {
      state: {
        groupList: [{
            id: 1,
            name: "名人明星",
            unread: 1
          },
          {
            id: 2,
            name: "同事",
            unread: 0
          }
        ],
        groupListExtraInfo: {
          // 初始显示多少个小组
          initShowCount: 5,
          loading: true
        },
        self: {
          id: 1,
          nickname: "yibuyisheng",
          email: "yibuyisheng@163.com",
          avatar: "http://weibo.com/2674779523/profile?rightmod=1&wvr=6&mod=personinfo",
          followedCount: 405,
          followerCount: 235,
          weiboCount: 1321
        },
        recommendMovies: [
          ...
        ],
        recommendTopics: [
            ...
          ]
          ...
      },
    },
    "page:home:weiboList": createWeiboListModule(...)
  }

  ...
});

这样一来,只要给 vue 组件传一个 namespace 参数就行了:

嗯,看起来挺好的!

如何处理“store 缓存”?

可以在上一个问题解决的基础上,加上缓存功能,目测有大把现成的缓存策略可以参考(服务器端都玩儿烂了),由于绝大部分系统并不需要这层缓存功能,所以此处不赘述。

就这样了吗?

上述方案,思维方向的确是导致最后执行起来轻松了很多,从具体到抽象的过程,很自然,符合思考习惯。但是最终的代码还是会很容易搞得很乱的:

1、mergeModules() 要照顾各种合并策略;

2、createXXXModule() 方法会抽出很多层。比如可以从 createWeiboListModule() 抽出来 createContinuousListModule() ,用于构造通用的具备“向前向后”加载能力的列表 Module,最终可能会形成一条常常的“继承链”,需要自己去定义维护这套继承逻辑,心累。

其实上面两条一看,就知道有现成的解决方案了: class。

参考此处实现:https://github.com/yibuyishen...(代码还在完善中)。

具体业务代码写起来就像是这样了:

class ContinuousList extends BaseModule {
    state = {
        list: [],
        pageInfo: {
            loadingStatus: "QUIET",
            startTime: "20170720003939",
            endTime: "20170720003939"
        }
    }
    
    @action
    async appendList(...) { 
        ...
        const result = await request("some url", params);
        this.updateList(result.list);
        ...
    }
    
    @action
    prependList(...) { ... }
}

class WeiboList extends ContinuousList {
    
    @action
    async voteUp(...) {
        ...
        await request("some url", params);
        const weiboDetail = await updateWeibo("some url", params.weiboId);
        const newList = this.state.list.map((wb) => {
            return wb.id === weiboDetail.id ? weiboDetail : wb;
        });
        this.updateList(newList);
        ...
    }
}

@composition(WeiboList)
class HomePage extends BaseModule {

    $namespace = "page:home:";
    
    ...
    @action
    requestRecommendInfo(...) {
        ...
    }
    ...
}

HomePage.register();

在对应的 HomePage.vue 里面,大致是这样:


WeiboListComponent 组件大致是这样:


总结

其实就是换一种思路:从界面推导数据,从具体到抽象。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/84149.html

相关文章

  • 关于Vue2一些值得推荐的文章 -- 五、六月份

    摘要:五六月份推荐集合查看最新的请点击集前端最近很火的框架资源定时更新,欢迎一下。苏幕遮燎沈香宋周邦彦燎沈香,消溽暑。鸟雀呼晴,侵晓窥檐语。叶上初阳乾宿雨,水面清圆,一一风荷举。家住吴门,久作长安旅。五月渔郎相忆否。小楫轻舟,梦入芙蓉浦。 五、六月份推荐集合 查看github最新的Vue weekly;请::点击::集web前端最近很火的vue2框架资源;定时更新,欢迎 Star 一下。 苏...

    sutaking 评论0 收藏0
  • 关于Vue2一些值得推荐的文章 -- 五、六月份

    摘要:五六月份推荐集合查看最新的请点击集前端最近很火的框架资源定时更新,欢迎一下。苏幕遮燎沈香宋周邦彦燎沈香,消溽暑。鸟雀呼晴,侵晓窥檐语。叶上初阳乾宿雨,水面清圆,一一风荷举。家住吴门,久作长安旅。五月渔郎相忆否。小楫轻舟,梦入芙蓉浦。 五、六月份推荐集合 查看github最新的Vue weekly;请::点击::集web前端最近很火的vue2框架资源;定时更新,欢迎 Star 一下。 苏...

    khs1994 评论0 收藏0
  • 前端开发之走进Vue.js

    摘要:作为目前最热门最具前景的前端框架之一,其提供了一种帮助我们快速构建并开发前端项目的新的思维模式。的新版本,的简称。的包管理工具,用于同一管理我们前端项目中需要用到的包插件工具命令等,便于开发和维护。 Vue.js作为目前最热门最具前景的前端框架之一,其提供了一种帮助我们快速构建并开发前端项目的新的思维模式。本文旨在帮助大家认识Vue.js,了解Vue.js的开发流程,并进一步理解如何通...

    zxhaaa 评论0 收藏0
  • 前方来报,八月最新资讯--关于vue2&3的最佳文章推荐

    摘要:哪吒别人的看法都是狗屁,你是谁只有你自己说了才算,这是爹教我的道理。哪吒去他个鸟命我命由我,不由天是魔是仙,我自己决定哪吒白白搭上一条人命,你傻不傻敖丙不傻谁和你做朋友太乙真人人是否能够改变命运,我不晓得。我只晓得,不认命是哪吒的命。 showImg(https://segmentfault.com/img/bVbwiGL?w=900&h=378); 出处 查看github最新的Vue...

    izhuhaodev 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<