一路繁花似锦绣前程
失败的越多,成功才越有价值

导航

 

九、项目整体搭建

1、导学
  • 将收获什么
* 第一部分:相关准备知识
    - 前端工具链的相关工具介绍
    - 脚手架工具的使用和对比
        ~ Imooc CLI
        ~ Vue CLI
        ~ Vite
    - 编码规范
        ~ ESLint
        ~ Prettier
        ~ 产出**编码规范文档**
    - 项目结构规范
        ~ 产出**项目结构规范文档**
    - Git操作规范
        ~ Git Flow
* 第二部分:搭建项目整体框架
    - Ant Design Vue
    - Vue Router
    - Vuex
  • 关键词
* **技术规范**文档-必须落实到文档中,别放在脑子里
* Ant Design Vue
* Vue Router和Vuex
* Typescript-用了TS,一定要培养使用的习惯,看到任何变量都想到它的类型
  • 学习方法
* 对比学习:更进一步,不同工具也可以横向对比,这样可以收获的更多
* 必须亲自实践:请不要因为比较简单就不写代码,眼高手低。**无他,唯手熟尔**
* 不要教条主义:很多过程没有标准答案,适合自己的项目的方案才是最优解。
* 学会看**文档**:好的文档中有大部分的知识点。
2、大话前端工具链
* 简介
    - 前端的飞速发展:带来了更复杂的项目
    - 项目的常见需求 - 依赖管理,预编译,构建打包,压缩合并等
    - 随着项目越来越复杂 - 诞生了**前端工程化**
    - 随着工程化的产生 - 产生了对应的**前端工具链**
* 静态类型语言
    - 动态语言的弊端
        ~ **typescript**
        ~ flow
* 代码风格检查Linter
    - 多人协作的弊端,风格各异,维护和扩展的困难
        ~ eslint
* 包管理器
    - npm
    - yarn - 兼容npm registry
* 转译器Traspiler
    - 非JS或不同版本的JS翻译成符合平台要求的等价代码
        ~ Babel
* 开发服务器
    - live reload
    - HMR
* 打包工具Bundler
    - 将源代码转换成符合生产环境的代码
        ~ Webpack - Loader,Plugin,大而全的功能
        ~ Rollup - 专注于打包输出多种格式
        ~ Parcel - 零配置
* 任务管理工具Task Runner
    - 自动执行项目所需的重复任务
        ~ css预处理
        ~ 优化图片
        ~ 合并压缩javascript
        ~ 文件处理(拷贝,删除)
        ~ 监听文件变化
        ~ Gulp - 流式管道写法组合多个任务
        ~ Webpack - 通过插件的方式
        ~ npm scripts或者Shell脚本
* 脚手架Scaffolding tools
    - **将工具链聚合在一个工具内**简单,快速,零配置
        ~ Vue - Vue CLI,Vite,Imooc CLI
        ~ React - create-react-app
        ~ Angular - Angular CLI
3、使用Imooc CLI新建项目
* 不是针对某个前端框架的脚手架,而是一个**大而全更加针对业务的脚手架**
    - 支持各种模板,可扩展性
    - 云构建
    - 预发布和正式发布
    - 项目回滚
    - 远程Git操作
* 安装
    - npm install -g @imooc-cli/core
    - imooc-cli init
* 依赖**cnpm**
    - npm install -g cnpm
4、Vue CLI vs Vite
* **Vite比Vue CLI快10-100倍?**
* Vue CLI的功能
    - 工程脚手架
    - 开发服务器
    - 插件系统
    - 用户UI界面
* Vue CLI构建是基于**Webpack**的。主要耗时都在Webpack的性能上。
* Vite
    - 利用浏览器的**原生ES模块**,基于**Rollup**进行构建
    - 处于测试阶段,不是一体化的工具,目的就是一个**快速**的开发服务器和**简单的**构建工具
* 对比时刻
* 它为什么这么快?
* Vite的缺点
    - 测试阶段
    - 只支持新版支持ES modules的浏览器
    - 第三方库也需要都支持ES modules
    - CommonJS支持有限
    - 开发构建属于两套系统,可能导致生产和开发不一致行为
* Vite的前辈
    - [Snowpack](https://www.snowpack.dev/)
      **一个利用浏览器中JavaScript模块的开发服务器项目**
5、ESLint
* **规范的代码格式可以让整个工作的效率在一定程度上提升到最高**
* 没有规范可能出现的问题
    - 代码难以读懂
    - 代码提交的时候会有很多格式问题的修改,造成不必要的事件消耗
* ESLint是什么?
    - 是一个开源的JavaScript的linting工具,使用espree将JavaScript代码解析成抽象语法树
      (AST),然后通过AST来分析我们代码。
* 命令行工具
    - npx eslint --version
    - npx eslint --ext ts,vue src/**
* 编辑器插件
    - [ESLint插件](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint)
    - [Vetur插件](https://marketplace.visualstudio.com/items?itemName=octref.vetur)
6、ESLint配置文件
* Rules
    - [ESLint可用的Rules](https://eslint.org/docs/rules/)
* Extends
* 自动修正错误
7、小花絮:Prettier
* **Prettier**顾名思义,将代码变漂亮
* ESLint的功能
    - 代码质量问题
    - 代码风格问题
* Prettier的理念
    - **An opinionated code formatter**,格式很重要,但是很重要,让我来帮你搞定!
    - Fewer Options:Prettier还给予了一部分配置项,可以通过.prettierrc文件修改。
* ESLint prettier的工作原理
    - 禁用所有和Prettier冲突的ESLint的代码格式规则
    - 将所有Prettier的规则和修改导入ESLint中,在ESLint统一的显示这些错误
8、项目结构规范
* **代码结构**针对单个文件的书写格式
* **项目结构**针对这些文件应该以怎样的标准进行存放和管理
* [React项目文件结构](https://reactjs.org/docs/faq-structure.html)
    - 按照按功能或路由组织,也就是所说的feature
    - **按照文件类型**
* 注意事项
    - 避免多层嵌套
    - 不要过度思考
* 项目结构举例
/assets
  image.png
  logo.png
/components
  ColorPicker.vue
  Dropdown.vue
  ...
/views
  Home.vue
  ...
/router
  index.ts
  ...
/store
  index.ts
  editor.ts
  user.ts
  ...
/hooks
  useURLloader.ts
  ...
/plugins
  hotKeys.ts
  ...
/test
  ColorPicker.spec.ts
App.vue
main.ts
...
9、Git标准操作流程:Git Flow
* 所有的这些规范都是针对特定的多人设定的,意在让多人协作的过程更顺畅,更简单,
  减少不必要的冲突和时间的浪费。
* Git Flow
    - 预设两个分支
        ~ master只能用来包括产品代码。你不能直接工作在这个master分支上
        ~ develop是你进行任何新的开发的基础分支
        ~ **这两个分支被称之为长期分支**
    - 功能开发feature
        ~ 整合回到develop
        ~ 等待更全面的测试
        ~ 等待和develop一起进行发布
    - 管理release
        ~ 新功能已经添加,bug已经修复
        ~ 代码已经被测试
        ~ release分支使用版本号命名的
    - bug修复hotfix
        ~ 针对master分支
    - 优点:清晰可控
    - 缺点:相对复杂,不适合持续发布
* Github Flow
    - 根据需求,从master拉出分支
    - 激烈的开发阶段,提交commit
    - 开发完毕,发起PR(pull request)
    - 代码评审(很重要!)
    - 部署,并且测试
    - 没问题,merge到master!
    - **Github flow的最大优点就是简单,对于“持续发布”的产品,可以说是最合适的流程**
* 两大规则
    - branch命名
        ~ feature开头代表功能开发
        ~ hotfix开发代码bug修复
    - commit信息,必须**言之有物**,杜绝update,fix bug这类废话
10、ant-design-vue组件库
* 两大解决方案
    - ***[ant-design-vue](https://2x.antdv.com/docs/vue/getting-started-cn/)*
    - [element-plus](https://element-plus.gitee.io/)
* 安装方式
    - npm安装配合webpack等打包工具使用
        ~ npm install ant-design-vue@next --save
    - 直接引入js和css(不推荐)
        ~ <!-- 引入样式 -->
          <link rel="stylesheet" href="https://unpkg.com/element-plus/lib/theme-chalk/index.css">
          <!-- 引入组件库 -->
          <script src="https://unpkg.com/element-plus/lib/index.full.js"></script>
* 开始使用
    - // main.ts
      import Antd from 'ant-design-vue';
      import 'ant-design-vue/dist/reset.css'; 
      app.use(Antd)
* 关于全局API
    - Vue2的时代,都是全局API和配置
        ~ Vue.component('button-counter', {})
        ~ Vue.directive('focus', {})
    - Vue2没有“app”的概念,我们定义的应用只是通过new Vue()创建的根Vue实例。从同一个Vue
      构造函数创建的每个根实例共享相同的全局配置。
        ~ 在测试期间,全局配置很容易意外地污染其他测试用例
        ~ 全局配置使得在同一页面上的多个“app”之间共享同一个Vue副本非常困难
        ~ Vue.mixin({
            /* ... */
          })
          const app1 = new Vue({el: '#app-1'})
          const app2 = new Vue({el: '#app-2'})
    - **Vue3的做法:createApp**
        ~ import {createApp} from 'vue'
          const app = createApp({})
        ~ 应用实例暴露当前全局API的子集,任何全局改变Vue行为的API现在都会移动到**应用实例**上,
          现在就不会产生vue2的这些冲突了。
11、SPA应用路由的基本原理
* SPA和普通网页应用的区别
    - 普通网页
        ~ 跳转到新页面,每次重新加载所有资源
        ~ HTML内容是后端直接渲染的
    - SPA应用
        ~ 不跳转,JS拦截跳转,修改URL
        ~ JS动态渲染DOM内容
* SPA路由的实现方式
    - History API
        ~ [pushState](https://developer.mozilla.org/zh-CN/docs/Web/API/History/pushState)
        ~ [codesandbox](https://codesandbox.io/s/optimistic-cookies-wgxhc?file=/src/index.js)
    - URL Hash
* SPA优点
    - 速度快
    - 体验好
    - 为前后端分离提供了实践场所
* Vue Router4
    - https://router.vuejs.org/zh/
12、状态管理工具
* 什么是状态管理工具
    - 首先搞清楚,是否真的需要状态管理工具
    - 它随着SPA的出现,而浮出水面。客户端需要处理复杂的状态数据。
    - 多个组件需要共享的一系列数据,称之为全局数据。
* 解决方案
    - 方案一:单向数据流,从父组件传递到子组件
    - 方案一缺点:
        ~ 多层传递非常繁琐
        ~ 中间传递层有可能根本不需要这个数据
        ~ 根组件压力太大,逻辑代码会非常繁杂
    - 方案二:使用全局对象
    - 方案二缺点:
        ~ 数据非响应式
        ~ 修改无法追踪
        ~ 直接从组件获取数据是一种反模式
* 状态管理工具三杰
    - Vuex
    - Redux
    - Mobx
* 状态管理工具的特点
    - store,神奇的全局数据结构:single source of truth
    - 不能随意修改,调用特殊的方法来实现数据修改
    - 变化可追溯,可预测(predictable)
13、Vuex安装和基础
* Vue的数据流
    -       Actions(methods)
             ↗             ↘         
      View(template) ←  State(data)
* 出现问题:多组件共享状态
    - 根组件多层传递的困境
    - 多组件同步数据的繁琐
* Vuex的解决方案
    - Vue Components  →  (dispatch)Actions
              ↑               ↓
            State     ←  (commit)Mutations
* Vuex的特点
14、总结
* 知识点
    - 脚手架
        ~ Imooc CLI
        ~ Vue CLI
        ~ Vite
    - 代码规范
        ~ ESLint简介,使用和配置文件
        ~ Prettier的定位和作用以及使用
        ~ 产出:代码规范文档:https://www.yuque.com/imooc-lego/elp4vn/wtg4vo
    - 项目文件结构和命名规范
        ~ 产出:文件结构和命名规范文档:https://www.yuque.com/imooc-lego/elp4vn/igcosu
    - Git Flow
        ~ 标准Git Flow
        ~ **Github Flow**
        ~ 产出Git操作规范文档:https://www.yuque.com/imooc-lego/elp4vn/cwu0z1
    - Ant Design Vue
        ~ 安装,全局导入和使用
        ~ 多看文档,多用
    - Vue Router
        ~ SPA router的简单原理
        ~ 安装,全局引入
        ~ 添加路由,使用内置组件router-view和router-link
        ~ 使用钩子函数useRoute和useRouter获取路由信息和跳转
    - Vuex
        ~ 全局状态工具的定义
        ~ 安装,概念:**store,state,mutations**,使用commit提交mutations
        ~ 使用钩子函数useStore
        ~ 使用module将store拆分成多个模块
* 要点
    - **文档化**标准
    - **Typescript**深入编码理念中
* 作业
    - 根据我的介绍,写自己的**技术规范文档**,你可以根据我的简介和自己的偏好,
      写出适合自己项目的文档

十、编辑器基本布局及业务组件库初步开发

1、导学
* 主要内容
    - 完成第一个业务组件LText的书写
    - 完成业务组件属性和表单组件的显示和实时更新
    - 代码升级:支持vNode的在vue template中的展示
* 将收获什么
    - 渐进式的开发方式
    - 组件属性和重用性的设计和实现
    - Typescript结合实际项目的高度实战
    - Vue template和JSX写法的异同和优劣
* 学习方法
    - 渐进式的开发方法:小步快跑,一步步完善最终的需求。
    - 对比学习:多种方法完成一个任务,更能了解它们的优劣。
    - 流程图:以流程图的方式来描述代码的逻辑过程或者数据流动。
    - 技术文档:以技术文档为指引。
2、uuid
// npm i uuid @types/uuid
import { v4 as uuidv4 } from 'uuid'

console.log(uuidv4())
3、lodash
// npm i lodash-es @types/lodash
import { pick, mapValues, without, reduce } from 'lodash-es'

const obj = { a: '1', b: '2', c: '3' }
const arr = [1, 2, 3, 4, 5]
// 创建一个从obj中选中的属性的对象。
console.log(pick(obj, ['a']))
// 创建一个对象,属性与obj相同,属性值为箭头函数的返回值
console.log(
  mapValues(obj, (item) => {
    return {
      type: item.constructor,
      default: item
    }
  })
)
// 创建一个剔除所有给定值的新数组
console.log(without(arr, 4, 5))
// 参数1:迭代集合;参数2:迭代调用的函数;参数3:初始值。
console.log(
  reduce(
    obj,
    function (result, value, key) {
      result[key] = value
      return result
    },
    {} as { [p: string]: string }
  )
)
4、typescript
  • Readonly
interface IPerson {
  name: string
  age: number
}
const person: Readonly<IPerson> = {
  name: '骨法',
  age: 18
}
// 这里会报错,Readonly不可修改
person.name = '末日'
console.log(person)
  • Required
interface IPerson {
  name?: string
  age?: number
}
// 这里会报错,Required确定的类型
const person: Required<IPerson> = {}
console.log(person)
  • Partial
interface IPerson {
  name: string
  age: number
}
// 这里不会报错,Partial可选类型
const person: Partial<IPerson> = {}
console.log(person)

十一、掌握测试基本工具,给组件添加单元测试

1、导学
* 主要内容
    - Jest的基础以及进阶用法
    - Vue Test Utils的基础以及进阶用法
    - 使用TDD的方式进行业务代码的开发
* 将收获什么
    - 测试的定义,分类以及重要性
    - 常用通用测试框架的分类和特点
    - Jest和Vue Test Utils的基础和进阶全覆盖
    - TDD,一种全新的开发方式
* 关键词
    - 单元测试
    - Mock
    - TDD
* 学习方法
    - 转变思维方式-认识到测试的重要性,在以后的代码中有机会也可以写测试
2、Jest
  • 简介
* 通用测试框架
    - [Mocha](https://mochajs.org/)
    - [Jasmine](https://jasmine.github.io/)
    - **[Jest](https://jestjs.io/)**
* 测试框架的几大功能
    - 断言
        ~ Jest内置
        ~ Mocha需要另外安装[Chai](https://www.chaijs.com/)或者其他断言库
    - 异步支持
    - Mock
        ~ Jest内置
        ~ Mocha需要另外安装[Sinon](https://sinonjs.org/)
    - 代码覆盖率
        ~ Jest内置
        ~ Mocha需要另外安装[Istanbul](https://istanbul.js.org/)
* Jest的特点
    - 开箱即用,零配置
    - **快!**
    - 内置代码覆盖率
    - Mocking很容易
  • 基础用法
* 安装(全局也要安装,不然会报错):npm i -S jest
* 查看版本:npx jest --version
* 命令:npx jest
    - 执行一系列以.test.js结尾的测试用例
* 命令:npx jest ./async.test.js --watch
    - 热更新替换
* webstorm编辑器jest代码类型提示
    - File | Settings | Languages & Frameworks | JavaScript | Libraries
    - Download -> jest
3、使用
  • expect.test.js
test('test common matcher', () => {
  expect(2 + 2).toBe(4)
  expect(2 + 2).not.toBe(5)
})

test('test not equal', () => {
  expect(2 + 2).not.toBe(5)
})

test('test to be true or false', () => {
  expect(1).toBeTruthy()
  expect(0).toBeFalsy()
})

test('test number', () => {
  expect(4).toBeGreaterThan(3)
  expect(2).toBeLessThan(3)
})

test('test object', () => {
  expect({name: 'viking'}).toEqual({name: 'viking'})
})
  • async.test.js
// callback
const fetchUser = (cb) => {
  setTimeout(() => {
    cb('hello')
  }, 100)
}
it('test callback', (done) => {
  fetchUser((data) => {
    expect(data).toBe('hello')
    done()
  })
})

// promise
const userPromise = () => Promise.resolve('hello')
it('test Promise', () => {
  return userPromise().then(data => {
    expect(data).toBe('hello')
  })
})
it('test with async', async () => {
  const data = await userPromise()
  expect(data).toBe('hello')
})
it('test with expect', () => {
  return expect(userPromise()).resolves.toBe('hello')
})
const rejectPromise = () => Promise.reject('error')
it('test with expect reject', () => {
  return expect(rejectPromise()).rejects.toBe('error')
})
  • mock.test.js
const getUserName = require('./user')
const axios = require('axios')
// 方式一
// jest.mock('axios')
// 用法1
// axios.get.mockImplementation(() => {
//   return Promise.resolve({data: {username: 'viking'}})
// })
// 用法2
// axios.get.mockReturnValue(Promise.resolve({data: {username: 'viking'}}))
// 用法3
// axios.get.mockResolvedValue({data: {username: 'viking'}})

// 方式二:项目根目录新建__mocks__目录,__mocks__目录下新建axios.js文件

function mockTest(shouldCall, cb) {
  if (shouldCall) {
    return cb(42)
  }
}

it('test with mock modules', () => {
  return getUserName(1).then(name => {
    console.log(name)
    expect(axios.get).toHaveBeenCalled()
    expect(axios.get).toHaveBeenCalledTimes(1)
  })
})
it('test with mock function', () => {
  const mockCb = jest.fn()
  mockTest(true, mockCb)
  expect(mockCb).toHaveBeenCalled()
  expect(mockCb).toHaveBeenCalledWith(42)
  expect(mockCb).toHaveBeenCalledTimes(1)
})
it('test mock with implementation', () => {
  // const mockCb = jest.fn(x => x * 2)
  const mockCb = jest.fn().mockReturnValue(20)
  mockTest(true, mockCb)
})
const axios = require('axios')

module.exports = function getUserName(id) {
  return axios.get(`https://jsonplaceholder.typicode.com/users/${id}`).then(resp => {
    return resp.data.username
  })
}
const axios = {
  get: jest.fn(() => Promise.resolve({data: {username: 'viking'}}))
}
module.exports = axios
  • timer.test.js
const fetchUser = (cb) => {
  setTimeout(() => {
    cb('hello')
  }, 1000)
}
const loopFetchUser = (cb) => {
  setTimeout(() => {
    cb('one')
    setTimeout(() => {
      cb('two')
    }, 2000)
  }, 1000)
}
jest.useFakeTimers()
it('test the callback after 1 sec', () => {
  const callback = jest.fn()
  fetchUser(callback)
  expect(callback).not.toHaveBeenCalled()
  expect(setTimeout).toHaveBeenCalledTimes(1)
  jest.runAllTimers()
  expect(callback).toHaveBeenCalled()
  expect(callback).toHaveBeenCalledWith('hello')
});
it('test the callback in timeout loops', () => {
  const callback = jest.fn()
  loopFetchUser(callback)
  expect(callback).not.toHaveBeenCalled()
  jest.runOnlyPendingTimers()
  expect(callback).toHaveBeenCalledTimes(1)
  expect(callback).toHaveBeenLastCalledWith('one')
  jest.runOnlyPendingTimers()
  expect(callback).toHaveBeenCalledTimes(2)
  expect(callback).toHaveBeenLastCalledWith('two')
});
it('test the callback with advance timer', () => {
  const callback = jest.fn()
  loopFetchUser(callback)
  expect(callback).not.toHaveBeenCalled()
  jest.advanceTimersByTime(500)
  jest.advanceTimersByTime(500)
  expect(callback).toHaveBeenCalledTimes(1)
  expect(callback).toHaveBeenLastCalledWith('one')
  jest.advanceTimersByTime(2000)
  expect(callback).toHaveBeenCalledTimes(2)
  expect(callback).toHaveBeenLastCalledWith('two')
});
4、Vue Test Utils
* 配置开发环境
    - 手动配置?(不推荐)
    - vue cli是基于插件架构的,插件可以:
        ~ 安装对应功能的依赖
        ~ 修改内部配置
        ~ 注入命令
    - 在现有项目中安装插件
        ~ vue add 插件名称
* 添加测试插件
    - 插件地址:https://www.npmjs.com/package/@vue/cli-plugin-unit-jest
    - 命令:vue add unit-jest
* 插件运作的过程
    - 安装的依赖
        ~ vue-test-utils
        ~ vue-jest
        ~ 注入了新的命令
    - vue-cli-service test:unit
        ~ Any files in tests/unit that end in .spec.(js|jsx|ts|tsx)
        ~ Any js(x)/ts(x) files inside __tests__ directories
    - vue-jest转换
        ~ 将vue SFC格式文件转换成对应的ts文件
        ~ 将ts通过presets/typescript-babel转换成对应的js文件
5、测试组件
* 文档地址:https://vue-test-utils.vuejs.org/v2/api/
* 运行jest本身的命令:npm run test:unit -- --watch
* 测试内容
    - 渲染组件
        ~ mount和shallowMount
        ~ 传递属性
    - 元素是否成功的显示
        ~ 查找元素的不同写法
        ~ get、getAll
        ~ find、findAll
        ~ findComponent和getComponent
    - 触发事件
        ~ trigger方法
    - 测试界面是否更新
        ~ 特别注意DOM更新是个异步的过程
        ~ 使用async await
    - 更新表单
        ~ setValue方法
    - 验证事件是否发送
        ~ wrapper.emitted()
* mount和shallowMount的区别
    - mount一股脑全都渲染
    - shallowMount只渲染组件本身,外来的子组件都不渲染
    - shallowMount更快,更适合单元测试
* find和get的区别
    - 找不到的时候,find返回null,case不会出错,get throw错误,case报错
    - 通用规则:总是使用get,除了你想判断一些元素不存在的时候,这种情况下使用find文档链接
* getComponent的意义
    - 不必测试子组件里面的内容,只要判断是否渲染了子组件,是否传递了正确的属性就可以了,
      这就是单元测试的意义,独立,互不影响的模块。
6、测试异步请求
* 不要依赖第三方库,模拟第三方库的实现我们应该已经掌握
* 使用flushPromises将所有Promise pending状态都改为完成
    - 安装地址:https://www.npmjs.com/package/flush-promises
* 小知识点
    - 将mock对象断言为特定类型,使用jest.Mocked<>
    - 使用only跑一个单独的case
7、测试准备和结束
* 一次性完成测试准备
    - beforeAll
    - afterAll
    - 文档地址
* 每个测试测试准备
    - beforeEach
    - afterEach
    - 文档地址
* 建议
    - 如果一个测试失败,要注意的是
    - 它是否是唯一在运行的测试,使用it.only进行隔离
    - 使用beforeEach或者afterEach清空一些共享状态
* 小tip
    - 使用only只运行一个用例
    - 使用skip跳过一个用例
8、替换全局组件
* 遇到难题
    - 全局组件
    - 外部模块
* 测试行为
    - ant-design-vue -> message -> success()
    - vue-router -> useRouter() -> push()
    - vuex -> useStore() -> commit()
9、测试vuex
* 打破惯性思维,前端工程师的任务不仅仅是和界面打交道
    - vuex store天生是脱离组件,独立开来的。它是一个特殊的数据结构,
      使用特定的方法,更新其中的状态。
* 测试一个store是否有必要
    - 非常有必要交互变得复杂之后,你可以脱离界面对数据的改动做测试,最大限度的保证功能的正常运行。
* 测试过程
    - 检查初始state是否正常
    - 触发mutations或者actions,对于每个mutations可以写一个case
    - 检查修改后的state是否正常
    - 测试getters
10、什么是TDD开发方式?
* 一个实际组件的开发场景
    - 开发ColorPicker组件,在很多场景(背景颜色,字体颜色)下使用。
* 原型图
    - 点击左侧颜色框之前
    - 点击之后
* 需求
    - 显示
        ~ 左侧显示当前传入的颜色
        ~ 右侧显示十种常用的颜色
        ~ 右侧最后一个是透明,点击以后清除效果
    - 点击
        ~ 点击左侧,显示颜色选择框,在颜色框中点击或者在input中修改值以后,将
          新的值以事件的形式发射出去 
        ~ 点击右侧的任何颜色,将新的值以事件的形式发射出去
    - 特别注意:
        ~ 左侧可以使用<input type="color" />-文档地址
        ~ 遵守业务组件设计原则:以属性value为传入值,以事件change发射出新的要
          改变的值
* TDD的开发方式
    - Test Driven Development:测试驱动开发-维基百科链接
        ~ 先根据需求写测试用例
        ~ 测试用例全部失败
        ~ 开始写代码实现
        ~ 将测试用例由失败变成通过
11、TDD的特点
* 开发过程(TDD Cycle)
    - 不可运行(TEST FAILS)
    - 可运行(TEST PASSES)
    - 重构(REFACTOR)
* 动机
    - 控制编程过程可能出现的忧虑感
    - 将编程过程任务化,可以对进度做到更加精确的把握。
12、本周回顾
* 过程回顾和要点
    - Jest-测试框架
        ~ Jest vs Mocha
        ~ 安装和断言
        ~ 异步测试-回调和Promise
        ~ mock函数-jest.fn()
        ~ mock第三方模块-jest.mock()
        ~ mock Timers-jest.runTimers()...
    - Vue Test Utils-Vue测试工具
        ~ 渲染-mount和shallowMount
        ~ 获取元素-get、find
        ~ 表单-更新表单setValue,特别注意await
        ~ 事件-触发DOM事件trigger,验证组件的自定义事件emitted
        ~ 异步请求-结合jest和VTU一起
    - 高级技巧UserProfile组件测试
        ~ mock全局组件
        ~ mock第三方模块的实现
        ~ 在实例中添加真实的Vuex store
        ~ 单独测试Vuex store
    - TDD的开发方式:开发ColorPicker组件
        ~ 先写测试用例,所有用例失败
        ~ 根据用例写实现代码,让用例通过
        ~ 根据实际情况进行测试,如果有需要可以进行重构
* 单元测试的重要性
    - 开发人员编写,使用mocks等工具确保单元测试直接相互独立
    - 不需要使用教条主义的眼光来看测试
        ~ 没有必要追求100%的coverage
        ~ 有些组件其实根本没有必要写测试
    - 让测试真的能够帮助你,为你减少Bug和工作量
* 作业
    - 完成IconSwitch的组件开发,并且为其写测试
        ~ 自己撰写需求
        ~ 可以使用ant-design-vue提供的一些组件,比如a-tooltip,也可以自研
        ~ 这个组件其实并不能很好的体现单元测试的优越,但是可以比较好的练习学习的内容
posted on 2023-07-26 11:48  一路繁花似锦绣前程  阅读(30)  评论(0编辑  收藏  举报