前言
我们之所以拥抱Vue.js以及React等MVVM框架,原因有很多,其中重要的一条就是:优雅,容易维护。而初学者在使用了Vue.js之后,代码依然是一团面条,这显然还有很大的提升空间。现在我们研讨一下,如何让你的Vue项目看起来十分的牛逼?
我来列一列:
发誓:不重构一次就自杀
在你会用Vue写出一个项目之后,你要做的并不是去写第二个项目,而是不断思考:如何重构。
你对前一个项目的重构绝对是值得的,你之后的所有项目都会获益。
有句圈内名言是:“程序员看自己一个月前的代码,都有种想吐的感觉”,这很正常。一个项目除了基本维护,还要有重构的心,当然了,重构的工作量是相当大的,可能会相当于第一次开发时间的30%-80%甚至更多,所以一定要制定计划,还要有心理准备。
多学习高star的开源作品
作为初学者,你身边不太可能有很多大牛,毕竟大牛云集的公司也没你的容身之处。我比较推荐的学习对象是github,去上面找高star的开源作品,这些作品的水平是经得住检验的。
封装!再封装!
封装是让代码看起来优雅的最有效办法,没有之一。当你不知道怎么重构,那么,先封装。
将一切能复用的代码全都封装起来,存到另外的文件中,然后import。包括:
- 组件
- 混入
- 工具
- ajax
等等。
最后,让你的page(或者叫view)文件夹里的每个.vue文件的js行数不超过100行,css行数不超过100行,就是最合适的,你的代码如果能给人这种感觉:“卧槽?外观看着复杂的页面,vue文件就这么几行代码?”——恭喜,你成功了。
拆分
封装肯定要拆分,但拆分不一定都是封装,有时候只是将大文件拆分成多个小文件。
我们都知道,对人脑来说,最一目了然的“索引”,就是目录和文件名,因为你连文件都不用打开,就能知道这个文件是干什么用的,这样维护一个项目无疑是优雅的。
比如,一个项目的scss文件,就可以这么拆分:
完全不用解释,也不用打开文件看内容,我就一定知道这些文件的代码大致会是什么样的,是负责什么职责的。
同样的,公用js文件也可以拆分,比如utils.js、modal.js等等。就比如这个modal.js,可能代码不超过50行,功能也很单一,就是负责弹出对话框,但是依然单成为一个文件,你会问,这么做值得么?值。它负责了一个很常用的、无歧义的功能,又不算utils,因为utils主要是做一些计算函数,比如格式化时间戳、比如对js原生函数做一些补充,等等。更何况,modal.js可能还包括若干种使用场景,比如它的content可能是文本,也可能是表单,那么你的弹出框函数可能要准备2个,一个是基本弹出框,一个是带表单的弹出框,所以整体下来可能70、80行都有可能,值得单成一个文件。
最后差不多是这意思:
- scss
- - base.scss
- - icon.scss
- - index.scss
- - mixin.scss
- - reset.scss
- - variable.scss
- config.js
- utils
- - ajax.js
- - modal.js
- - utils.js
- - ......
page文件夹的目录结构
业内通常做法是根据page的名字先命名文件夹,然后里面放一个跟page名字相同的.vue文件。也就是:
- page
- - home
- - - home.vue
- - search
- - - search.vue
然后,再考虑home.vue的组件存放在哪,以及home的某个子页存放在哪,这时候业内的习惯就有不同说法了,而我的建议是:
一、能复用的组件当然要拆分。
二、不能复用的组件封装不封装呢?看情况而定。假如不封装,全写在home.vue里,依然能保持home.vue足够整洁,那么就不要封装,否则,就可以去封装。
对于复杂的页面,就比如仿美团的webapp的首页,肯定是很复杂的,这个可以拆分组件封装起来。
三、组件放在哪里?我建议:放在跟page并列的components文件夹里,也就是:
- components
- - home
- - - home-slider.vue
- page
- - home
- - - home.vue
- - search
- - - search.vue
所以,components文件夹不一定包含所有page的组件。
这个方案的优势:
开发者和阅读代码者,永远将目光放在page文件夹,不要被其他任何文件夹分心,也就是说,page相当于主干道,而其他文件夹、其他文件相当于小路,小路用到的时候自然回去查阅怎么走,用不到的时候,永远不要出现在宏观视野里。
有些人的方案是,在page\search文件夹建一个components目录,然后放组件,这样的劣势很明显,乱,IDE的左侧目录树里各种components文件夹。
四、子页面放哪里?实践中你会发现,比如一个search页面,它其实还分成多个page来辅助,这些子页面怎么存放?根据上个自然段的原则,就很好办了:放到search文件夹就可以了。比如:
- components
- - common ------ 公用组件,不多说
- - home
- - - home-slider.vue
- page
- - home
- - - home.vue
- - search
- - - search.vue
- - - search-setting.vue
- - - search-setting-xxx.vue
而有些人的做法是,建立一个children文件夹:
- components
- - common ------ 公用组件,不多说
- - home
- - - home-slider.vue
- page
- - home
- - - home.vue
- - search
- - - search.vue
- - - children
- - - - setting.vue
显然,用children文件夹,就不符合“一目了然”的原则,因为还要打开子目录才能看清全貌,甚至children里面还有children,结果满眼的children。
总之,如果你对别人说“我维护了一个80多页的大项目”,那么,你的page文件夹里有80多个vue文件就没错了,不要有多余的文件,不要有复杂的子目录,这样无论对开发者、后继维护者、吃瓜群众来讲,都是最好的目录架构。
怎么对待vuex
你可能有N种选择:
- 干脆不用vuex
- 用简单用法,一个store.js搞定
- 用高级用法,index.js、state.js、getter.js、action.js、mutations.js、mutation-types.js一个也不能少
- 再加上module和其他高级用法
怎么选,需要你跟你的团队商定。我觉得吧:
- 单人开发:不用vuex,或是简单模式足够,无论项目有多复杂。
- 多人开发,还是用高级用法和更高级用法为妙。
注释
给函数和类做注释是一个好习惯,通常注释长得像这样:
/**
* 干什么什么用途的
* @param {Sting} url
* @param {Sting} title
* @param {Number} w
* @param {Number} h
* @return {number} 返回XXX
*/
如果你用VS Code,当你写好一个函数或者类,紧贴这个函数或者类的上一行敲入/**
,会有一个JSDoc提示,自动抓取该函数的参数。
VS Code官方介绍是:https://code.visualstudio.com/Docs/languages/javascript#_js-doc-support
当你紧贴函数敲入:
就会形成:
可见,自动生成的注释只是个半成品,你需要:
- 注意到上面有一个空行了么?这里写函数的用途
- 将星号换成数据类型,比如
Sting
、Number
- 每个参数后面都可以加解释,例如
* @param {Sting} url 请求地址
- 如果有返回值,可以最下方新增一行,写上
* @return {number} 返回XXX
可能你见过更为复杂的注释,比如有作者、最后编辑时间等,也可以加上:
/**
* 干什么什么用途的
* @author 某某某
* @lastModified 2019.3.15
* @param {Sting} url
* @param {Sting} title
* @param {Number} w
* @param {Number} h
* @return {number} 返回XXX
*/
都是可以的,更为复杂的内容我认为就没必要加了。
如果你需要使用JSDoc生成API文档,那时候你才需要仔细研究JSDoc的每一个细节。
ESLint
无论对于什么层级的选手,ESLint都属于又爱又恨的东西,当你正在思考复杂的逻辑的时候,它突然给你来个“没有敲空格”的提示,你说难受不难受?但是,又不能不用。
其实网上已经有很多的文章介绍正确的ESLint用法,简单说:
- 平时关掉ESLint,做法是去相关配置文件注释掉关于ESLint的配置
- 只在阶段性编程任务完成之后,再取消注释,然后一次性排查所有错误
其他细节
其他细节就不好总结了,需要慢慢积累。
比如template里面的插值表达式,你是用{{ xxx }}
这种写法,还是{{xxx}}
?显然,前者看着更舒服。但是,是不是凡是能空格的地方全空格呢?又不一定。
总之,多学习,多积累,你就能够写出漂亮优雅的代码。