前端vue2 element ui高效配置化省时又省力

目录
  • 前言
  • 一、场景介绍
    • 1. 业务场景
    • 2. 配置化想法萌生
  • 二、设计 & 实现
    • 1. 设计协议
    • 2. 实现渲染器
    • 3. render函数 & 配置数据
    • 4.丰富组件能力,实现业务
  • 三、配置静态化

前言

这篇文章是笔者曾经全盘负责了接近一年的广告投放系统沉淀下来的开发经验,大家各取所需,不喜勿喷~当然啦,有自己的见解、更好的建议的大牛朋友们,我们评论区见~hhh,大多提点高见,让笔者继续学习继续进步!

本文从 场景介绍 、 设计&实现 、 性能优化 三个部分进行讲解。笔者当时的技术栈是 vue2 + element-ui,文章案例也是(其实大家不必纠结于技术栈,掌握设计的思路和理念,什么框架都是一样的)。主要能解决的问题就是 提高代码复用能力、提升开发效率,特别是需要开发多个大型表单系统的,配置化可以极大的提升效率,让你上班摸鱼不再是梦想!为了早点下班,我们接着往下看吧!

一、场景介绍

1. 业务场景

如何定义「巨型」表单,这个因人而异。但如果只是一些:收货人信息、登陆、注册的这种比较简单的表单,那肯定算不上巨型,直接常规开发写模版就好了,没有必要为了配置化而配置化~

从笔者的理解出发,表单项非常多,比如笔者曾经负责的「投放系统」,随随便便提交时都会涉及几十甚至上百个字段,这样整个表单会有几十、上百个表单项组成,这就算得上是巨型表单了。

先给大家看看成品的其中的一小块截图~

别看到截图好像表单项也就那样,根据右栏数起来共40+个,但是这个只是初期版的,还有很多字段是没接进来的;而且很多表单项之间有联动、可增删,还有很多表单项是隐藏的

相信你很难想象,其实你只要进行简单的配置,就能实现上图的界面。比如下图的 js对象 就是上图的其中几个表单项的配置:

大家已经不难看出,配置化思路其实就是对表单项进行了抽象,制定了一份协议去描述每个表单项。具体对象中的每个属性有什么用,这个笔者稍后讲自己的设计思路时再详细介绍~

这时候你一定会有疑问,为什么要抽象、为什么配置化的方案更好,我们接着往下看~

2. 配置化想法萌生

高复用、好维护。是的,笔者用配置化方式开发表单,完完全全就是为了高复用、可维护性,然后提升开发效率,解放生产力。

  • 高复用:相似的业务逻辑进行统一处理,复用在相似领域的业务场景。如果说投放系统只需要接入一个渠道,那真的写 template 一把梭就完了。但事实上却不是这样的,当你接入了第一个 facebook ,你发现后面还有 tiktok 、 巨量引擎 、 广点通 等各种媒体渠道...
  • 可维护:实现配置代替开发。即使把配置抽离,交到非技术人员处,其根据协议一样能实现表单项的增删,完成业务。并不是把东西做出来就完事了。首先,渠道方会有新配置功能推出,这个是不可控的。其次,系统开发时并不是全字段接入,而是先接入业务方所需要的核心配置,所以后期会有很多接入新的字段需求。

接下来举两个例子来说说,高复用、好维护体现在哪里

  • 表单1。代码如下:
<el-form ref="form" :model="form">
  <!-- 当活动区域的值为 “area1” 时, 活动名称才展示 -->
  <el-form-item label="活动名称" v-if="form.area === 'area1'">
    <el-input v-model="form.name"></el-input>
  </el-form-item>
  <el-form-item label="活动区域">
    <el-select v-model="form.area" multiple>...</el-input>
  </el-form-item>
</el-form>
  • 表单2。虽然跟 表单1 很相似,但又存在不同。比如 表单2 的活动区域不叫 “活动区域” ,且 表单项 之间的联动关系有所不同,我们接着使用 copy大法 来做,代码如下:
<el-form ref="form" :model="form">
  <el-form-item label="活动名称">
    <el-input v-model="form.name"></el-input>
  </el-form-item>
  <!-- label变成 “活动2”,且需要填写name后才能操作,且是多选 -->
  <el-form-item label="活动2">
    <el-select
      v-model="form.area"
      :disable="form.name"
      multiple
    >...</el-input>
  </el-form-item>
</el-form>

copy大法虽然好使,但是我们的复用能力基本就没了,所有功能都近乎是重新开发,这使得非常的被动。别看上面举例好像很轻松就能实现,笔者说过了,我们将要开发的是一个上百项表单项的系统,当模版的量堆积到一定程度时,你会想吐血。好不容写了上千行模版,以为完事了,结果再接一个新的媒体,又是从一个新的开始......并且,你要再写一个上千行的 template 和各种表单项之间的联动逻辑,也是很痛苦的...

所以,怎么 提升复用能力 , 怎么让复杂的表单 变得清晰好维护,就是笔者的出发点的~

二、设计 & 实现

1. 设计协议

首先我们思考下我们的每个表单项目需要一些什么:

  • type 类型。比如 input 、 select 、 radio 等等
  • label 表单项的名称/描述。
  • formKey 字段名。我们提交数据到后段的字段名,比如 form.name 的 'name'
  • value 存放表单值。表单上 v-model 所绑定的值
  • options 配置项。比如配置 multiple 、 disabled 、 是否显示 等等

好了,有了以上这些点,我们试着把案例中的 表单1 用协议表达出来:

<el-form-item label="活动名称" v-if="form.area === 'area1'">
  <el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="活动区域">
  <el-select v-model="form.area">...</el-input>
</el-form-item>

我们可以用协议这样去描述它

[
  {
    type: 'el-input',
    label: '活动名称',
    formKey: 'name',
    value: '', // 默认值为空字符串
    options: {
      vIf: [
        // 表示:当 form.area === 'area1',才显示
        { relationKey: 'area', value: 'area1' }
      ]
    }
  },
  {
    type: 'el-select',
    label: '活动区域',
    formKey: 'area',
    value: 'area1',
    options: {
      multiple: true
    }
  }
]

是不是有点内意思了?如果把 开发巨型表单系统 转换成 编写JSON ,是不是很爽?

2. 实现渲染器

配置是有了,但是怎么把配置转换成我们真实的表单呢?如果直接开干,我想大部分可能会先这样下手,比如:

<template>
  <el-form-item :label="props.label">
    <el-input
      v-if="props.type === 'el-input' && ...业务联动逻辑"
      :disabled="props.disabled"
      v-model="props.value"
      ...
    />
    <el-select
      v-if="props.type === 'el-select' && ...业务联动逻辑"
      :disabled="props.disabled"
      multiple="props.multiple"
      v-model="props.value"
      ...
    >...</el-select>
  </el-form-item>
</template>

好了,大家观察一下上面的 template 中,有没发现很多冗余的代码。如果我们需要给组件传入 props 比如例子中的 disabled 、 multiple ;控制 v-if 等等。。我们有多少个组件,这些重复的代码就要写多少次。如果以后有需要给所有组件传多一个 props,我们就要编辑n次~记住!我们配置化就是要提高效率的,所以这样是不行的~

在此,笔者就建议编写 render函数。render函数 的场景 & 对应的好处,大家可以看看 官方文档 对其的讲解~

  • 这里不会深入介绍 render函数 ,如果还不知道的,大家只需要记住:Vue 只认 render函数,平时我们 .vue文件 写的 template ,经过编译之后就是 render函数
  • render函数 作用就是返回一个 vNode。我们 vue2 初始化项目时写的: render (h) => h(App)是不是就似曾相识了呢?

都说 React 写 jsx 比 Vue 写 template 更好写逻辑,那我们也用 render函数 ,好写逻辑~ (当然,如果你对render函数不是特别熟悉,那么写template也是可以的)

接下来,我们看看,如何通过render函数,把我们的表单项做出来,以上述案例其中一个为例子:

<el-form-item label="活动名称">
  <el-input v-model="form.name"></el-input>
</el-form-item>

这一段要怎么通过render函数表述出来?根据官方文档,我们理清三个参数是什么就可以了:

createElement(
  'div', // {String | Object | Function},一个 HTML 标签名、组件选项对象,或者...
  {}, // 一个与模板中 attribute 对应的数据对象
  [] // {String | Array},可以理解成时 children 节点
)

接着,我们直接开干:

<script>
export default {
  name: "FormItemDemo",
  render(createElement) {
    return createElement('el-form-item', {
      props: {
        label: '活动名称'
      }
    }, [
        createElement('el-input') // input组件
    ])
  }
}
</script>

在 App组件 中引用这个 FormItemDemo组件,代码如下

<template>
  <div>
    <el-form label-width="100px">
      <FormItemDemo />
    </el-form>
  </div>
</template>
<script>
import FormItemDemo from "./components/FormItemDemo.vue";
export default {
  name: 'App',
  components: { FormItemDemo }
}
</script>

这时候,页面上就出现了我们的 input表单项 了

初始工作已经做完了,接下来的就是让我们把 render函数 的一些动态数据用变量代替,跟我们的 配置config 结合起来。

️️️注意,render函数很灵活,第一个参数可以是字符串、组件对象、function。大家不要被demo所局限,很多场景是需要我们定制一些组件,然后应用到我们的配置化中,而不是直接使用element-ui的原生组件。笔者项目中用的组件都是经过业务场景封装后export出来的组件对象,再配置到type中,最后render函数接收的是一个组件对象,具备业务能力的组件。因此,我们可以在自己实现的组件中定制自己的业务逻辑。

3. render函数 & 配置数据

要说 render函数 也不是真的完美,毕竟要自己去实现譬如 v-if 、 v-model 这种指令,但是没问题,它带给我的便利给大,所以我能接受。

正式演示配置化的实现时,笔者先声明一点:这里的只是 demo 级别的,具体实战到项目要根据业务场景。笔者做业务时,是对 select 、 cascader 等组件都封装了一层。因为很多时候我们的下拉数据要去后端拿,封装后组件可以通过传入的 params 和 urlPath 去获取数据。所以,大家更要关注思路,然后根据业务场景自己去思考、实现即可。

首先配置数据如下:

export default [
  {
    type: 'el-input',
    label: '活动名称',
    formKey: 'name',
    value: '', // 默认值为空字符串
    options: {
      vIf: [
        // 表示:当 form.area === 'area1',才显示
        { relationKey: 'area', value: 'area1' }
      ]
    }
  },
  {
    type: 'el-select',
    label: '活动区域',
    formKey: 'area',
    value: 'area1',
    options: {
      multiple: true
    },
    optionData: [ // 这里模拟去后端拉回数据
      { label: '区域1', value: 'area1' },
      { label: '区域2', value: 'area2' }
    ]
  }
]

我们把 render函数 改造后,变成这样

<script>
export default {
  name: "FormItemDemo",
  props: {
    itemConfig: Object // 接收配置,外部传入
  },
  render(createElement) {
    return createElement('el-form-item', {
      props: {
        label: this.itemConfig.label // 表单项的label
      }
    }, [
        // 表单组件
        createElement(this.itemConfig.type, {
          props: {
            value: this.itemConfig.value // 这里是自己实现一个 v-model
          },
          on: {
            change: (nVal) => { // 这里是自己实现一个 v-model
              this.itemConfig.value = nVal
            }
          }
        }, this.itemConfig.optionData && this.itemConfig.optionData.map(option => {
          // 这里只是 本demo 处理 el-select 的 option 数据,实际大家根据具体业务来实现即可
          return createElement('el-option', { props: { label: option.label, value: option.value } })
        }))
    ])
  }
}
</script>

接下来我们在 app组件 中同时应用我们的 配置 + FormItemDemo 组件:

<template>
  <div>
    <el-form label-width="100px">
      <FormItemDemo v-for="item in config" :item-config="item" />
    </el-form>
  </div>
</template>
<script>
import FormItemDemo from "./components/FormItemDemo.vue";
import config from "./config";
export default {
  name: 'App',
  components: { FormItemDemo },
  data () {
    return {
      config
    }
  }
}
</script>

这时候我们看下页面长什么样?

ok!!!实现了,接下来,我们只需要根据业务需求不断丰富我们的 FormItemDemo 组件即可。这里,笔者会带着大家一起实现一个 联动显示隐藏 、 下拉框多选 的功能~相信看完后,你一定有醍醐灌顶的感受,然后就可以自己根据业务去实现需求了。

4.丰富组件能力,实现业务

我们先来看第一个需求:

  • 当活动区域的值为 “area1” 时, 活动名称才展示

分析一下这个需求,我们的 input组件 跟 select组件 联动,所以 input组件 要获取 select组件 的值,这时候,我们可以在 app组件 中,将整个 config 传入 FormItemDemo组件。

再回看一下我们的配置,我们把显示隐藏的配置放在 options.vIf 中(这里笔者设计成了一个数组,因为碰到的业务经常存在一个表单会受到好几个表单值联动的),所以 FormItemDemo组件 需要用这个来判断是否执行本次 render 以此来实现 v-if。如图所示:

笔者用了一个 computed 去实现这个需求。大家可以不用仔细深入,只要知道 componentShow 的作用就是,找到联动的 relationKey 的 config 中的 value 值,判断是否跟配置的一致。

computed: {
  componentShow () {
    const vIfArr = this.itemConfig?.options.vIf
    if (!vIfArr) return true
    const relationArr = this.config.filter(config => vIfArr.find(vIf => vIf.relationKey === config.formKey))
    for (const relationItem of relationArr) {
      const vIfItem = vIfArr.find(_ => _.relationKey === relationItem.formKey)
      // 这里就是判断 联动的表单值 是否不满足 可以显示 的条件,不满足则不显示
      if (relationItem.value !== vIfItem.value) return false
    }
    return true
  }
}

模拟实现 v-if,只需要把上述计算属性在 render 的开头进行判断即可

ok,直接看下结果!两个表单项之间的联动完成了

接下来的需求,大家自行思考下怎么实现即可。其实都是异曲同工的

  • 控制 select 多选 、 单选
  • 添加 filter 属性 ...

好了,这样子,基本上就大功告成了,只要我们把 FormItemDemo 的业务逻辑都实现了,后续不管开发N个表单系统,我们只需要配置就完事了,摸鱼也就是板上定钉的事情了~但是,一个优秀的前端,怎么能这么算了呢?我们好歹也要做一点优化是吧?

三、配置静态化

细心的朋友可能已经发现了,我们上述实现配置化的时候,直接把整个 config 赋值给 data ,然后在 App组件 的 el-form 中 v-for 使用,那这样避免不了就会出现一些尴尬的事情,比如我们看下图:

没错,就如大家所见,所有的属性都带上了 getter 和 setter,这意味着,他们都被初始化成了响应式的。由于我们的业务是非常复杂的,所以当我们真的要用一个 config 去描述整个表单时,config 的规模远不止以上这么点,并且整个配置对象的层级可能还会比较深,如果这样的话就可能会有性能问题了。

熟悉 Vue2 的同学都知道,初始化的时候,会对 data 做一个深度遍历添加 get 、 set 变成响应时数据,并且在组件执行 render函数 时,会访问到这些对象的属性。一旦访问到,就会触发 data属性 的依赖收集动作,如果无脑多的属性时,这个 get方法 将被无脑执行。

这肯定不符合我们这种优秀的前端的作风的是吧?怎么搞,优化呗。思路我们也不自己想了,直接拿 尤大 的处理来耍吧哈哈哈。

有深入看过 Vue2 源码的同学,对 __ob__ 这个属性一定不陌生,上面截图也有这个属性,但是大家发现没,这个 ob属性 却没有对应的 get 、set 。让我们打开源码,看看 尤大 做了什么?

首先,在进行响应式处理之前,调用了一个 def 的方法,这里 第四个参数 是没传的

看看 def 的具体实现,其实就是重新定义这个对象的属性。由于没传 enumerable,所以此时 __ob__的 enumerable 为 false

这样有什么用?一句话概括就是无法遍历到这个属性,后续响应式初始化时也会跳过这个属性。不清楚的伙伴可以看看笔者写的一个 demo 来加深理解:

没错,我们这里也是采用同样的方式对我们的 config 进行 非响应式 优化。其实整个 config 数据,我们只是需要保证 value 是响应式的即可,其他很多描述性数据都是大可不必的。那我们就把其他字段进行一个优化~

// 优化函数
function optimize (array) {
  return array.reduce((acc, cur) => {
    for (const key of Object.keys(cur)) {
      if (key === 'value') continue
      // 将不是 value 的属性都进行非响应式优化
      Object.defineProperty(cur, [key], { enumerable: false })
    }
    acc.push(cur)
    return acc
  }, [])
}

具体就不展开介绍函数实现了,大家 get 到思路就 ok 了(有兴趣的可以细看一下)~

此时,我们再打印 config 来看看变成什么样了:

ok,这下就舒服了~终于大功告成了!!!

写在最后,其实这个是我差不多一年前的实践了,一直在分享与不分享之间徘徊。因为这类型的文章,适用性一般般,需要有一定的业务场景应用才能比较有用,但是嘛,说不定有跟我之前遇到一样境况的小伙伴,又或者是大家有更好的见解建议能为我带来提升,所以我还是决定分享出来。

平时更多的开发伙伴都会吐槽天天在业务中摸爬打滚,项目没有亮点,这个是不可否认也不可避免的现状吧~企业本就是为了盈利生产,不可能每时每刻都能有技术挑战的活下来,更多时候我们可能是平庸的业务中度过。但是,我们能否在平庸的业务中再拓展出更高效、更便捷的方式,说不定这就是一种突破和亮点吧。

虽然你们可能不会认可,但是这的的确确是让我开发效率提升大半以上的方案,并且出去面试我也是把这一条放在第一点去写。它可能不是特别亮点,不是特别完善,但对我个人而言,我从 设计 - 实现 - 优化 的每一步都有自我的思考且落地,对我自己而言,它就是亮点了,也许很少人会注意到配置优化这一步,笔者个人觉得这一步算是点睛之笔,因为深入到了细节。最后,希望能帮助到有需要的大,大家可以早点下班,留给多的时间给自己去享受生活!没有绝对完美的技术和方案,只有合适与否,根据场景选择方案哈,更多关于vue2 element-ui前端配置化的资料请关注我们其它相关文章!

(0)

相关推荐

  • VUE2.0+ElementUI2.0表格el-table实现表头扩展el-tooltip

    ElementUI2.0的表格的扩展: elementUI表格table elementUI文字提示Tooltip 如果要实现鼠标移到表头有注释或者弹框该怎么添加呢? <el-table empty-text="正在加载中..." :data="contentList" style="width: 100%" @sort-change="sort" class="pro-table-item" too

  • VUE2.0+ElementUI2.0表格el-table循环动态列渲染的写法详解

    先看看ElementUI里关于el-table的template数据结构: <template> <el-table :data="tableData" style="width: 100%"> <el-table-column prop="date" label="日期" width="180"> </el-table-column> <el-tabl

  • Vue2中Element UI表单的使用详解

    目录 引入ElementUI 表单中组件数据的获取 表单中的修饰符 实例 自定义指令 全局指令directive 不带参inserted 带参bind 局部指令directives 总结 引入Element UI <!-- 引入样式 --> <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"> <!-- 引入组件库 --

  • 解决vue2中使用elementUi打包报错的问题

    bug1.找不到element-ui/lib/theme-default/index.css 解决:修改路径为 element-ui/lib/theme-chalk/index.css 原因:elementUi升级时遗留bug bug2: ERROR in static/js/app.77ab8a3664d32f2b9c76.js from UglifyJs Unexpected token: operator (>) [./~/element-ui/src/mixins/emitter.js:

  • vue2+elementui进行hover提示的使用

    vue2+elementui进行hover提示分为外部和内部,内部使用el-tooltip,外部使用mouseover和mouseout来让提示框显隐(两个事件要做节流处理,事件要在beforedestroy中销毁) <template> <div class="hello"> <!-- <el-tooltip placement="top"> --> <!-- <div slot="conten

  • vue2.0基于vue-cli+element-ui制作树形treeTable

    该组件基于技术栈,主要涉及vue-cli生成的webpack项目脚手架,在此脚手架项目基础上完成的,整合了element-ui开源vue的UI项目 1.vue-cli的安装使用 npm install -g vue-cli 全局安装vue-cli之后,使用该脚手架的相关命令,可快速生成一个比较规范的vue项目结构 vue init <template-name> <project-name> 例子 vue init webpack treeTable 这样一个快速的项目结构生成,如

  • 前端vue2 element ui高效配置化省时又省力

    目录 前言 一.场景介绍 1. 业务场景 2. 配置化想法萌生 二.设计 & 实现 1. 设计协议 2. 实现渲染器 3. render函数 & 配置数据 4.丰富组件能力,实现业务 三.配置静态化 前言 这篇文章是笔者曾经全盘负责了接近一年的广告投放系统沉淀下来的开发经验,大家各取所需,不喜勿喷-当然啦,有自己的见解.更好的建议的大牛朋友们,我们评论区见-hhh,大多提点高见,让笔者继续学习继续进步! 本文从 场景介绍 . 设计&实现 . 性能优化 三个部分进行讲解.笔者当时的技

  • Vue2 Element Schema Form 配置式生成表单的实现

    目录 前置知识点 Component $attrs $listeners 表单的结构是什么样的 配置数组数据结构 结语 前置知识点 为了实现一个Schema Form配置式表单的生成,需要了解一部分前置知识点. Component vue 提供了一个内置组件 Component,用来动态渲染组件,举个例子,本篇文章以Element UI 为例,假设我们全局注册了Element UI的组件,那么下面一段代码 <Component is="el-input"></Comp

  • Vue前端整合Element Ui的教程详解

    目录 Vue前端整合Element Ui 1.安装Element Ui组件库 2.测试Element Ui是否整合成功 Vue前端整合Element Ui 本节内容服务于SpringBoot + Vue 搭建 JavaWeb 增删改查项目. Element UI 是一套采用 Vue 2.0 作为基础框架实现的组件库,一套为开发者.设计师和产品经理准备的基于 Vue 2.0 的组件库,提供了配套设计资源,帮助网站快速成型. Element Ui组件官网 1.安装Element Ui组件库 WIN+

  • Vue2.5 结合 Element UI 之 Table 和 Pagination 组件实现分页功能

    2017年底了,总结了这一年多来的前端之路,Vue从入门到放弃,再二进宫,从 Vue1.0 持续跟踪到 Vue2.5.结合公司的一些实际项目,也封装了一些比较实用的组件. 由于现在公司管理平台主要运用Element UI,索性就结合组件Table 和 Pagination 封装了一个支持页面切换的Table组件,不啰嗦,直接上代码. 2.实现思路 2.1.Element UI 引入(整体引入) main.js // Element UI import Element from 'element-

  • 详解vue2.0的Element UI的表格table列时间戳格式化

    这两天学习了vue2.0的Element UI的表格table列时间戳格式化,所以,今天添加一点小笔记. 表格属性 <el-table :data="tableData" v-loading.body="loading" border @selection-change="selectionChange" style="width: 100%"> <el-table-column prop="cre

  • vue2.0 + element UI 中 el-table 数据导出Excel的方法

    1.安装相关依赖 主要是两个依赖 npm install --save xlsx file-saver 如果想详细看着两个插件使用,请移步github. https://github.com/SheetJS/js-xlsx https://github.com/eligrey/FileSaver.js 2.组件里头引入 import FileSaver from 'file-saver' import XLSX from 'xlsx' 3.组件methods里写一个方法 exportExcel

  • Vue Element UI + OSS实现上传文件功能

    Element提供了upload上传组件,可以查看官网upload组件的详细介绍:查看upload组件的上传源码upload/ajax,使用的是XHR对象上传文件.在项目实践中,发现该上传方法上传大文件时会出现问题,所以决定使用阿里云对象存储服务(Object Storage Service,简称OSS),OSS详细介绍可以查看官网,本文主要讲解的是OSS上传文件的前端,后台开发请查看官网介绍,SDK Browser.js讲解了前端如何进行上传. 1.使用npm安装SDK的开发包: npm in

  • Web Components实现类Element UI中的Card卡片

    目录 引言 Web Components 核心组成 1. Custom Elements 2. Shadow DOM 3. templates 和 slots 完整代码 Web Components vs Vue Components Web Components 生命周期回调函数 优点 and 缺点 七.基于web components的框架 引言 Web Components 是一个浏览器原生支持的组件化方案,允许你创建新的自定义.可封装.可重用的HTML 标记.不用加载任何外部模块,直接就

  • 前端单元测试之UI测试功能性代码测试教程

    目录 前言 UI测试: 功能性代码测试: 让人闻风丧胆的单元测试 代码测试代码 Jest介绍 一.基础教程 安装 源码开发 测试用例编写 开始测试 二.核心API 全局方法 匹配器 异步代码测试 回调 Promise Async/Await Mock Functions 使用 mock 函数 .mock 属性 Mock 的返回值 Mocking Modules 快照测试 前言 <孤勇者>最近火爆的一塌糊涂,占领了小学生.甚至幼儿园,连我家2岁多的儿子尽然也会哼几句.虽然他以为这首歌是奥特曼的主

随机推荐