├── README.md ├── .gitignore ├── docs ├── standard │ ├── README.md │ ├── 讨论.md │ ├── html规范.md │ ├── vue规范.md │ ├── 文本规范.md │ ├── 命名规范.md │ ├── css规范.md │ ├── 开发规范.md │ └── js规范.md ├── .vuepress │ ├── enhanceApp.js │ ├── styles │ │ └── palette.styl │ ├── public │ │ └── manifest.json │ └── config.js └── README.md └── package.json /README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .history -------------------------------------------------------------------------------- /docs/standard/README.md: -------------------------------------------------------------------------------- 1 | # 前端项目规范 2 | 3 | 统一团队代码风格,优化团队协作效率。 4 | 5 | -------------------------------------------------------------------------------- /docs/.vuepress/enhanceApp.js: -------------------------------------------------------------------------------- 1 | export default ({ Vue, options, router, siteData, isServer }) => { 2 | 3 | }; 4 | -------------------------------------------------------------------------------- /docs/standard/讨论.md: -------------------------------------------------------------------------------- 1 | # 其他待讨论的问题 2 | 3 | ## 限制代码规范 4 | 5 | * eslint 6 | * sonar 7 | * git flow 8 | 9 | ## 统一ide 10 | 11 | * vscode 12 | * webstore 13 | * idea 14 | 15 | 个人建议vscode:强大的插件库,较低的内存占用,大厂的首选。 16 | -------------------------------------------------------------------------------- /docs/.vuepress/styles/palette.styl: -------------------------------------------------------------------------------- 1 | $contentWidth = 1300px 2 | 3 | .theme-default-content:not(.custom){ 4 | width: 1300px; 5 | } 6 | 7 | .ant-table table{ 8 | display: inline-table !important; 9 | } 10 | .ant-table-thead > tr > th, .ant-table-tbody > tr > td{ 11 | padding: 10px 5px; 12 | } -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | home: true 3 | actionText: 查看文档 4 | actionLink: /standard/ 5 | 6 | features: 7 | - title: 规范的重要性 8 | details: 统一团队代码风格,优化团队协作效率。 9 | 10 | footer: 11 | --- 12 | 13 | 26 | 27 | ``` js 28 | 31 | ``` -------------------------------------------------------------------------------- /docs/.vuepress/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "西陇科学", 3 | "short_name": "xi", 4 | "start_url": "index.html", 5 | "display": "standalone", 6 | "background_color": "#2196f3", 7 | "description": "西陇科学前端文档", 8 | "theme_color": "blue", 9 | "icons": [ 10 | { 11 | "src": "./logo.png", 12 | "sizes": "144x144", 13 | "type": "image/png" 14 | } 15 | ], 16 | "related_applications": [ 17 | { 18 | "platform": "web" 19 | }, 20 | { 21 | "platform": "play", 22 | "url": "https://play.google.com/store/apps/details?id=cheeaun.hackerweb" 23 | } 24 | ] 25 | } -------------------------------------------------------------------------------- /docs/standard/html规范.md: -------------------------------------------------------------------------------- 1 | # html规范 2 | 3 | ## 基本语法 4 | 5 | * 节点统一2行缩进 6 | * 不可忽略可选的关闭标签:如: \ 7 | * 静态boolean属性, 使用简写: 如: \ 8 | * 所有属性,标签,使用全小写,用中划线做分隔符,如: x-img, class 9 | * 其他参考"文本规范" 10 | 11 | ## 属性顺序 12 | 13 | 属性按照重要重要级别往下排列(如下属性从前往后); 14 | 15 | * id, ref, type 16 | * click, change 17 | * src, href 18 | * class 19 | * placeholder 20 | * max-length, max, min, 21 | * required, readonly, disabled 22 | 23 | ## 语义化 24 | 25 | 尽量使用语义化,大模块头部尽量有模块说明, 或是语义标签。如 26 | 27 | ``` 28 | 29 |
30 |
...
31 |
32 | 33 |
34 |
35 | 36 |
37 | ``` -------------------------------------------------------------------------------- /docs/standard/vue规范.md: -------------------------------------------------------------------------------- 1 | # VUE细节 2 | 3 | ## 基本准则 4 | 5 | * vue公用方法都在mixins, 重叠功能不再命名 6 | * 禁止name命名与跟根元素名称重叠 7 | * data返回数据必须为对象 8 | * 标签的key, 使用id等可标记属性,不使用index 9 | * 一个文件只允许声明一个组件 10 | * 单文件声明顺序:template > script > style 11 | * 避免隐性的父子组件通信: 应该优先通过 prop 和事件进行父子组件之间的通信,而不是 this.$parent 或变更 prop。 12 | 13 | 14 | ## 细节说明 15 | 16 | * 禁止v-if与v-for同标签使用 17 | * 计算出结果再进行赋值 18 | * 页面没有使用的元素,可不放置data 19 | 20 | 21 | ## 生命周期 22 | 23 | * 声明 > 引入 > 数据/监听 > 生命周期 > 方法 24 | 25 | 即:name > mixin > components > data > watch > computed > created > mounted > activated > methods 26 | 27 | ## 缓存方案 28 | 29 | * 用户相关使用cookies 30 | * 项目内部使用vuex 31 | * vuex使用module, 与业务为基线,切割业务 32 | * vuex使用长久方案, 配合createMyVuexPlugin使用 33 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vuepressBlog", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "keywords": [ 7 | "vue" 8 | ], 9 | "scripts": { 10 | "start": "vuepress dev docs", 11 | "dev": "vuepress dev docs", 12 | "build": "vuepress build docs", 13 | "deploy": "bash deploy.sh" 14 | }, 15 | "author": "", 16 | "license": "ISC", 17 | "dependencies": { 18 | "vuepress": "^1.4.0", 19 | "ant-design-vue": "^1.6.5" 20 | }, 21 | "devDependencies": { 22 | "highlight.js": "^9.18.1", 23 | "v-viewer": "^1.5.1", 24 | "core-js": "^2.6.11", 25 | "less": "^3.10.3", 26 | "less-loader": "^5.0.0", 27 | "sass": "^1.26.5", 28 | "sass-loader": "^8.0.2" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /docs/standard/文本规范.md: -------------------------------------------------------------------------------- 1 | # 文本规范 2 | 3 | ## 空格缩进 4 | 5 | 统一2个缩进 6 | 7 | ``` 8 | 11 | ``` 12 | 13 | ## 分号 14 | 15 | 结尾统一分号 16 | 17 | ``` 18 | this.name = "小明同学"; 19 | ``` 20 | 21 | ## 属性间隔 22 | 23 | 属性统一一个间隔 24 | ``` 25 | const { data } = await getUser(); 26 | ``` 27 | 28 | ## 双引号 29 | 30 | 统一双引号,没有嵌套不使用单引 31 | 32 | ## 方法嵌套 33 | 34 | 不使用多级方法嵌套,严禁使用三级以上的嵌套 35 | 36 | ## 注释 37 | 38 | ``` 39 | 字段(统一右侧): 40 | pageNo: 1 // 当前页 41 | 42 | 方法(统一顶部, 不带参数): 43 | // 改变页码 44 | changePage() { 45 | this.getList(); 46 | } 47 | 48 | 方法(统一顶部, 带参数): 49 | /** 50 | * @changePage 改变页码 51 | * @page 行数 52 | **/ 53 | changePage(page) { 54 | this.listForm.pageNo = page; 55 | this.getList(); 56 | } 57 | 58 | 页面(统一顶部): 59 | 60 | 61 | 62 | ``` 63 | ## 代码行数 64 | 不超过500, 超过500需组件化,或是考虑重构问题 65 | 66 | ## 每行长度 67 | 不超过150字符 -------------------------------------------------------------------------------- /docs/.vuepress/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | title: 'WEB规范', 3 | description: '本案例仅供参考', 4 | head: [ // 注入到当前页面的 HTML 中的标签 5 | ['link', { rel: 'icon', href: '/images/logo.png' }], 6 | ], 7 | serviceWorker: true, // 是否开启 PWA 8 | base: '/', // 部署到github相关的配置 9 | markdown: { 10 | lineNumbers: true // 代码块是否显示行号 11 | }, 12 | themeConfig: { 13 | nav:[ // 导航栏配置 14 | {text: '主页', link: '/' }, 15 | {text: '前端规范', link: '/standard/' }, 16 | ], 17 | displayAllHeaders: true, 18 | lastUpdated: '最后更新时间:', // 最后更新时间提示 19 | nextLinks: true, 20 | // 默认值是 true 。设置为 false 来禁用所有页面的 上一篇 链接 21 | prevLinks: true, 22 | sidebar: { 23 | '/standard/': [ 24 | '命名规范', 25 | '文本规范', 26 | '开发规范', 27 | 'html规范', 28 | 'css规范', 29 | 'js规范', 30 | 'vue规范' 31 | ] 32 | }, 33 | sidebarDepth: 2 34 | }, 35 | chainWebpack: (config, isServer) => { 36 | config.module.rule('less') 37 | .test(/\.less$/) 38 | .oneOf('normal') 39 | .use('less') 40 | .loader('less-loader') 41 | .end() 42 | .end() 43 | }, 44 | less: { 45 | javascriptEnabled: true 46 | } 47 | }; -------------------------------------------------------------------------------- /docs/standard/命名规范.md: -------------------------------------------------------------------------------- 1 | # 命名规范 2 | 3 | ## 原则 4 | 5 | * 样式相关用中划线优先 6 | * 与逻辑相关用驼峰优先 7 | 8 | 9 | ## 目录/文件命名 10 | 11 | * 常用:驼峰式规范 12 | * 特殊/历史原因:组件库,小程序分包名, 静态资源使用中划线 13 | * 名称应为对应的业务为参考 14 | * 如有文件类型标记,以文件类型标记为结尾。 15 | * 目录命名有复数时,添加s结尾 16 | 17 | ``` 18 | 正确案例:myPageName, components, userModal, login-logo.png 19 | 错误示范:my-page-name, MyPageName, component, modalUser, loginLogo.png 20 | ``` 21 | 22 | ## 样式/静态命名 23 | 24 | * 类名使用小写字母,以中划线分隔 25 | * id采用驼峰式命名 26 | * scss中的变量、函数、混合、placeholder采用驼峰式命名 27 | * 静态也属于样式的范围内,也使用中划线 28 | 29 | ``` 30 | /* class */ 31 | .element-content { 32 | ... 33 | } 34 | 35 | /* id */ 36 | #myDialog { 37 | ... 38 | } 39 | 40 | /* 变量 */ 41 | $colorBlack: #000; 42 | 43 | /* 函数 */ 44 | @function pxToRem($px) { 45 | ... 46 | } 47 | ``` 48 | 49 | ## 变量/对象命名 50 | 51 | 业务名 + 属性名 52 | 53 | * 标准变量采用驼峰式命名 54 | * 自定义前端遍历,使用:业务名 + 属性名 55 | 常见的属性名: flag, list, obj, visable, form, table,enum 56 | * 对上下文this的引用只能使用that, 不使用_that 57 | * 如有对象类型标记,以对象类型标记为结尾。如ref对象: 组件名称 + (如需:业务名称) + Ref 58 | 59 | ``` 60 | 正确案例: myFormVisable, myFormRef 61 | 错误示范: my-form-visable, MyFormVisable, refMyForm 62 | ``` 63 | 64 | 65 | ## 接口命名 66 | 67 | 68 | 使用接口名称:动词 + 模块 + 接口名称 69 | 常见动词:get,set, add,find,detele, update 70 | 常见模块:uc,up 71 | 72 | ``` 73 | 案例:getUcRoleList 74 | export function getUcRoleList(data?: Object) { 75 | return http.get("/uc/role/list", data) 76 | } 77 | ``` 78 | 79 | 80 | ## 方法命名 81 | 82 | * 使用驼峰命名法 83 | * 动词 + 接口 84 | 85 | 常见动词:edit, set, click, add, on, accept, is, get 86 | 如: addClick, setClick, 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /docs/standard/css规范.md: -------------------------------------------------------------------------------- 1 | # css规范 2 | 3 | 4 | ## 基本语法 5 | 6 | * 节点统一2行缩进 7 | * 分号结尾 8 | * 样式之间用空行隔开 9 | * 换行 10 | ``` 11 | /* 错误示范 */ 12 | .element 13 | {color: red}; 14 | 15 | /* 建议 */ 16 | .element { 17 | color: red; 18 | } 19 | ``` 20 | 21 | * 尽量不使用多规则 22 | ``` 23 | /* 错误示范 */ 24 | .element, .dialog { 25 | ... 26 | } 27 | 28 | /* 建议 */ 29 | .element { 30 | ... 31 | } 32 | .dialog { 33 | ... 34 | } 35 | ``` 36 | * 统一双引号 37 | * 颜色统一16进制,如:#001122 38 | 39 | 40 | ## 统一使用scss 41 | 42 | 严谨使用less,当前less只为覆盖antd 43 | 44 | ## 组件级class 45 | 46 | * bem规范 47 | 48 | ``` 49 | b: block 块级 50 | e: element 元素 51 | m: modifier 修饰器名 52 | block-name__element-name-modifier-name,也就是模块名 + 元素名 + 修饰器名。 53 | ``` 54 | 55 | 了解: 56 | utils.bem 57 | 58 | 样式: mixin function 59 | ## 原子类定义 60 | 61 | * 简写说明: 以英文首字母为准 62 | 63 | 规则如下: 64 | * 1)缩写统一用首字母 + "_" + 属性值, 65 | * 2)属性值,数字默认单位px,如数字100表示100px, 66 | %使用percentage缩写, 如100p表示100%。 67 | 其他英文名称直接使用,如left 68 | * 3)由于max跟min缩写都为m,故采用全名,如maxh表示max-height 69 | 70 | 缩写规则如下: 71 | ``` 72 | b: border, 此外,bl,br,bt,bb 73 | bg: background 74 | c: color 75 | d: display 76 | m: margin 此外,ml,mr,mt,mb, m-10-20表示margin: 10px 20px; 77 | p: padding 此外,pl,pr,pt,pb 78 | po: position 79 | f: float 80 | fs: font-size, 会默认设置line-height与font-weight 81 | fw: font-weight, 如fw-500 82 | ff: font-family, 如ff-bold 83 | h: height 84 | minh: min-height 85 | maxh: max-height 86 | w: width 87 | minw: min-width 88 | maxw: max-width 89 | lh: line-height 90 | t: text, 如:text-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;} 91 | ta-l: text-align 92 | ``` 93 | 94 | ## 公用class 95 | * html使用原子类简写,如:\你好\ 96 | 97 | * css使用使用原子类混入,不使用继承 98 | ``` 99 | /* 错误示范 */ 100 | .empty{ 101 | @extend .fs-16; 102 | }; 103 | 104 | /* 建议 */ 105 | .empty{ 106 | @include fs(16) 107 | }; 108 | 109 | ``` 110 | ## class层级叠加 111 | 112 | 方案建议: 113 | * 1)&-继承(推荐) 114 | * 2)同级处理 115 | * 3)首字母缩写 116 | 117 | 不建议: 混合使用 118 | 119 | 推荐1): 120 | ``` 121 | .item { 122 | &-name { 123 | ... 124 | } 125 | &-age { 126 | ... 127 | } 128 | } 129 | ``` 130 | 131 | 方案2: 132 | ``` 133 | .item-name { 134 | ... 135 | } 136 | .item-age { 137 | ... 138 | } 139 | ``` 140 | 141 | 方案3: 142 | ``` 143 | .item { 144 | .i-name { 145 | ... 146 | } 147 | .i-age { 148 | ... 149 | } 150 | } 151 | ``` 152 | -------------------------------------------------------------------------------- /docs/standard/开发规范.md: -------------------------------------------------------------------------------- 1 | # 开发规范 2 | 3 | ## 基本原则 4 | 5 | * 项目统一采用vscode进行开发 6 | * 项目自定义规则等均在.vscode控制 7 | * 设置prettier为默认格式化方案 8 | * PC项目统一使用k8s部署,小程序统一使用云端打包 9 | 10 | ## vscode插件 11 | 12 | * 要求统一安装插件: 13 | 14 | 插件名称|作用 15 | :-|:- 16 | eslint | 检测项目格式 17 | prettier | 文件自动化格式 18 | JavaScript (ES6) code snippets | es6支持 19 | vue | vue高亮,突出vue语法 20 | Git Graph | 查看存储库的Git图,并从该图执行Git操作。 21 | Git History | git历史记录查看 22 | wechat-snippet | 微信小程序代码辅助,代码片段自动完成 23 | Beautify css/sass/scss/less | 格式化样式规则 24 | 25 | 26 | * 第三方建议插件: 27 | 28 | 插件名称|作用 29 | :-|:- 30 | Local History | 本地有文件历史,避免文件丢失 31 | Auto Close Tag | 自动添加关闭标签 32 | Auto Rename Tag | 自动重命名标签 33 | Git History Diff | 对比git不同分支 34 | Chineses | 汉化 35 | Postcode | 类似post man 36 | Draw.io Integration | vscode流程图工具 37 | 38 | 39 | * ide设置,关闭默认格式化方式 40 | 41 | ``` 42 | "editor.formatOnPaste": false, 43 | "editor.formatOnType": false, 44 | "editor.formatOnSave": true, 45 | "editor.codeActionsOnSave": { 46 | "source.fixAll.eslint": true 47 | }, 48 | ``` 49 | 50 | ## eslint配置文件 51 | 52 | 统一放在.eslintrc.js中 53 | 54 | ``` 55 | module.exports = { 56 | root: false, 57 | parser: "vue-eslint-parser", 58 | extends: ["airbnb-base", "plugin:prettier/recommended"], 59 | globals: { // 允许的变量 60 | window: true, 61 | lodash: true, 62 | require: true, 63 | document: true, 64 | localStorage: true 65 | }, 66 | rules: { 67 | indent: [2, 2, { SwitchCase: 1 }], 68 | ... 规则, 69 | "prettier/prettier": [ // prettier配置 70 | "error", 71 | { 72 | singleQuote: false, 73 | endOfLine: "auto", 74 | printWidth: 500, 75 | trailingComma: "none", 76 | semi: true 77 | } 78 | ] 79 | } 80 | }; 81 | 82 | ``` 83 | 84 | 85 | ## prettier格式化 86 | 87 | ``` 88 | "prettier.printWidth": 500, // 超过最大值换行 89 | "prettier.tabWidth": 2, // 缩进字节数 90 | "prettier.useTabs": false, // 缩进不使用tab,使用空格 91 | "prettier.semi": true, // 句尾添加分号 92 | "prettier.singleQuote": true, // 使用单引号代替双引号 93 | "prettier.arrowParens": "avoid", // (x) => {} 箭头函数参数只有一个时是否要有小括号。avoid:省略括号 94 | "prettier.bracketSpacing": true, // 在对象,数组括号与文字之间加空格 "{ foo: bar }" 95 | "prettier.endOfLine": "auto", // 结尾是 \n \r \n\r auto 96 | "prettier.eslintIntegration": false, //不让prettier使用eslint的代码格式进行校验 97 | "prettier.htmlWhitespaceSensitivity": "ignore", 98 | "prettier.ignorePath": ".prettierignore", // 不使用prettier格式化的文件填写在项目的.prettierignore文件中 99 | "prettier.parser": "babylon", // 格式化的解析器,默认是babylon 100 | "prettier.requireConfig": false, // Require a 'prettierconfig' to format prettier 101 | "prettier.trailingComma": "es5", 102 | ``` 103 | 104 | 105 | ## 快捷命令 106 | 107 | 支持page_系列快速页面代码 108 | 支持x_系列快速生成组件 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /docs/standard/js规范.md: -------------------------------------------------------------------------------- 1 | # JS规范 2 | 3 | ## 基本准则 4 | 5 | * 方法长度,不超过100行 6 | * 禁止使用var,强制使用const与let 7 | * 使用字符串模板(注意小程序兼容性)(下方提供案例) 8 | * 尽量使用字面形变量(下方提供案例) 9 | * 数组尽量使用操作函数。(如push等)(下方提供案例) 10 | * 对象与数组,推荐使用解构(下方提供案例) 11 | * 能用箭头函数,不使用普通函数 12 | 13 | 14 | * 推荐简写 15 | ``` 16 | /** 不建议 **/ 17 | const str = "My name is " + name; 18 | 19 | const array = new Array(); 20 | const obj = new Object(); 21 | array[0] = '你好'; 22 | 23 | const first = arr[0]; 24 | const second = arr[1]; 25 | 26 | const atom = { 27 | value: 1, 28 | addValue: function (value) { 29 | return value; 30 | }, 31 | }; 32 | 33 | /** 建议 **/ 34 | const str = `My name is ${name}`; 35 | 36 | const array = []; 37 | const obj = {}; 38 | array.push('你好'); 39 | 40 | const { first, second } = arr; 41 | 42 | const atom = { 43 | obj: 1, 44 | addValue(value) { 45 | return value; 46 | }, 47 | }; 48 | ``` 49 | 50 | ## 函数准则 51 | 52 | * 尽量只做一件事 53 | * 尽量短小,最高不超过100行 54 | * 推荐纯函数,尽量不写非纯函数(下方有说明) 55 | * 推荐采用"函数式编程"的思维(下方有说明) 56 | * 推荐使用"高阶函数"(下方有说明) 57 | * 推荐函数柯里化(下方有说明) 58 | * 了解递归函数 59 | 60 | --- 61 | 62 | **纯函数的定义**: 当一个函数的输出不受外部环境影响,同时也不影响外部环境时,该函数就是纯函数,也就是它只关注逻辑运算和数学运算,同一个输入总得到同一个输出。 63 | 64 | 纯函数如:Array.prototype.map, 非纯函数如: Array.ptototype.splice 65 | 66 | --- 67 | 68 | **函数式编程的理解:** 69 | 70 | 1.避免多次赋值变量 71 | 72 | 2.拒绝使用eval 73 | 74 | 3.不修改内核对象 75 | 76 | 4.优先使用函数而不是方法(了解一下javascript中函数和方法的区别: https://blog.csdn.net/qq_44163269/article/details/104627274) 77 | 78 | --- 79 | 80 | 81 | **高阶函数的概念:** 以一个函数作为参数,以一个函数作为结果。如常用的reduce。 82 | 83 | 84 | ## 循环方法 85 | 86 | 对比优势for, forEach, map, filter, reduce, find, some等 87 | 88 | * *遍历当前对象: forEach 89 | * *计算总算:reduce 90 | * *过滤数据:filter 91 | * *获取新对象:map 92 | * 查找新对象:find 93 | * 每一项返回true,则返回true: every 94 | * 任一项返回true,则返回true:some 95 | 96 | 97 | ## 判断方法 98 | 99 | * 双重否定!! 100 | 101 | * || 与 && 102 | 103 | 表达式a && 表达式b : 计算表达式a(也可以是函数)的运算结果, 104 | 如果为 True, 执行表达式b(或函数),并返回b的结果; 105 | 如果为 False,返回a的结果; 106 | 107 | 表达式a || 表达式b : 计算表达式a(也可以是函数)的运算结果, 108 | 如果为 Fasle, 执行表达式b(或函数),并返回b的结果; 109 | 如果为 True,返回a的结果; 110 | ``` 111 | if (this.uploadData.length < this.num){ 112 | this.showUploadBtn = true; 113 | } 114 | 115 | 优化后: 116 | this.uploadData.length < this.num && ( this.showUploadBtn = true) 117 | ``` 118 | 119 | 120 | * 三元表达式 121 | 122 | 能用三元表达式解决的问题,尽量不使用if。 123 | 124 | ``` 125 | if(name === '小明'){ 126 | this.show = true 127 | }else{ 128 | this.show = false 129 | } 130 | 131 | 优化后: 132 | this.show = name === '小明' ? true : false; 133 | ``` 134 | 135 | * ES10 136 | 137 | * 多层判断以上,使用switch或对象获取。 138 | 139 | ## 异步方案 140 | 141 | 异步解决方案统一使用async, await。无需捕捉异常的情况下,尽快少使用promise, then。 142 | 143 | ``` 144 | const res = await test1().catch((err)=>{ 145 | console.log(new Error) 146 | }) 147 | ``` 148 | --------------------------------------------------------------------------------