中后台组件库Legao在京东慧采项目中的初应用






什么是京东慧采

京东慧采(简称VSP)面向计划电商化转型或需要快速提升企业内部采购协同效率的企业级客户,打造标准化零研发成本或定制化采购管理服务商城,为企业用户提供差异化、可快速对接的企业专属综合集采解决方案。京东慧采可以为用户提供定制化优质服务。

中后台组件库Legao在京东慧采项目中的初应用京东慧采的四大优势中后台组件库Legao在京东慧采项目中的初应用

慧采包含 PC 和 APP 两个平台,此次是针对慧采 PC 进行的改版优化。了解更多慧采的介绍,欢迎移步京东慧采。

改版的起因

自 2015 年至今,慧采 PC 的交互及视觉一直没有变化,存在页面整体交互视觉落后、交互体验繁杂等问题,技术架构已经逐渐难以满足日益增长的业务发展。

从技术客服反馈、区域反馈、数据层面上看,系统从用户登录到下单流程均有不足之处,为了满足日益增长的客户量及客户诉求,亟需对慧采 PC 端做全面体验升级,以便更好的为客户服务。

改版前一个季度统计了涉及 VSP 的 1024 个问题,很多重复性的问题和体验优化问题:

中后台组件库Legao在京东慧采项目中的初应用

面对这么多的问题,项目整体计划通过三个阶段的迭代,对慧采进行全面体验优化,针对客户痛点,有效解决客户问题,进而提升慧采的用户黏性及 GMV 。中后台组件库Legao在京东慧采项目中的初应用

确定了项目迭代计划,那么接下来就需要我们大展拳脚了~

中后台组件库Legao在京东慧采项目中的初应用

技术选型

综合考虑项目的基本情况,我们从基础架构,性能优化两大方面来进行慧采项目的升级改造。中后台组件库Legao在京东慧采项目中的初应用

基础架构

Gaea 脚手架自动化构建项目

Vue 技术栈单页面构建工具。Gaea 构建工具是基于 Node.js 、 Webpack 模版工程等的 Vue 技术栈的整套解决方案,包含了开发、调试、打包上线完整的工作流程。本次采用的是在上一版本基础上进行的全新升级版本,构建速度和性能方面有了质的飞跃。

Legao 组件库快捷开发

开发效率一直是我们开发者重点关注的问题,为了提升开发效率引入组件库是必不可少的。本次项目使用了乐高组件库。

乐高组件库介绍

乐高组件库是 JDC 按照京东中后台设计平台的设计规范打造的 UI 组件库,实现了多技术栈风格统一、功能统一,在 jQuery 、Vue 、React 技术栈都可以使用对应技术栈的组件库来快速开发业务。

中后台组件库Legao在京东慧采项目中的初应用

乐高组件库适用于 PC 端项目,涵盖常用基础组件,也包括一些业务组件。慧采开发使用的是 Vue 技术栈,当然使用的也是 Vue 版乐高组件库。那么我们使用过程中又有哪些趣事呢?

组件库的使用状况

乐高组件库涵盖的组件及使用情况如下:

中后台组件库Legao在京东慧采项目中的初应用

覆盖率

现有 43 个组件,项目中使用多达 29 个,组件库场景覆盖率达 67% 。目前项目只完成了初版,在后续的开发中会有更多的组件可以复用。

适用性

大客户那边的需求大多是和京东零售类似的购物系统或者是中后台管理系统,乐高组件库可以覆盖大部分的业务场景,总的来说在大客户 PC 项目中使用乐高组件库可以明显提升开发效率。

组件库使用过程中也并不是十分的顺畅,由于组件库还在不断的丰富和迭代,在使用过程难免会遇到这样那样的问题。

组件库改进建议收集

组件开发完成一般是很难全面覆盖应用场景的,在实际的业务场景中才更容易发现问题,在项目初期我们就遇到了比较多的组件问题,并进行收集。

每个开发者在使用过程中遇到的问题记录下来,并配有具体的使用案例和场景截图等,反馈问题的方式有两种:

  1. 直接跟组件开发者反映组件缺陷

  2. 汇总整理到项目负责人定期向组件库负责人反馈

组件具体问题举例

在使用组件库的初期我们遇到了下列问题:

中后台组件库Legao在京东慧采项目中的初应用

看到这么多的组件问题,我的内心也是非常崩溃的,但是组件库的初期肯定会有不完善的地方,需要使用者去发现问题,提出问题,从而去完善。

组件有这些问题,但是也不能因为组件问题影响项目进度,那么如何去协调修改呢?

项目进度和组件库完善,同等重要

在开发的过程中必须保证项目的正常进度,不能因为组件库问题给项目带来风险,时候项目进度和组件库完善迭代升级需要同步进行。

在项目开发过程中我们采用了以下流程来合作开发:

中后台组件库Legao在京东慧采项目中的初应用

通过这样的配合,既保证了项目的正常进度,也将组件库进行了完善。

这个项目是 Vue 乐高组件库实战的首个项目,也是对乐高组件库的检验,暴露了很多问题,也修复了很多问题,经过这样一轮的检验,组件库变得越来越完善,再有别的项目使用起来将会更快捷,避免了大家再次踩坑。

TS 规范项目代码

为什么要用 TS 啊?TS 这么麻烦,必须指定数据类型,不指定就报错~~~~ 事实上,这是我在没有被迫在项目中使用 TS 之前的想法,相信这也是很多没有使用 TS 做项目开发的我们的共同心声,希望 TS 原地消失。。。接下来就把我在项目中使用 TS 的一下想法分享给大家,给 TS 洗洗白~~

我们为什么要使用 TS ?

先放张表格给大家感受一下静态类型跟动态类型的差异中后台组件库Legao在京东慧采项目中的初应用

我们都知道 JS 是弱类型语言,很多人会误认为 TS 是强类型语言。我们要明确一点,TS 是有类型的编译到纯 JS 的 JS 超集,这是它最大的亮点。TS 不是「强类型」,是「静态类型检查」的「弱类型」,通俗点说 TS 填充了 JS 作为一门动态弱类型脚本语言的缺点,多了类型检查,能够对代码中的错误及时反馈,但保留的 JS 的灵活。下边我们从代码层面看一下 TS 相较于 JS 的优点:


  1. 编译阶段即可发现类型不匹配的错误:IDE 下可以做到智能提示,智能感知 bug ,不用等到运行时才能发现错误,提高代码的开发效率:中后台组件库Legao在京东慧采项目中的初应用



  2. 类型就是最好的注释:静态类型对阅读代码是友好的;对于编译器来说,类型定义可以让编译器揪出隐藏的 bug 。



  3. 提高重构的效率:比如后端接口一改,要改字段,全局搜索,一个个改;用了 TS 之后,把数据对应的 Interface 改掉,然后重新编译一次,把编译失败的地方全部改掉就好了。中后台组件库Legao在京东慧采项目中的初应用

TS 的一些用法技巧

声明与声明合并

声明

TS 的所有声明概括起来,会创建这三种实体之一:命名空间、类型和值:

  1. 命名空间的创建实际是创建一个对象,对象的属性是在命名空间里 export 导出的内容;

  2. 类型的声明是创建一个类型并赋给一个名字;

  3. 值的声明就是创建一个在 JS 中可以使用的值。

中后台组件库Legao在京东慧采项目中的初应用

可以看到,只要命名空间创建了命名空间这种实体。Class 、 Enum 两个, Class 即是实际的值也作为类使用, Enum 编译为 JS 后也是实际值,某种条件下,它的成员可以作为类型使用;Interface 和类型别名是纯粹的类型;而 Funciton 和 Variable 只是创建了 JS 中可用的值,不能作为类型使用,注意这里 Variable 是变量,不是常量,常量是可以作为类型使用的。

声明合并

声明合并是指 TS 编译器会将名字相同的多个声明合并为一个声明,合并后的声明同时拥有多个声明的特性;

声明的合并包含不同类型的合并,规则略有差别,我们拿最基本的接口举例:

  1. 多个同名接口,定义的非函数的成员命名应该是不重复的,如果重复了,类型应该是相同的,否则将会报错。

  1. interfaceInfo{

  2. name: string

  3. }

  4. interfaceInfo{

  5. age: number

  6. }

  7. interfaceInfo{

  8. age: boolean// error 后续属性声明必须属于同一类型。属性“age”的类型必须为“number”,但此处却为类型“boolean”

  9. }

  1. 对于函数成员,每个同名函数成员都会被当成这个函数的重载,且合并时后面的接口具有更高的优先级。来看下多个同名函数成员的例子

  1. interfaceRes{

  2. getRes(input: string): number

  3. }

  4. interfaceRes{

  5. getRes(input: number): string

  6. }

  7. const res: Res= {

  8. getRes: (input: any): any => {

  9. if(typeof input === 'string') return input.length

  10. elsereturnString(input)

  11. }

  12. }

  13. res.getRes('123').length // error 类型“number”上不存在属性“length”

TS 编译器对于相同命名的声明有合并策略,这个策略能够帮我们实现一些类型定义的复用,比如多个函数定义可合并为一个函数的重载,还可以利用声明合并实现一些复杂的类型定义。一定程度上减少冗余的代码。

让 Vue 识别全局方法/变量

不使用 TS 声明全局方法:

  1. //全局js文件中引入,放入vue原型对象

  2. import{ api } from'./asset/js/request'

  3. Vue.prototype.$api = api;

  4. //组件中使用

  5. this.$api

使用 TS 后,如果还是按照上边的方式引入以及使用, IDE 会提错误,因为 TS 会去 node_modulesh/vue/types 中去找模块声明, API 属性并没有在 Vue 实例中声明。我们可以新建一个 global.d.ts ,用来声明我们需要放在全局的属性或者方法

  1. importVuefrom'vue';


  2. declare module'vue/types/vue'{

  3. interfaceVue{

  4. $api: any

  5. $toast: any

  6. $dialog: any

  7. }

  8. }

这里注意,一定要保证文件中引入了 Vue 。

Type 和 Interface 的区别

使用过 TS 的小伙伴肯定用过 Interface ,把它视为描述对象和自定义类型的工具。从很多地方大家可能也听说过关键字 Type 。显然,Interface 和 Type 在 TS 中可以互换使用,但是它们在许多方面有所不同。

官方的解释:An interface can be named in an extends or implements clause, but a type alias for an object type literal cannot. An interface can have multiple merged declarations, but a type alias for an object type literal cannot.

但是没有太具体的例子。

我总结一下: TS 中的接口描述是某个东西的结构,大多数情况下是一个复杂的对象。另一方面,Type 也可以用来描述自定义的结构,但它只是一个别名,或者换句话说,是自定义类型的标签。

下边我总结一下它们各自可以使用的场景:

相同点:
  1. 都可以描述一个对象或者函数

  2. 都允许扩展

不同点:

  1. Type 可以声明 基本类型,联合类型,元组 的别名,Interface 不行

    
    


    1. // 基本类型别名

    2. type Name= string

    3. // 联合类型

    4. interfaceDog{

    5. wong();

    6. }

    7. interfaceCat{

    8. miao();

    9. }


    10. type Pet= Dog| Cat


    11. // 具体定义数组每个位置的类型

    12. type PetList= [Dog, Pet]


  2. Type 语句中可以使用 typeof 获取类型实例

    
    


    1. // 当你想获取一个变量的类型时,使用 typeof

    2. let list = this.$refs.list;

    3. type B = typeof list


  3. Type 支持类型映射,Interface 不支持

    
    


    1. type Keys= "firstname"| "lastname"

    2. type nameType = {

    3. [key inKeys]: string

    4. }


    5. const test: nameType = {

    6. firstname: "Pawel",

    7. lastname: "Grzybek"

    8. }


    9. // 报错

    10. //interface DudeType {

    11. // [key in keys]: string

    12. //}


  4. Interface 能够声明合并,Type 不能

Vue 多层组件信息通信管理

提起项目中的信息通讯,很多人想到的就是 Vuex ,毋庸置疑的是它的强大功能,但是在慧采项目中,我们还用到了其它的通讯方式,主要是快捷简单。那么在信息通讯这块我们是怎么选择通讯方式呢?主要根据数据的功能和作用进行选择。

Vuex 全局数据管理

使用 Vuex 管理全局信息:

中后台组件库Legao在京东慧采项目中的初应用

Vuex 属于宝刀屠龙类的神器了,所以在使用上我要慎重,只有神器运用的恰当才可以让我们的项目开发更加得心应手,无往不利,如果滥用,例如去用屠龙宝刀去搞一只蚂蚁,还不如直接踩死更加方便。

中后台组件库Legao在京东慧采项目中的初应用

所以我们这个项目中 Vuex 的作用主要就是用来全局数据的管理,主要管理一些接口数据,例如购物信息的变更,头部信息的变更。具体的方法就不在详细的说了想必所有人都了解,我们这里单把 Vuex 如何与 TS 结合说下。

入口文件:

  1. import{ GlobalState} from "./types";

  2. import{ RootState} from "../types";

  3. import{ Module} from "vuex";

  4. exportconst global: Module<GlobalState, RootState> = {

  5. namespaced,

  6. state,

  7. getters,

  8. actions,

  9. mutations

  10. };

没错,通过 Module 实现了模块化 store 它有助于你把不同的数据进行分类。而我们的 TS 规则写在 ./types 里面了,具体如下:

  1. export interface GlobalState{

  2. userInfo: {

  3. [propName: string]: any;

  4. };

  5. permissionInfo: {

  6. [propName: string]: any;

  7. };

  8. addrInfo: any;

  9. fullAddressInfo: any;

  10. cartTag: any[];

  11. isAdded: boolean;

  12. cartType: number;

  13. commonNav: any;

  14. }

这样就为我们的模型定义好了规则,他的使用也非常简单,只要在入口文件

  1. import store from "./../../store";

  2. exportdefaultnewVue({

  3. el: "#app",

  4. store,

  5. render: (h) => h(App)

  6. });

如同上面一样把 store 传到 Vue 里面就可以了。而在具体组件里面可以如下面这样使用

  1. import{ State} from "vuex-class";

  2. @State('global') global:any;

  3. get commonNav (){

  4. returnthis.global.commonNav

  5. }

它等同于

  1. computed:{

  2. commonNav(){

  3. returnthis.$store.state.global.commonNav

  4. }

  5. }

new Vue() 对象实现组件通信说完 Vuex 接下来就说说组件间我们的通信管理,由于项目组件我们拆分的很细致,这样就给通信传参带来了一点点麻烦。通常我们项目中的组件关系是这样的:

中后台组件库Legao在京东慧采项目中的初应用

看着上面一团乱麻的组件关系是不是有种抓狂爆炸的感觉。别急,我们项目的这种方法会安全高效的解决组件间信息通信的难题。

首先我们说下事件的传递:

在总入口文件内重新实例化一个 Vue ,代码如下:js vue.prototype.$public=newVue()这样 我们的 Vue 就有一个全局的新的实例化的 Vue, $public 将会拥有 Vue一切公共,包括数据的劫持和监听,我们主要利用它的 $emit 和 $on 进行新的数据传递,这里为了凸显它的用处,我们这里采用亲属关系来代表组件。

爸爸的妹妹的老公的的堂哥家的表姨夫组件发送:jsthis.$public.$emit('ask','借点钱');

本人组件接受并通知:js created(){this.$public.$on('ask',(msg)=>{console.log(msg)// 借点钱// 不想借this.$public.$emit('backask','不想借')});}爸爸的妹妹的老公的的堂哥家的表姨夫组件接收:js created(){this.$public.$on('backask',(msg)=>{console.log(msg)// 不想借})}

上面的 3 个代码片段就解决了多层级组件数据传播的问题。这样不管组件嵌套的多么深总能第一时间把信息给要传递的人,像现在我们用手机联系,有一种天涯若比邻的感觉。

中后台组件库Legao在京东慧采项目中的初应用

单例模式共享数据

在我们项目中还有一类组件的通信,我先给他描述下它的作用,就是全局搜索组件,它的位置有两个一个是头部,一个是在中间的右侧,它是慧采项目搜索的灵魂每个页面都用到它。那么我们是如何管理多页面中他们的通信呢,这里借用了单例模式思想。通过单例化一个 class 来实现信息共享和方法公用。

实现思路如下:

  1. import{ fetch } from "./fetch.ts";

  2. classSearch{

  3. constructor(obj) {

  4. this.params = {};

  5. this.callback = null;

  6. this.setKeyAdr();

  7. this.init();

  8. }

  9. set(obj) {

  10. // 插入新数据

  11. const param = this.params;

  12. this.params = Object.assign(param, obj);

  13. returnthis;

  14. }

  15. }

使用

  1. Vue.prototype.$search = newSearch();

这样搜索条件的数据就挂载到了 Vue 对象里面,我们在项目中只要使用 this.$search 调用内部的 API 就可以修改里面的数据,同时里面的数据也被我们通过 Object.defineProperty 进行了劫持,提供了 Watch 的方法。它可以是说是一个简单的数据监听的模型。

项目优化

页面加载性能提升

小图标在项目开发中是必不可少的,处理图标的方式也是多种多样,在技术不断更新的同时处理图标的方式也是越来越多,先来一起看一下图标处理的逐步进化。

标签引用链接展示图片

从最原始  开始说起吧,如果说处理图片最简单的方式那可能就是使用 img 标签了。图标也属于图片,当然完全可以使用它,它可以加载浏览器支持的所有格式的图片资源。

它的优势在于:

  1. 方便更换,更换路径或者覆盖原图片即可达到更换图片的目的

  2. 易于控制,可灵活准确控制尺寸

  3. 没有兼容性问题

劣势:

  1. 增加 HTTP 请求次数,图标越多请求越多,会直接影响页面的加载性能

  2. 不易适配终端和分辨率,高分辨率下可能会有锯齿

  3. 不易操作,如颜色、阴影等

  4. 不易维护

这种方式最大的缺陷是会增加 HTTP 请求次数,为了解决这个问题,雪碧图应运而生。

Sprites 雪碧图减少 HTTP 请求网络催化剂

俗称雪碧图,又称 CSS 雪碧、CSS 精灵。它是将多个小图标整合在一张图片上,然后通过坐标位置来控制使用内容,从而减少 HTTP 请求次数。

技术日新月异的今天这种技术还是很流行,很多网站也还在使用,比如我们京东主站。

中后台组件库Legao在京东慧采项目中的初应用

它的优势:

  1. 减少 HTTP 请求次数

  2. 支持任意图形,任意色彩

  3. 兼容性比较好

劣势:

  1. 增加开发时间,需要人肉或通过相关工具,将图形零散的图形合并到一起,而不同的合并方式,图形的色彩对 Web 的性能有直接的影响

  2. 增加维护成本,要增加新的图标合成进来,是件较难的事情,甚至直接会影响到前面又定位好的图片

  3. 图片尺寸固定,当图标尺寸和容器尺寸不一致时,需要使用 background-size调整图标的大小,而 background-size 在 IE8 及以下浏览器并不支持。

  4. img 的问题这里同样会有

雪碧图虽然减少了 HTTP 请求次数,但劣势也是相当明显的,对开发人员来说效率低下,难以维护。

而且随着高清屏幕的出现,同样清晰度的图片在不同分辨率的屏幕下展示效果也不相同,最直观的感受就是图片模糊了锯齿了,要解决这个问题可能会有以下几种方案:

  1. 通过 background-image:image-set('xxx.png'1x,'xxx_2x.png'2x); 来实现 Retina 屏下的图片展示

  2. 通过媒体查询,在不同的屏幕下加载不同的图片

  3. 使用 img 的 srcset 属性

  4. 使用 <ptcture> 标签元素根据不同屏幕调用不同的图像

以上方法除了媒体查询,其他几个有会有兼容性问题,而他们共同的问题是都必须提供对应的图片, image-set 和 媒体查询只适合背景图, srcset 和 picture 只适用于 src 资源加载,这与我们的优化方向背道而驰。

其实发展到现在最主要的问题就是解决屏幕分辨率对图标的影响,字体图标闪亮登场。

Icon Font 小图标

字体图标是一种全新的设计方式,它解决了前两种方式中最重要的两个问题,HTTP 请求次数和屏幕分辨率,而且拥有 Web 字体相关的所有 CSS 属性。如

  1. 使用 font-size 改变字体大小

  2. 使用 color 改变颜色

  3. 使用 text-shadow 给图标加阴影

也正是基于此,越来越多的 Web 开发中使用字体来做图标了。

优势:

  1. 减少 HTTP 请求

  2. 容易缩放且保证清晰

  3. 改变颜色、使用阴影、透明效果变得容易

  4. 兼容性好,CSS 支持度高

  5. 本身体积小

  6. 图片能达成的效果它一样可以

劣势:

  1. 只能使用单色或 CSS3 渐变色,多色组合图标无法使用

  2. 创作字体图标比较耗费时间

  3. 如果使用现成的字体文件可能会文件过大,而使用的很少

  4. 不同设备浏览器渲染的字体会略有差别,跟文字类似,会收到 font-size 、 line-height 等 CSS 属性影响

  5. 在手机上可能与系统字体冲突

对于以上问题,可根据项目的实际场景来综合考虑是否适合使用图标字体。

本次项目是 PC 项目,而设计师提供了图标 svg 那么可以在 iconfont 网站上去生成字体图标文件,然后在项目中使用。

这样可以正常像文字那样使用字体,同时没有多余的图标,不会造成体积浪费。

使用:

  1. @font-face {

  2. font-family: 'common';

  3. src: url('common.eot'); /* IE9 */

  4. src: url('common.eot?#iefix') format('embedded-opentype') /* IE6-IE8 */,

  5. url('common.woff') format('woff') /* chrome、firefox */,

  6. url('common.ttf') format('truetype') /* chrome、firefox、opera、Safari, Android, iOS 4.2+ */,

  7. url('common.svg#common') format('svg') /* iOS 4.1- */;

  8. }


  9. .font_family{

  10. font-family: 'common';

  11. font-size: 16px;

  12. font-style: normal;

  13. -webkit-font-smoothing: antialiased;

  14. -moz-osx-font-smoothing: grayscale;

  15. }


  16. .gouwuche:before {

  17. content: "e072";

  18. }

  1. <spanclass="font_family gouwuche"></span>

就只是这么简单,这些小图标就用上了,并且只需要设置相应的文字颜色,以及 :hover 文字颜色就能实现这种效果,是不是比使用两种颜色的小图片方便太多。

中后台组件库Legao在京东慧采项目中的初应用

不仅如此,如果设计改个颜色,比如主题色不再是红色,那也没有关系,直接将文字颜色改成新的颜色即可,真的是省时省力。

另外的一个最常用到的优势是,无论放大缩小任何倍数,它都是清晰的,不会模糊和锯齿。

离线缓存,沉浸式体验

每个页面都会发送包括图片等在内的大量请求,如果不进行优化,将会影响用户的使用效果,所有我们考虑了一下,决定对每个页面进行请求的缓存优化,首先想到的就是 PWA ; 关于 PWA 的介绍我们这里就不赘述了,大家可以去官网查看。PWA 的内容比较多,可以实现很多逆天的功能:

  1. 后台数据的同步

  2. 从其他域获取资源请求

  3. 接受计算密集型数据的更新,多页面共享该数据

  4. 客户端编译与依赖管理

  5. 后端服务的 hook 机制 … 我们只需要根据自己的项目情况,配置自己需要的部分就可以了。

PWA 之核心 Service Worker

  1. 运行于浏览器后台,不受页面刷新的影响,可以监听和截拦作用域范围内所有页面的 HTTP 请求。

  2. 网站必须使用 HTTPS 。除了使用本地开发环境调试时(如域名使用 localhost )

  3. 单独的作用域范围,单独的运行环境和执行线程

  4. 不能操作页面 DOM 。但可以通过事件机制来处理

  5. 事件驱动型服务线程

Service Worker的生命周期简单来讲,可以分为四个部分:注册(解析)–安装–激活–废弃 意思是在我们输入 url 键入回车,Service Worker 就会进行注册,注册成功后会进入安装状态,最后安装成功,进入已激活状态之后,此时的 Worker 已有控制页面的行为, 可以处理一些功能事件, 比如 Fetch , Push , Message… 我们是做缓存处理,使用 Fetch 。另外,Cache 是 Service Worker 衍生出来的 API ,配合 Service Worker 实现对资源请求的缓存。不过 Cache 并不直接缓存字符串,而是直接缓存资源请求( CSS 、 JS 、 HTML 等)。

  1. //检查资源是否匹配如果匹配那么就本地加载如果不匹配就服务加载

  2. self.addEventListener('fetch',event=>{

  3. event.respondWith(

  4. caches.match(event.request).then(res=>{

  5. if(res){

  6. return res

  7. }

  8. return fetch(event.request)

  9. })

  10. )

  11. })

配置完了,我们看下效果:配置前:中后台组件库Legao在京东慧采项目中的初应用配置之后:中后台组件库Legao在京东慧采项目中的初应用配置起来比较简单,可以看到很多静态资源都是从 Service Worker 里获得的,效果还是不错,大家项目中可以多尝试使用。

ESLint代码格式化与自动检测

ESLint 是代码规范检查工具,可以辅助开发人员规范代码风格

注意:ESLint 查找自己配置文件的优先级如下

  1. .eslintrc.js

  2. .eslintrc.yaml

  3. .eslintrc.yml

  4. .eslintrc.json

  5. .eslintrc

  6. package.json

如果项目中存在多个配置文件则 ESLint 先检同级下的 配置文件然后在找别的,选择原则就是就近原则。

例如:如果在你的主目录下有一个自定义的配置文件 (~/.eslintrc) ,如果没有其它配置文件时它才会被使用。

如何自动修复代码

–fix 是自动修复功能 –ext 是用来传后面的配置 .ts,.vue src 意思是对 src 下面的 .ts,.vue当我们执行 npm run lint 时候 系统会直接使用我们根目录下的 .eslintrc.js 对当前的目录下的文件进行检查和提示。这时候我们执行 lint 控制台就会把有问题的代码呈现给我们,同时 ESLint 提供了一个格式化配置,可以把有问题的代码按照我们想要的样子给我们具体配置如下

  1. //package.json 项目根目录

  2. {

  3. "scripts":{

  4. "lint": "eslint --format codeframe --fix --ext .ts,.vue src"

  5. }

  6. }

–format 后面可以跟下面的值

  • checkstyle

  • codeframe

  • compact

  • html

  • jslint-xml

  • json-with-metadata

  • json

  • junit

  • stylish

  • table

  • tap

  • unix

  • visualstudio

不同的配置会有不同的结果样式,具体大家可以自己试试

配置说明

在开始详细介绍前我把我项目中的配置发到了下面,并删除了很多个性化的配置只留下了比较常用的场景,和不同的配置风格,方便大家理解并自行扩展。

  1. module.exports = {

  2. "root": true,

  3. "extends": "eslint:recommended",

  4. "env": {

  5. "browser": true,

  6. "es6": true

  7. },

  8. "parserOptions": {

  9. "ecmaVersion": 7,

  10. "sourceType": "module",

  11. "parser": "@typescript-eslint/parser",

  12. "ecmaFeatures": {

  13. "legacyDecorators": true

  14. }

  15. },

  16. "parser": "vue-eslint-parser",

  17. "plugins": ["prettier"],

  18. "rules": {

  19. "prettier/prettier": [ 1, {

  20. "printWidth": 80,

  21. "tabWidth": 4,

  22. "useTabs": false,

  23. "singleQuote": false,

  24. "semi": true,

  25. "trailingComma": "none",

  26. "bracketSpacing": true,

  27. }],

  28. "no-debugger":[1],

  29. "arrow-spacing": [

  30. 1,

  31. {

  32. "before": true,

  33. "after": true

  34. }

  35. ],

  36. "no-dupe-args":[1]

  37. }

  38. }

  1. root 默认情况下, ESLint 将在所有父文件夹中查找根目录中的配置文件。如果您希望所有项目都遵循特定惯例,但有时会导致意想不到的结果,这会非常有用。要将 ESLint 限制为特定项目,请将其 “root”: true 放在文件的eslintConfig 字段内 package.json 或 .eslintrc.* 项目根目录下的文件中。一旦找到配置, ESLint 将停止在父文件夹中查找 “root”: true 。

  1. module.exports = {

  2. "root": true

  3. }

  1. extends 属性我们在很多场景下都会见到,意思就是扩展。但是在 eslint 中它还有别的用途,

  1. module.exports = {

  2. "extends": "eslint:recommended"|| "eslint:all",

  3. }

"eslint:all" 用于启用当前安装的 ESLint 版本中的所有核心规则。核心规则集可以在任何次要或主要版本的 ESLint 中更改。注意: 不建议将此配置用于生产用途,因为它随 ESLint 的每个次要版本和主要版本而变化。使用风险自负。所以推荐使用 "eslint:recommended"

  1. env ESlint 可以让我们选择支持的 JS 语言,我这个项目是浏览器项目,同时使用了很多新的特性,所以我的配置是

  1. module.exports = {

  2. "env": {

  3. "browser": true,

  4. "es6": true

  5. },

  6. }

"es6":true 会启动 ES6 语法规则检测,这时候就需要 parserOptions 进行详细的配置

  1. module.exports = {

  2. "parserOptions": {

  3. "ecmaVersion": 7,

  4. "sourceType": "module",

  5. "parser": "@typescript-eslint/parser",

  6. "ecmaFeatures": {

  7. "legacyDecorators": true

  8. }

  9. },

  10. "parser": "vue-eslint-parser",

  11. }

ecmaVersion – 设置为 3 , 5(默认), 6 , 7 或 8 以指定要使用的 ECMAScript 语法的版本。您也可以设置为 2015 年(与 6 )相同,2016 年(与 7 相同)或 2017(与 8 相同)使用年份命名。

sourceType- 设置为 “script” (默认)或者 “module” 您的代码位于 ECMAScript 模块中。

parser 解析器,例如我的项目是 Vue + TS 版 我用的就是 @typescript-eslint/parser 如果是普通的可以写成 babel-eslint

而在外面还有一个 parser 我的项目是 Vue 项目于是选择解析器 "vue-eslint-parser"

注意:在 npm 下载这些解析器的时候要匹配好相应的 ESLint 版本。

  1. 在 ESLint 中使用插件 例如 prettier

我们只要下载好插件 然后在 rules 里面配置好就可以用了,具体配置如下

  1. module.exports = {

  2. "plugins": ["prettier"],

  3. "rules": {

  4. "prettier/prettier": ["error", {

  5. "printWidth": 80,

  6. "tabWidth": 4,

  7. "useTabs": false,

  8. "singleQuote": false,

  9. "semi": true,

  10. "trailingComma": "none",

  11. "bracketSpacing": true

  12. }]

  13. }

  1. rules 配置规则

这个配置方案挺简单,规则比较简单 例如:

  1. "no-debugger":[1],

  2. "arrow-spacing": [

  3. 'error',

  4. {

  5. "before": true,

  6. "after": true

  7. }

  8. ],

ESLint 所有的 rules 配置都是一样的 ,它接收一个数组对象 ary

ary[0] 代表规则级别,可以理解为规则的严重程度,具体如下:

“off” 或者 0 – 关闭规则 “warn” 或者 1 – 将规则打开为警告(不影响退出代码) “error” 或者 2 – 将规则打开为错误(触发时退出代码为 1 ) 可以是 string 也可以是 number

ary[1] 配置该规则的具体描述,每个规则都有独特的描述如果不清楚就不要配置了。

结语

截至目前,慧采 PC 项目优化升级已经进行了 3 个多月,为了优化用户体验,提高页面加载性能,提高开发效率,我们也经历的很多的挑战,但看到项目按照迭代计划顺利上线,我们还是很受鼓舞的。当然,项目优化之路还没有结束,我们会一直保持激情,不断提升自己的技术水平,确保用户体验更上一层楼~


本篇文章来源于微信公众号:京东设计中心JDC

UI/UX

二手房交易体验升级“核武器” - 线上视频核签设计揭秘

2020-8-19 11:30:00

UI/UX

夜校技巧荟Vol.11 | Nucleo-专属于你的图标管理工具

2020-8-20 9:30:00

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索