从头搭建一个 Vue.js 项目工程

2 个月前

前言:

在很多人眼里能用 vue-cli 脚手架直接搭建 Vue.js 项目工程很爽,很方便,但是当遇到问题的时候我相信会有一堆人一脸茫然,有时候会不知所措。而我不喜欢用别人准备好的架子,无论做什么项目必须从0到1的搭建起来,每次构建项目体系的时候如同搭积木一般,每次积攒不同的技术实战经验。我一直认为:“只有自己亲身体验才能印象深刻的理解,才能控制住局面,才能成长!”。之前一直使用的是 React 体系做项目,但最近我经历了几次vue体系的项目获取了很多知识,也产生了浓厚兴趣,Vue.js 是一套构建用户界面的渐进式框架,而一个网站所涉及到元素很多,单纯一个 Vue.js 库是不足以支撑,它需要结合很多不同的库去做一个生态体系,比如(路由、数据源、UI组件等),下面我来总结一下我的经历,如果有欠缺的地方可以反馈给我,相互学习成长!

Vue.js

我使用的版本是v2.3.3

路由(vue-router)

vue 生态系统中的路由(vue-router)是我们在做vue.js单页面应用体系必用到的机制,这里经常会用到以下几种:

动态路由

const router = new VueRouter({
  routes: [
      path: '/',
      component: resolve => require(['./pages/Home.vue'], resolve)
  ]
})

路由重定向

有些场景也需要重定向(redirect)来做默认路径配置

const router = new VueRouter({
  routes: [
        path: '*',
        redirect: '/index'
  ]
})

嵌套路由

这种场景最常见,尤其是组件存在父子关系的时候,我需要在路由里面也配置出相对应的关系结构

const router = new VueRouter({
  routes: [
      path: '/regist',
      component: Regist,
      children: [{
            path: 'index',
            component: resolve => require(['./pages/Regist.vue'], resolve)
      }]
  ]
})

编程式路由

有些场景需要在js里面去控制路由的跳转

router.push({ name: 'user', params: { userName: 'Stars' }})

有时候会在template里面去控制路由

<router-link :to=""></router-link>

我在一个项目中会经常用到这些形式的路由操作,在调用路径时候基本使用异步加载方式。

数据源(vuex)

vuex是vue生态系统中管理数据源的库!它提供了状态树(state),这里定义了全局的数据结构,但在使用中不是什么数据都往这里塞,需要慎重考虑!同时提供了mutations事件操作改变数据源,这是唯一的改变state数据的方式,或者使用异步操作的action,通过触发store.dispatch()找到action中定义的函数,此函数再触发mutations中的函数去实现数据改变。其次当我们项目体系复杂的时候,光靠一个state管理很不方便,vuex提供了modules机制,让我们可以管理多个状态树,达到支撑复杂场景的应用,而我现在用的方式就是多modules来管理,对于每个大模块做了一个modules,参考官方例子,一看便知道。

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

数据分为2种:动态数据和静态数据,在vuex我只放动态数据,把静态数据放入到vue.js的data里面,我是这么划分的,如果有更好的意见可以微博上联系“前端艺术者”。

UI组件库(iview)

在vue生态体系里面有很多专业的UI组件库,比如Element ui、Mint ui等一些,虽然很多组件的交互大体相似,但我个人觉得iview元素设计方案很漂亮,所以就选择了。iview的css样式是基于less,并提供了主题可定制化方案。

@import './src/styles/index.less';

// 下面是要覆盖的变量,例如:
@primary-color: #333;

更多的配置信息在 https://github.com/iview/iview/blob/master/src/styles/custom.less iview现有的组件已经足够支撑我们很多业务场景需求,如果需要拓展我也可以在iview基础上再编写新的UI组件

vue-bus

经常会遇到2个平级组件之间的通讯,vue-bus提供了一个全局事件中心,并将其注入每一个组件,可以像使用内置事件流一样方便的使用全局事件,这样就解决了平级组件之间无法通信的问题。但是vue-bus的使用需要合理的规划和规范,比如请求接收的事件名,比如严格规定使用场景,不能平凡,无章法的使用,为了以后维护思路更清晰,乱用会造成“蜘蛛网式”混乱。

数据获取(axios)

我在vue.js社区咨询过,现在基本使用axios来做获取数据操作,放弃使用vue-resource,通过几个项目中的实践,感觉axios用起来很顺手,在POST请求的时候需要配合“qs”插件来做,遇到跨域场景我使用CORS方式,需要浏览器和服务器同时支持,axios里面的withCredentials配置可以控制,因为axios源码里面是基于XMLHttpRequest对象来实现。

//axios部分源码
var request = new XMLHttpRequest();

// Add withCredentials to request if needed
if (config.withCredentials) {
 request.withCredentials = true;
}

而服务器端需要针对“Access-Control-Allow-Origin”、“Access-Control-Allow-Credentials”、“Access-Control-Expose-Headers”去设置配置好即可,总体来说简单快捷。

PostCSS

之前Less、Sass都使用过,这次我的css方案选择PostCSS,它已经出现了一段时间了,并且有些大公司开始实践了,为此买了一本《深入PostCSS Web设计》自学并实践,这里简单介绍一下,不细说了:

  1. PostCSS 提供核心工具
  2. PostCSS是基于node.js构建一个css插件化的平台
  3. PostCSS不是一个预处理器也不是一个后处理器

性能看下图便可知道

postcss.3c29e8a655fd.png

注:此图来自css专家“大漠”授权使用

在使用过程中会用很多插件:

  1. 比如解决css全局作用域问题使用PostCSS-modules
  2. 比如经常会清除浮动,可使用postcss-clearfix
  3. 比如要像Stylus,Sass或Less一样编写css结构,可使用PreCSS
  4. 比如项目中会加载很多样式表,可使用postcss-import将样式表合并成压缩成一个
  5. 比如页面中我们会直接用html+css实现一个小图标的操作(如三角形,圆形等)可以使用postcss-circle
  6. 比如你想简写css属性名使用postcss-alias,代码示例如下:
//编写css代码
@alias {
  bg: background;
}

.set-bg {
  bg: red;
}
//转译后css代码
.set-bg {
  background: red;
}

还有很多插件,postcss也提供了编写插件的方式,可以自定义一些新的postcss插件去丰富css体系,在使用期间遇到一些问题请教了"大漠",让我脑洞大开并顺利的解决。

二维码

我们的业务场景会用到二维码展示,所以找到了qrcode.vue来解决此场景,这个插件使用简单不多说

国际化(i18n)

前几天听了小春分享的i18n体系真是感悟颇深,他们使用场景较复杂,涉及的国家语言种类多,更全面,而我使用的是vue-i18n来处理,我们的翻译语种不多,就英文和中文切换,下面的zh.js和en.js就是语言脚本文件

import Vue from 'vue'
import VueI18n from 'vue-i18n'
import Zh from './zh.js'
import En from './en.js'
Vue.use(VueI18n)


export function createI18n() {
    return new VueI18n({
        locale: 'zh',
        messages: {
            'zh': Zh,
            'en': En
        }
    })
}

在使用过程中遇到一个问题,在页面切换的时候如果使用iview组件展示就会报错,查出原因是vue-i18n解析报错!一脸蒙~在github上面有人说换版本vue-i18n的版本,但我试一下无效,也请教了vue-i18n作者,后来找到新的方式并解决了i18n和iview的冲突,具体代码如下:

 //在vue组册iview的时候做一下处理
Vue.use(iView, {
    i18n: (key, value) => i18n.vm._t(key, value)
})

代码规范(Eslint)

这个工具一开始我是不喜欢使用的,后来为了让团队编写代码更规范些,把Eslint加进了项目工程,在以前没有这些工具的时候,我们都是输出一份规范文档,大家都是按此文档上的规范定义去执行,但是也不乏有些人不愿意去做。现在有了工具强执行机制,做到了更好的约束。我在使用的时候有2种选择:

1.配置一套规范
2.继承airbnb的规范

最终选择了配置一套规范更符合团队需要。

如果想看Eslint的报错日志集合可以在使用一个命令,会在项目根目录下生成一个名为eslint.report的文件

eslint --ext .js,.vue --format unix -o eslint.report src/**; echo

webpack打包

这个打包工具做前端的再熟悉不过了,很好的帮我们把代码压缩,也可以打包在一个文件夹里,里面有单独的css文件,分包压缩的js,转成base64码引用的图片等文件。

BundleAnalyzerPlugin

为了看清楚打包情况,会使用这个插件来生成一个打包详情图,分析打包情况,可以针对打包情况做分包的优化。

f1.0363b256c98e.png

HtmlWebpackPlugin

我想把入口的html文件也打包到指定目录下,并自动加上打包后的css,js的引用,这时候就用到HtmlWebpackPlugin插件来解决。

总结

我开始涉及做vue.js项目时间较晚,通过这几次磨练,不断的加深理解,不断地实践,不断地看源码分析,vue.js是渐进式框架,我也是渐进式学习vue.js。当中遇到坑,基本都是靠自己解决掉!对我来说这是最好的技术成长,最好的收获,其次用vue.js做过渡动画的时候可以结合animate.css提升UI交互效果,真心的感觉非常棒!后续我们还有拓扑图的场景开发,我打算用vue.js+d3.js来完成效果,现在暂时用echarts去支撑,还有建站场景的开发,用vue.js完全没问题!前端是一条非常折腾的路,保持激情的心态走下去!

6
推荐阅读