V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
1340641314
V2EX  ›  分享创造

Vue 大型 SPA 项目的最佳实践

  •  2
     
  •   1340641314 ·
    lzxb · 2017-03-14 00:28:06 +08:00 · 9507 次点击
    这是一个创建于 2594 天前的主题,其中的信息可能已经有所发展或是发生改变。

    前言

    从去年 10 月份之后 Vue 2.0 发布了正式版,便将 React 全线转到了 Vue 上开发,陆陆续续开发了四五个项目,多多少少积累了一些心得,现在拿出来和大家分享一下和探讨一下。本人英语水平太 low ,如有错误,还望指正。

    现代前端的标配

    这两年前端发展迅速,日新月异,各种框架层出不穷,这是一个坏时代,也是一个最好的时代,有幸的是能够身处在这个时代去亲眼见证它、实践它。

    • 前端框架: Vue 、 React 、 Angular
    • 打包工具: Webpack 、 Gulp 、 Rollup
    • 语法效验: Eslint
    • css 预处理器: Less 、 Sass 、 PostCSS
    • 语法编译器: Babel 、 TypeScript ...... 一个 web 技术新时代的来临,如滚滚洪流般推动着历史的发展。

    多项目统一的打包配置

    Vue 官方虽然提供了 vue-cli 的脚手架,供我们得以快速开发,但是如果有多个项目,每个项目都生成一套打包配置,很容易造成各个项目都进行一些定制,进而造成项目之间的一些偏离,然而这些都不是我们想要的,所以有必要单独提取出来一套内部的打包配置,创建一个单独的 git 包,然后让其他项目依赖这个 git 包即可。

    1

    Vuex 应该如何使用?

    很抱歉,在我的项目中, Vuex 仅仅是用来存储用户信息等一些全局通用的数据,我不建议将每一个页面的数据存储到 Store 中,那样会导致程序极其的复杂,让我每新增一个页面,都感觉到倍增压力。

    统一 Mixin 处理页面数据请求

    在 SPA 应用中,最离不开的就是如何方便快捷的获取页面的数据,统一处理路由的变化去更新数据,为页面进行数据缓存,实现列表、详情、编辑、新增共用一个 model ,而且有的时候列表的字段不如详情的字段多,所以还要增加一个字段补全的机制。 2

      // 一个简单的例子
      export default function MixinPagesGet () {
        const opt = {
          list: []
          // 各种配置的参数等等
        }
        Object.assign(opt, arguments[0])
        return {
          list: {
            // 列表的 mixin 各种逻辑
          },
          detail: {
            // 详情、修改、新增的 mixin 各种逻辑
          }
        }
      }
    
    
    

    统一的处理 Methods 的错误

    为了避免回调地狱, Promise 简直就是一个神器,一旦遇上,便恨初见晚,不管是 Fetch 还是第三方的请求模块,都普遍支持了 Promise ,我们可以使用 vue-methods-promise 模块对各种错误进行统一处理

    更好的 Vue 组件开发规范

    在 JS 中, object 对象的 key 值是没有顺序之分的,但是人的阅读顺序是有顺序的,按照钩子的执行顺序来书写可以让别人更好的读懂你的代码,如果不是钩子则放到最后。如:

    export default {
      mixins: [],
      data () {
        return {}
      },
      mounted () {
      },
      destroyed () {
      },
      watch: {
      },
      methods: {
      }
    }
    

    如何打一个标准包

    在日常开发中,我们有开发环境、测试环境、正式环境等等,我们需要打出一个标准包,让运维进行配置不同环境的。 我们可以在入口的 html 文件中设置

         <% if (process.env.NODE_ENV == 'production') { %>
        <script src="<%=webpack.publicPath %>configs.js?v=<%=new Date().getTime()%>"></script>
         <% } %>
    

    在 config 的 JS 中设置

      let configs = {}
      if (process.env.NODE_ENV === 'production') {
        configs = window.__configs // 在 config.js 中设置的
      }
      export default configs
    
    25 条回复    2017-06-12 08:21:12 +08:00
    loading
        1
    loading  
       2017-03-14 07:44:50 +08:00 via Android
    还在看官方文档,看完熟悉后再看您这个。
    taowen
        2
    taowen  
       2017-03-14 08:55:11 +08:00
    更关心你为啥要弃坑 react
    wensonsmith
        3
    wensonsmith  
       2017-03-14 09:13:35 +08:00
    感谢! 正在准备构建一个大型应用,学习学习
    1340641314
        4
    1340641314  
    OP
       2017-03-14 09:15:32 +08:00
    @taowen 因为 React 只有我自己会, vue 可以推荐同事在页面中先直接引入使用, React 就不行了,所以后来 vue2.0 的时候直接就上了,这是有铺垫基础的。
    1340641314
        5
    1340641314  
    OP
       2017-03-14 09:18:37 +08:00
    @wensonsmith 写得比较匆忙,很多具体的细节没有写到,就好比统一处理页面请求数据的 mixin 这一块,其实还可以使用数据库进行存储数据,这样用户刷新页面也能快速渲染,因为我公司内部用的,都是针对公司的需求定制化开发,对 api 的规范要求比较严格。
    1340641314
        6
    1340641314  
    OP
       2017-03-14 09:18:44 +08:00
    @loading 666
    1990andy
        7
    1990andy  
       2017-03-14 09:20:28 +08:00 via iPhone
    从掘金上复制粘贴有意思吗?
    https://gold.xitu.io/entry/58c6c6d32f301e006bcc1260
    flybears
        8
    flybears  
       2017-03-14 09:23:37 +08:00
    @1990andy 你没发现头像是一样的?
    Lucius
        9
    Lucius  
       2017-03-14 09:56:00 +08:00
    @1990andy #7
    @flybears #8

    哈哈,确实是一样的头像。
    popo233
        10
    popo233  
       2017-03-14 10:22:42 +08:00
    @1990andy 说你什么好
    weeai
        11
    weeai  
       2017-03-14 10:25:56 +08:00
    不错,非常棒
    elvba
        12
    elvba  
       2017-03-14 10:42:37 +08:00
    "实现列表、详情、编辑、新增共用一个 model"
    这个不错,学到了,谢谢分享!!
    待会儿就去实践下
    elvba
        13
    elvba  
       2017-03-14 10:46:56 +08:00
    @1340641314
    "就好比统一处理页面请求数据的 mixin 这一块,其实还可以使用数据库进行存储数据"
    数据库是指?没太明白,是指浏览器的本地存储么?
    1340641314
        14
    1340641314  
    OP
       2017-03-14 10:55:23 +08:00
    @elvba 是的。这些只是更高级的特性,除此之外还可以增加指令,存储当前页面用户查看的滚动条位置,等用户从详情返回回来之后,能还原到指定的位置。这一切都需要一个统一的 mixin 来处理这些行为,其他人就可以专心负责用户行为上的开发,这一块比较复杂,有时间单独拿出来分享
    tedd
        15
    tedd  
       2017-03-14 10:55:39 +08:00
    感谢分享,我才接触 vue ,写了个购物车试了下手,直接上的 2.0 ,虽然 app 很小,但也硬上了 vuex ,之前都没有用过单项数据流,所以想尝尝鲜,用了后感觉很不错,所有数据变动的操作都集中在一个地方,貌似这是双向绑定后又一个非常值得借鉴的模式。但由于没有大型项目实际使用的经验,现阶段的理解也很浅薄,很想听听 lz 具体说说 “不建议将每一个页面的数据存储到 Store 中,那样会导致程序极其的复杂”。我的理解是 Store 也可以根据模块分拆开来,这样 componenent 对应个字的 store , map 其中的方法即可,这样也会增加程序复杂度吗?如果不用的话那用什么呢?
    1340641314
        16
    1340641314  
    OP
       2017-03-14 10:58:37 +08:00
    @tedd 上面已经提到了啊,专门写一个 mixin 来负责管理页面的数据虽然无法想 vuex 那样可以追踪用户的行为,但是你应该保存这个 mixin 应该是可靠的。
    strwei
        17
    strwei  
       2017-03-14 12:58:08 +08:00
    贝爷现在在哪上班
    meathill
        18
    meathill  
       2017-03-14 15:29:16 +08:00
    我的经验,列表读取的时候可以直接返回全部数据,通过模板控制,有些不显示就可以。这样在编辑和详情的时候,可以少取一次。

    Vuex 要求所有的修改通过 `mutation` 进行,会影响表单元素使用 `v-model` 进行双向数据绑定,不知道楼主怎么处理的?我目前试过两个做法, 1. 按照 Vuex 文档对每个属性写 getter/setter (很麻烦); 2. 增加一个中间对象,操作针对中间对象,在关闭弹窗 /切换路由的时候再一次性 `commit()`。目前我比较倾向后者。
    1340641314
        19
    1340641314  
    OP
       2017-03-14 15:32:17 +08:00
    @meathill 那样只能监听 change 事件了,我是另开一个 mixin 统一处理页面的数据,不涉及 vuex
    1340641314
        20
    1340641314  
    OP
       2017-03-14 15:32:29 +08:00
    @strwei 大神带我飞
    zhuangtongfa
        21
    zhuangtongfa  
       2017-03-17 14:30:33 +08:00
    @meathill
    监听 chage 事件,然后加上 debounce
    meathill
        22
    meathill  
       2017-03-17 15:06:51 +08:00
    @zhuangtongfa 这个跟 debounce 没有关系
    zhuangtongfa
        23
    zhuangtongfa  
       2017-03-17 15:58:04 +08:00
    @meathill 如果监听了 change 事件,不做处理持续发 mutation 太耗资源
    meathill
        24
    meathill  
       2017-03-17 16:05:06 +08:00
    @zhuangtongfa 这里的问题不是持续发 mutation ……是 Vuex 严格模式禁止直接修改对象,使得表单里的双向数据绑定失效,需要多写很多代码,损失了使用 Vue 带来的好处。所以我在想有没有什么好办法可以解决。
    1340641314
        25
    1340641314  
    OP
       2017-06-12 08:21:12 +08:00
    @meathill 最近搞了一个 vuet 出来,专门管理 Vue.js 应用程序的状态 https://github.com/medevicex/vuet
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1014 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 19:18 · PVG 03:18 · LAX 12:18 · JFK 15:18
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.