电商网站项目总结:Vuex 带来全新的编程体验

栏目: 编程语言 · 发布时间: 5年前

内容简介:如果在简历上写“XX电商系统”的实现,其实第一直觉是这个人一定是从培训班出来的。而我们“项目管理”课程正好就是做一个小型电商网站。开发时长一个月左右,包含买家端、卖家端、管理员端,虽然业务逻辑比较常见,但是这次开发仍有收获,最重要的一点收获就是前面的几次项目开发,拿到后端接口和需求之后,会按照以下的方式去实现功能:第1、2、3步基本上是没太大问题的,问题就出在第4步,其结果是导致一个Vue文件越来越大,到后面一个复杂的页面vue文件将会包含如下内容:

如果在简历上写“XX电商系统”的实现,其实第一直觉是这个人一定是从培训班出来的。而我们“项目管理”课程正好就是做一个小型电商网站。开发时长一个月左右,包含买家端、卖家端、管理员端,虽然业务逻辑比较常见,但是这次开发仍有收获,最重要的一点收获就是 对Vuex有了真正的实践和认识。 所以,本文大部分介绍Vuex在该项目上的实践以及所踩的坑,另外的部分则是项目中一些其他要点的总结。

过去那臃肿的Vue组件

前面的几次项目开发,拿到后端接口和需求之后,会按照以下的方式去实现功能:

  1. 划分出 Components 和 Pages,尽量保证一些组件能够复用。
  2. 抽象出部分可以复用的 SCSS 代码以及设计通用的 style class。
  3. 基于某个 HTTP 库(如 axios)配置并封装一层底层方法,并基于该方法之上书写具体的API 函数。
  4. 在页面和组件内调用上述封装的方法,在函数回调或 Promisethen 方法里进行数据更新或者做更多的业务处理。

好像没什么问题哈?

第1、2、3步基本上是没太大问题的,问题就出在第4步,其结果是导致一个Vue文件越来越大,到后面一个复杂的页面vue文件将会包含如下内容:

  • data 里大量的数据字段,有 控制是否展示元素的渲染用数据用于"上锁"的变量 等。
  • createdmounted 里包含了大量的 请求回调处理
  • template 里使用的组件的属性内,绑定了大量的 props

最后的结果就是vue文件变得臃肿。

文件越长,可读难度会提高,可维护性会降低。

谁也不喜欢看一个包含了逻辑处理、界面处理、数据处理的冗杂代码文件。

所以,为了解决上述问题,引入 Vuex 是非常必要的。

其实,之前也一直在使用Vuex,不过用的目的仅仅是为了 “保存一点数据能够全局使用” 而已,根本没有深入使用 ActionGettersMutations 等。 本文关于Vuex不会过多介绍其原理以及好处,主要关注实践以及使用心得,Vuex介绍或入门请移步官方文档。

干净、解耦合、职责分明

笔者所做的,是将关于数据请求和更新,基本都放到了 Vuex 里,让 Vuex 成为了整个项目的 “数据集散中心” ,而 vue 组件里,仅仅是进行 事件调度(dispatch)绑定来自Vuex的数据

简单的例子

我们以商品详情页面举例,其包含如下的功能:

  • 第一次进入页面根据URL参数中的id请求商品数据。
  • 根据商品的属性选择更新库存和价格。
  • 添加购物车并更新小红点。
  • 下单。
  • 收藏商品。

如图所示:

电商网站项目总结:Vuex 带来全新的编程体验

如果我们不使用Vuex,代码的结构可能如下:

<template>

<template>

<script>
export default {
    data() {
        detail: {
            name: '',
            shopId: '',
            id: '', 
            pic: '',
            description: '',
            price: '',
            updateTime: '',
            categoryId: '',
            stock: 0,
            createTime: '',
            attributeList: {},
            collectId: 0,
        },
        // 一大堆商品的字段数据 【MARK】
    },
    created(){
        this.$http.get('/product/:id')
          .then()
          // 以及一端更新其他数据的请求 【MARK】
    },
    methods(){
        clickCart(){
            this.$http.get('xxx')
              .then('xxx')
            this.$emit('xxx'); // 与上层组件通信更新购物车的红点
        }
        // 一堆用户事件的触发方法,每个方法内都是一堆http请求和回调处理 【MARK】
    },
    computed:{
        // 一些基于商品数据判断状态的数据 【MARK】
    }
}
</script>

<style>
<!-- 忽略相关样式代码-->
<style>
复制代码

如果按照上述的方式来写,虽然可以保证关于这个页面的逻辑处理都保留在这个vue文件内,但是却显得十分臃肿,如果后续要加更多的功能抑或是修改,其需要读的代码可能更多。

所以,以上代码示例中的被 【MARK】 标记的部分,将是 Vuex 可以优化的。 最后的代码如下图所示:

电商网站项目总结:Vuex 带来全新的编程体验

代码的可读性提高了不少:

  • 该文件里看不到任何的http请求 ,也看不到任何请求路径。(请求路径一般是静态的,直接写HTTP请求路径相当于写死了数据的来源,对于后期的更改数据来源非常不友好)
  • data 里不含任何业务数据字段 ,仅保留控制页面的字段
  • 代码结构变得简单 ,只有 【触发事件】-【回调】 这样简单的逻辑。

关于数据处理的代码,全部封装到了 Vuex 上了:

电商网站项目总结:Vuex 带来全新的编程体验

我们在Vuex层,不仅请求了数据,同时对返回的数据做了判断以及不同的逻辑处理,同时设置 Getters 使的页面能够基于 Getters 提供的数据做各类 二元判断

Vuex层带来了如下的好处:

  • 在不同的页面可以触发相同的 Actions ,就这个例子,我只要写了一次 加入购物车 的函数,在各个页面都可以使用了。
  • Actions之间可以组合使用 ,通过组合的方式,我们可以更加轻易的实现复杂的业务逻辑,比如 添加商品进购物车的同时更新商品数据并更新购物车数据 ,这样需要写三次 HTTP 请求的业务逻辑,此时只需要将三个Actions进行组合即可,而这几个Actions还可以在其他地方单独使用。
  • 直观 ,一眼看过去,就知道商品模型上有哪些动作,对于 New Guy 熟悉业务逻辑更加方便,也方便开发者检查自己的代码或者函数是否考虑周全。(BTW,在一堆HTML里找逻辑是真的难受)
  • 减少组件间通信次数 ,一个中心化的 数据仓库 带来的好处就是减少了数据层层传递的操作,按照以前的编码习惯,我会大量使用 $emitprops 来实现父子或兄弟组件通信,而现在,只需要在组件中触发相应的事件绑定相应的数据即可。

全新的业务编写体验

直观体验来说,彻底使用 Vuex 后,编码思路清晰不少,因为写完整体的一个功能需要2~3天,而Vuex对于 “间断性编程” 非常有帮助,能够迅速捡起上一次开发的进度。

使用Vuex之后就是按照如下的步骤进行开发了:

(第1、2、3步不变,如前文) 4.构建Vuex的Store模型,定义所需的方法。 5.编写组件并绑定在Vuex上的相关数据和方法。 6.编写触发 dispatch 后的回调。

笔者认为使用Vuex几个重要的原则

使用 Vuex 存在一定的规范,在官网上已经陈列了诸如 表单处理测试项目结构 的规范,而下面的一些原则仅仅是笔者的一些经验之谈,不一定正确,有所帮助便是最好的。

【不处理页面跳转】:页面跳转在 dispatch 的回调里进行处理。

最初我的设计是在 Action 请求数据之后同时也负责所有的 跳转逻辑弹窗逻辑 ,不过,这样做又让 视图层数据层 耦合了,使得我抽象出来的 Action 的复用性变得极差,同时,在 vue 文件看到关于视图层的处理才算是比较正常的编写逻辑。

【单一职责原则】: mutationaction 尽量保持只做一件事原则。

正如上一条原则中提到的要提高 action 的复用性,那么就要保证需要复用的 action 只做一个功能,如 更新A数据更新B数据 不要直接融合成一个 action ,而是分别定义两个 action ,并 通过组合的方式 来实现一个更复杂的功能,有点类似精简指令集的思想。

如:

actions:{
    updateA(){}, // A 可能在其他地方被单独使用
    updateB(){},  // B 可能在其他地方被单独使用
    updateAandB({dispatch}){
        dispatch("updateA");
        dispatch("updateB");
    }, // 同时触发 A B 的复杂action
}
复制代码

【使用Promise和AA】(Async & Await)

为了让 dispatch 函数拥有 Promise风格 的处理回调的能力,可以让 action 的返回值作为一个 Promise 对象,如:

// store.js
actions:{
    updateA(){
        return Promise.resolve()
    }
}
复制代码

在组件内就可以使用 .then

...
created(){
    this.$store.dispatch('updateA')
        .then(() => {
            ...
        })
}
...
复制代码

Vuex 一般建议在 actions 进行异步操作,所以为了让代码更加优雅,可以用 AA 如下编写:

// store.js
actions:{
    async updateA(){
        const result = await ajax('/**/**');
        if(result){
            return Promise.resolve()
        }
    }
}
复制代码

所以,在实践中的代码如图:

电商网站项目总结:Vuex 带来全新的编程体验

【使用namespace】,为了你自己好。

一般使用vuex,会根据实体或者页面来拆分state形成module,一个module里包含其所需的所有 actions,states,mutation 等。如电商里,一般有 商品订单用户 这几个实体可以拆成module,拆分出来之后如图:

电商网站项目总结:Vuex 带来全新的编程体验

拆分的好处是更加独立直观了,坏处是如果不使用 命名空间 ,可能造成 actions , mutations 冲突, 正好 Vuex 也提供 namespace 的配置 ,参考官方文档即可。

这次使用的不足

未使用namespace

虽然总结到了原则里,不过这次并没有使用 namespace ,算是这次比较大的不足了,解决的办法是”手动namespace“,如图:

电商网站项目总结:Vuex 带来全新的编程体验

actions 的方法名前缀加上该实体名用于区分不同的方法,实在是比较拙劣的手段了。

部分代码仍然有重复书写的情况

情况发生在获取到异步数据之后的代码,一般如下这段代码会大量重复:

if (result.code){
    return Promise.resolve(data);
}
return Promise.reject(msg);
复制代码

虽然不算多,但是这逻辑仍然有可抽象出来的可能性,下次打算在 RootState 里添加一个 action ,用于处理这样的后端返回数据,期望结果如下:

actions: {
    parseResult({}, result){
      if (result.code){
        return Promise.resolve(data);
      }
        return Promise.reject(msg);
    },
    async getA({dispatch}){
        const result = await http.get('xx/xx');
        return dispatch('parseResult', result); // One line , it's clean
    }
}
复制代码

其他收获

拥抱 Vue CLI 3

3.0 基本在配置上做到 极简化 了。很久没开发 Vue 的项目了,记得上一个 Vue 项目里,仍然有一大堆 xxx.congfig.js ,而现在,基本集成到了CLI内部了,通过一个 vue.config.js 可满足大部分开发需求。本项目配置如下图:

电商网站项目总结:Vuex 带来全新的编程体验

比以前的配置更加直观了,更多请参考:cli.vuejs.org/zh/,至于插件机制,本次开发未用上,只是在安装第三方包的时候可以用 vue add 了,有GUI可以查看安装了哪些插件。

Vue.use 和 Vue.install 使用的地方汇总到 plugins 目录下

本项目是一个多页面应用,总共有3个Vue实例,所以希望能够按需注入想要的第三方依赖如 axios , qrcode , lazyload 等一些 工具 库或第三方组件。于是都将其汇总到 plugins 目录下了,如下图:

电商网站项目总结:Vuex 带来全新的编程体验
电商网站项目总结:Vuex 带来全新的编程体验

这样封装的好处是,我可以对每个Vue实例按需导入第三方依赖,一行import就可以,如下图:

电商网站项目总结:Vuex 带来全新的编程体验

开始考虑优化了

一个大型的web app 打包压缩后都不超过500kb,所以就以此作为 Benchmark 来优化该项目打包后的大小, 按需引入 第三方依赖(特别是 Elementlodash )减少了不少项目体积。不过最主要的还是得学会用 webpack analyse tool 来分析。

结论

总之,本次项目主要是刷新了对 Vuex 的认知,其能够让我们编写的 vue 组件可读性和可维护性更高。同时,也能够让数据更新这块的代码复用性更高。通过 Vuex 来构建一个 中心化的数据集散中心 还能让开发的思路更顺畅,值得学习。

参考:

Vuex 是什么?


以上所述就是小编给大家介绍的《电商网站项目总结:Vuex 带来全新的编程体验》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

C算法(第二卷:图算法)(第3版)

C算法(第二卷:图算法)(第3版)

塞德威克(Sedgewick Robert) / 周良忠 / 第1版 (2004年1月1日) / 2004-4 / 38.0

《C算法(第2卷)(图算法)(第3版)(中文版)》所讨论的图算法,都是实际中解决图问题的最重要的已知方法。《C算法(第2卷)(图算法)(第3版)(中文版)》的主要宗旨是让越来越多需要了解这些算法的人的能够掌握这些方法及基本原理。书中根据基本原理从基本住处开始循序渐进地讲解,然后再介绍一些经典方法,最后介绍仍在进行研究和发展的现代技术。精心挑选的实例、详尽的图示以及完整的实现代码与正文中的算法和应用......一起来看看 《C算法(第二卷:图算法)(第3版)》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码