建立和维护大型 Vue.js 项目的 10 个最佳实践

目录
  • 1.使用插槽(slot)使组件更易于理解并且功能更强大
  • 2.正确组织您的 Vuex 存储
  • 3.使用操作(Vuex Actions)进行 API 调用和提交数据
  • 4.使用 mapState,mapGetters,mapMutations 和 mapAction 简化代码库
  • 5.使用 API 工厂
  • 6.使用 $config 访问您的环境变量(在模板中特别有用)
  • 7.遵循一个约定来写提交注释
  • 8.始终在生产项目时冻结软件包的版本
  • 9.显示大量数据时使用 Vue 虚拟滚动条
  • 10.跟踪第三方程序包的大小

这是我在使用大型代码库进行 Vue 项目时开发的最佳实践。这些技巧将帮助您开发更有效的代码,更易于维护和共享。

今年的自由职业生涯中,我有机会从事一些大型Vue应用程序的工作。我所谈论的项目有超过12个Vuex 存储,大量组件(有时数百个)和许多视图(页面)。实际上,这对我来说是非常有意义的经历,因为我发现了许多有趣的模式来使代码可扩展。我还必须修复一些导致著名的意大利面条代码难题的错误做法

因此,今天,我将与您分享10个最佳实践,如果您要处理大量的代码库,我建议您遵循这些最佳实践。

1.使用插槽(slot)使组件更易于理解并且功能更强大

有一天,我只需要创建一个弹出窗口。乍一看,没有什么真正复杂的,只是包括标题,描述和一些按钮。所以我要做的就是把所有东西都当作属性。最后,我用了三个属性来定制组件,当人们单击按钮时会发出一个事件。十分简单!:sweat_smile:

但是,随着项目的不断发展,团队要求我们在其中显示许多其他新内容:表单字段,不同的按钮(取决于显示在哪个页面上),卡片,页脚和列表。我发现,如果我继续使用属性来使这个组件不断扩展,似乎也可以。但是上帝,:weary:我错了!该组件很快变得太复杂了,以至于无法理解,因为它包含了无数的子组件,使用了太多的属性并发出了大量事件。:volcano:我经历了一种可怕的情况,当您在某处进行更改时,它最终以某种方式破坏了另一页上的其他内容。我搞了个科学怪人的怪物,而不是一个可维护的组件!

但是,如果我从一开始就依赖插槽,情况可能会更好。最后,我重构了所有东西以提供这个小组件。易于维护,更快地理解并且可扩展性更高!

<template>
  <div class="c-base-popup">
    <div v-if="$slots.header" class="c-base-popup__header">
      <slot name="header">
    </div>
    <div v-if="$slots.subheader" class="c-base-popup__subheader">
      <slot name="subheader">
    </div>
    <div class="c-base-popup__body">
      <h1>{{ title }}</h1>
      <p v-if="description">{{ description }}</p>
    </div>
    <div v-if="$slots.actions" class="c-base-popup__actions">
      <slot name="actions">
    </div>
    <div v-if="$slots.footer" class="c-base-popup__footer">
      <slot name="footer">
    </div>
  </div>
</template>
<script> export default {
  props: {
    description: {
      type: String,
      default: null
    },
    title: {
      type: String,
      required: true
    }
  }
} </script>

我的观点是,根据经验,由知道何时使用插槽的开发人员构建的项目确实对其未来的可维护性有很大的影响。这样就可以减少发出事件的次数,使代码更易于理解,并且可以在内部显示所需的任何组件时提供更大的灵活性。

作为一个经验法则,请记住,当最终在子组件的父组件中复制子组件的属性时,应该从这一点开始使用插槽。

2.正确组织您的 Vuex 存储

通常,新的 Vue.js 开发人员开始学习 Vuex,因为他们偶然发现了以下两个问题:

  • 他们要么需要从树结构中实际上相距太远的另一个组件访问给定组件的数据,要么
  • 他们需要数据在组件销毁后继续存在。

那是他们创建第一个 Vuex 存储,了解模块并开始在应用程序中进行组织的时候。

问题是创建模块时没有单一模式可以遵循。但是我强烈建议您考虑如何组织它们。据我了解,大多数开发人员都喜欢按功能组织它们。例如:

  • 验证码
  • 博客
  • 收件箱
  • 设定

就我而言,我发现根据它们从API提取的数据模型来组织它们时更容易理解。例如:

  • 用户数
  • 队伍
  • 留言内容
  • 小部件
  • 文章

您选择哪一个取决于您。唯一要记住的是,从长远来看,组织良好的 Vuex 存储将使团队更具生产力。这也将使新来者更容易在加入您的团队时就将您的想法围绕您的代码库。

3.使用操作(Vuex Actions)进行 API 调用和提交数据

我的大多数API调用(如果不是全部)都在我的 Vuex 操作(vuex actions)中进行。您可能想知道:为什么这里调用更好?

仅仅因为它们中的大多数都提取了我需要在存储(vuex store)中提交的数据。此外,它们提供了我真正喜欢的封装性和可重用性。我这样做还有其他一些原因:

  • 如果我需要在两个不同的地方(例如博客和首页)获取文章的首页,则可以使用正确的参数调用适当的调度程序。数据将被提取,提交和返回,除了调度程序调用外,没有重复的代码。
  • 如果我需要创建一些逻辑来避免在提取第一页时提取它,则可以在一个地方进行。除了减少服务器上的负载之外,我还有信心它可以在任何地方使用。
  • 我可以在这些操作(vuex actions)中跟踪我的大多数 Mixpanel 事件,从而使分析代码库真正易于维护。我确实有一些应用程序,其中所有 Mixpanel 调用都是在操作中单独进行的。当我不必了解跟踪什么不跟踪什么以及何时发送时,:joy:这种方式工作会给我带来有多大的快乐。

译注:Mixpanel 是一家数据跟踪和分析公司,允许开发者跟踪各种用户行为,比如用户浏览的页面数,iPhone 应用分析,Facebook 应用互动情况,以及 Email 分析。类似Firebase一样的埋点分析工具。

4.使用 mapState,mapGetters,mapMutations 和 mapAction 简化代码库

当您只需要访问state/getter或在组件内部调用action/mutation时,通常无需创建多个计算属性或方法。使用 mapState mapGetters mapMutations mapActions 可以帮助你缩短你的代码,通过分组来化繁为简,从你存储里模块一个地方就能掌握全局。

// NPM
import { mapState, mapGetters, mapActions, mapMutations } from "vuex";
export default {
  computed: {
    // Accessing root properties
    ...mapState("my_module", ["property"]),
    // Accessing getters
    ...mapGetters("my_module", ["property"]),
    // Accessing non-root properties
    ...mapState("my_module", {
      property: state => state.object.nested.property
    })
  },
  methods: {
    // Accessing actions
    ...mapActions("my_module", ["myAction"]),
    // Accessing mutations
    ...mapMutations("my_module", ["myMutation"])
  }
};

Vuex官方文档中提供了您在这些便捷帮助器上所需的所有信息。

5.使用 API 工厂

我通常喜欢创建一个 this.$api 可以在任何地方调用以获取API端点的助手。在项目的根目录下,我有一个 api 包含所有类的文件夹(请参阅下面的其中一个)。

api
├── auth.js
├── notifications.js
└── teams.js

每个节点都将其类别的所有端点分组。这是我在 Nuxt 应用程序中使用插件初始化此模式的方式(这与标准 Vue 应用程序中的过程非常相似)。

// PROJECT: API
import Auth from "@/api/auth";
import Teams from "@/api/teams";
import Notifications from "@/api/notifications";
export default (context, inject) => {
  if (process.client) {
    const token = localStorage.getItem("token");
    // Set token when defined
    if (token) {
      context.$axios.setToken(token, "Bearer");
    }
  }
  // Initialize API repositories
  const repositories = {
    auth: Auth(context.$axios),
    teams: Teams(context.$axios),
    notifications: Notifications(context.$axios)
  };
  inject("api", repositories);
};
export default $axios => ({
  forgotPassword(email) {
    return $axios.$post("/auth/password/forgot", { email });
  },
  login(email, password) {
    return $axios.$post("/auth/login", { email, password });
  },
  logout() {
    return $axios.$get("/auth/logout");
  },
  register(payload) {
    return $axios.$post("/auth/register", payload);
  }
});

现在,我可以简单地在我的组件或 Vuex 操作中调用它们,如下所示:

export default {
  methods: {
    onSubmit() {
      try {
        this.$api.auth.login(this.email, this.password);
      } catch (error) {
        console.error(error);
      }
    }
  }
};

6.使用 $config 访问您的环境变量(在模板中特别有用)

您的项目可能在某些文件中定义了一些全局配置变量:

config
├── development.json
└── production.json

我喜欢通过 this.$config 助手快速访问它们,尤其是当我在模板中时。与往常一样,扩展Vue对象非常容易:

// NPM
import Vue from "vue";
// PROJECT: COMMONS
import development from "@/config/development.json";
import production from "@/config/production.json";
if (process.env.NODE_ENV === "production") {
  Vue.prototype.$config = Object.freeze(production);
} else {
  Vue.prototype.$config = Object.freeze(development);
}

7.遵循一个约定来写提交注释

随着项目的发展,您将需要定期浏览组件的提交历史记录。如果您的团队没有遵循相同的约定来书写他们的提交说明,那么将很难理解每个团队成员的行为。

我总是使用并推荐Angular commit消息准则。在我从事的每个项目中,我都会遵循它,在许多情况下,其他团队成员也会很快发现遵循它也更好。

遵循这些准则会导致更具可读性的消息,从而在查看项目历史记录时更易于跟踪提交。简而言之,这是它的工作方式:

git commit -am "<type>(<scope>): <subject>"
# Here are some samples
git commit -am "docs(changelog): update changelog to beta.5"
git commit -am "fix(release): need to depend on latest rxjs and zone.js"

看看他们的README文件以了解更多约定。

8.始终在生产项目时冻结软件包的版本

我知道...所有软件包都应遵循语义版本控制规则。但实际情况是,其中一些并非如此。:sweat_smile:

为避免因您的一个依赖项在半夜醒来破坏了整个项目,锁定所有软件包的版本会使您的早晨工作压力减轻。:innocent:

它的意思很简单:避免使用以 ^ 开头的版本:

{
  "name": "my project",
  "version": "1.0.0",
  "private": true,
  "dependencies": {
    "axios": "0.19.0",
    "imagemin-mozjpeg": "8.0.0",
    "imagemin-pngquant": "8.0.0",
    "imagemin-svgo": "7.0.0",
    "nuxt": "2.8.1",
  },
  "devDependencies": {
    "autoprefixer": "9.6.1",
    "babel-eslint": "10.0.2",
    "eslint": "6.1.0",
    "eslint-friendly-formatter": "4.0.1",
    "eslint-loader": "2.2.1",
    "eslint-plugin-vue": "5.2.3"
  }
}

9.显示大量数据时使用 Vue 虚拟滚动条

当您需要在给定页面中显示很多行或需要循环访问大量数据时,您可能已经注意到该页面的呈现速度很快。要解决此问题,可以使用vue-virtual-scoller

npm install vue-virtual-scroller

它将仅渲染列表中的可见项,并重用组件和dom元素,以使其尽可能高效。它真的很容易使用,顺滑得很

<template>
  <RecycleScroller
    class="scroller"
    :items="list"
    :item-size="32"
    key-field="id"
    v-slot="{ item }"
  >
    <div class="user">
      {{ item.name }}
    </div>
  </RecycleScroller>
</template>

10.跟踪第三方程序包的大小

当很多人在同一个项目中工作时,如果没有人关注它们,那么已安装软件包的数量会迅速增加,令人难以置信。为了避免您的应用程序变慢(尤其是在移动网络变慢的情况下),我在Visual Studio Code中使用了导入费用包。这样,我可以从编辑器中直接看到导入的模块库有多大,并且可以查看导入的模块库过大时出了什么问题。

例如,在最近的项目中,导入了整个 lodash 库(压缩后大约24kB)。问题在于,项目里仅仅使用cloneDeep 一个方法。通过在 导入费用包 中识别此问题后,我们通过以下方式解决了该问题:

npm remove lodash
npm install lodash.clonedeep

然后可以在需要的地方导入clonedeep函数:

import cloneDeep from "lodash.clonedeep";
的JavaScript

为了进一步优化,您还可以使用Webpack Bundle Analyzer软件包通过交互式可缩放树状图来可视化Webpack输出文件的大小。

到此这篇关于建立和维护大型 Vue.js 项目的 10 个最佳实践的文章就介绍到这了,更多相关建立和维护 Vue.js 项目实践内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Vue.js slot插槽的作用域插槽用法详解

    目录 没有插槽的情况 Vue2.x 插槽 有插槽的情况 具名插槽 没有slot属性 插槽简单实例应用 作用域插槽 ( 2.1.0 新增 ) Vue3.x 插槽 插槽 作用域插槽 没有插槽的情况 <div id="app"> <child> <span>1111</span> </child> </div> <script> // 注册子组件 Vue.component("child"

  • Vue.js实现日历功能

    本文实例为大家分享了Vue.js实现日历功能的具体代码,供大家参考,具体内容如下 Github 功能需求 使用 Vue.js 实现指定年月的日历表,配合后台接口数据,添加对应日期的空气质量描述等信息.后台传递当月空气质量指数的数据,前端生成日历表后将空气质量指数添加到对应日期上. 空气质量数据示例: data.json { "code": 200, "msg": "", "data": [{ "time":

  • vue.js管理后台table组件封装的方法

    目录 问题分析 为什么封装 封装的内容都有哪些 封装table组件 确认数据格式 封装组件 封装全局组件 table组件封装 分页组件封装 数据定义 封装 总结 最近开了新的项目,简单说了自己的table封装. 问题分析 为什么封装 首先为什么封装,是因为追求技术吗,不,是因为懒,不想一直的去粘贴复制代码,所以就想把table封装下,可以在创建新的table的时候,只需要填充数据就行了. 封装的内容都有哪些 主要有两个,一个是table组件,一个是分页组件 搞清楚这个些,就可以开始封装组件了.

  • Vue.js项目前端多语言方案的思路与实践

    目录 一.通常有哪些内容需要处理 二.基本思路 三.具体实践中的一些细节 1.获取当前应该采用何种语言的getLang模块的实现 2.Vux组件的多语言包的配置 3.vux-loader的配置 4.自定义组件内外文案的多语言化 5.vuex-i18n的实现 6.图片的多语言化 7.在当前页面通过按钮切换当前语言后,如何更新当前页面的内容? 8.Yaml中特殊字符的转义 总结 前端的国际化是一个比较常见的需求.但网上关于这一方面的直接可用的方案却不多.最近刚做了一版基于Vue.js的多语言实现,在

  • Vue.js实现时间轴功能

    本文实例为大家分享了Vue.js实现时间轴功能的具体代码,供大家参考,具体内容如下 GitHub 时间轴组件封装 Main.js <template> <div class="timeline-main"> <div class="timeline-axis"> <div class="axis-item" v-for="(time, index) in dateTimes" :key

  • Vue.js之$emit用法案例详解

    1.父组件可以使用 props 把数据传给子组件. 2.子组件可以使用 $emit 触发父组件的自定义事件. vm.$emit( event, arg ) //触发当前实例上的事件 vm.$on( event, fn );//监听event事件后运行 fn:  例如:子组件: <template> <div class="train-city"> <h3>父组件传给子组件的toCity:{{sendData}}</h3> <br/&

  • Vue.js 实现tab切换并变色操作讲解

    在实现这个功能时借鉴的原博主的方法没有实现切换变色,琢磨了好久终于知道了怎么切换变色(小菜鸟的咆哮)!!!记录下来以供参考,以下是vue的完整tab页切换并变色的代码框架. ​<template> <div > //tab页切换按钮部分 <ul > <li v-for="(item,index) in navList" :class = "{active:!(index- menuIndex)}" @click = 'men

  • vue.js+boostrap项目实践(案例详解)

    一.为什么要写这篇文章 最近忙里偷闲学了一下vue.js,同时也复习了一下boostrap,发现这两种东西如果同时运用到一起,可以发挥很强大的作用,boostrap优雅的样式和丰富的组件使得页面开发变得更美观和更容易,同时vue.js又是可以绑定model和view(这个相当于MVC中的,M和V之间的关系),使得对数据变换的操作变得更加的简易,简化了很多的逻辑代码. 二.学习这篇文章需要具备的知识 1.需要有vue.js的知识 2.需要有一定的HTML.CSS.JavaScript的基础知识 3

  • 建立和维护大型 Vue.js 项目的 10 个最佳实践

    目录 1.使用插槽(slot)使组件更易于理解并且功能更强大 2.正确组织您的 Vuex 存储 3.使用操作(Vuex Actions)进行 API 调用和提交数据 4.使用 mapState,mapGetters,mapMutations 和 mapAction 简化代码库 5.使用 API 工厂 6.使用 $config 访问您的环境变量(在模板中特别有用) 7.遵循一个约定来写提交注释 8.始终在生产项目时冻结软件包的版本 9.显示大量数据时使用 Vue 虚拟滚动条 10.跟踪第三方程序包

  • 构建大型 Vue.js 项目的10条建议(小结)

    下面是我在开发大型 Vue 项目时的最佳实践.这些技巧将帮助你开发更高效.更易于维护和共享的代码. 今年做自由职业的时候,我有机会开发了一些大型 Vue 应用程序.我所说的这些项目,Vuex store 超过十个,包含大量的组件(有时候几百个)和视图页面.对我来说这是个很有益的经验,因为我发现了很多有意思的模式,可以让代码拥有更好的伸缩性.我还必须修正一些导致著名的意大利面条式代码困境的错误实践. 因此,今天我将与你分享10个最佳实践,如果你正在处理大型代码库,我建议你参考这些方法. 1. 使用

  • 构建Vue大型应用的10个最佳实践(小结)

    这些是我构建大型Vue项目得出的最佳实践,这些技巧将帮助你更高效的编码,并且使其更容易维护和协作. 在我今年的自由职业生涯中我有幸开发了一些大型Vue程序.我所说的这些项目使用了大量Vuex stores

  • Vue.js@2.6.10更新内置错误处机制Fundebug同步支持相应错误监控

    Vue.js 从诞生至今已经 5 年,尤大在今年 2 月份发布了重大更新,即Vue 2.6.更新包括新增 scoped slot 语法.性能提升.动态指令参数等等.其中我们最关注的是错误处理. 异步错误处理 Vue 的内置错误处理机制(组件内 errorCaptured hook 和全局 errorHandler hook)现在也会捕获 v-on 处理程序内部的错误.此外,如果任意一个生命周期 hook 或事件处理程序执行了异步操作,现在可以从函数中返回一个 Promise,Promise 链中

  • Vue.js一个文件对应一个组件实践

    这方面官网给的示例是需要工具来编译的,但是nodejs又没有精力去学,只好曲线救国.VueJS的作者在另一个网站有一篇文章讲到可以用jQuery.getScript或RequireJS实现组件,却没有给示例,于是自己摸索出了一种方法. 用到的工具: vue.js --- 0.12.+ (需要0.12中async component支持) require.js text.js --- RequireJS text plugin https://github.com/requirejs/text 文

  • vue.js中Vue-router 2.0基础实践教程

    前言 Vue.js的一大特色就是构建单页面应用十分方便,既然要方便构建单页面应用那么自然少不了路由,vue-router就是vue官方提供的一个路由框架.本文主要介绍了Vue-router 2.0的相关内容,分享出来供大家参考学习,下面来看看详细的介绍: 一.基础用法: <div id="app"> <h1>Hello App!</h1> <p> <!-- 使用 router-link 组件来导航. --> <!-- 通

  • Vue开发高德地图应用的最佳实践

    目录 前言 异步加载 封装组件 使用组件 自定义界面最佳实践 总结 前言 之前做不过不少关于地图交互的产品系统,目前国内主流的地图应用 SDK 只有几家:高德.百度和腾讯.所以个人觉得在 PC 应用上高德地图开发相对好一些,至少体验起来没有很明显的坑.这篇文章算是总结下开发地图应用总结吧. 异步加载 因为使用 js sdk 应用,脚本文件本身体积很大,所以要注意下加载的白屏时间,解决用户体验问题,目前绝大部分产品应用都是 SPA 单页面应用系统,所以我封装一个异步加载的方法: const loa

  • 详解Node.js amqplib 连接 Rabbit MQ最佳实践

    客户端设置connection_name 在建立连接时,设置connection_name属性,可以在RabbitMQ Managerment 中查看到连接来自那个实例. amqp.connect(rabbitMqAddress, { clientProperties: { connection_name: 'your host name' } }) 队列属性autoDelete durable 如无必要,建议将队列设置成自动删除,这个在TCP连接断开后,队列会自动删除.另外也不要使用持久化队列

  • JS trim去空格的最佳实践

    刚好上次有同学提出疑问.刚好可以自测一下.先来看看老道在<JavaScript 精粹>P33 写的吧.他对 String 对象扩展了一个 trim() 方法: 复制代码 代码如下: Function.prototype.method = function(name, func) { this.prototype[name] = func; return this; }; String.method('trim', function() { return this.replace(/^\s+|\

  • 详解Vue.js项目API、Router配置拆分实践

    前后端分离开发方式前端拥有更高的控制权 随着前端框架技术的飞速发展,Router这个概念也被迅速普及到前端项目中,在早期前后的没有分离的时期下,并没有明确的路由概念,前端页面跳转大多是通过后端进行请求转发的,比如在Spring MVC项目中,进行一个页面跳转如下(画红线部分): 前端需要一个超链接,链接的href=/manager,这样这个超链接被转发到scs/waitFollowed路径指定的页面. 前后的分离后,前端页面跳转的方式发生了变化,不再需要后端处理了,数据交换方式也改变了,由此前端

随机推荐