处理组件的边界情况
$root
$parent
$children
$refs
依赖注入 provide / inject
-
$attrs
- 把父组件中非 prop 属性绑定到内部组件
-
$listeners
- 把父组件中的DOM对象的原生事件绑定到内部组件
- 从父组件传给自定义子组件的属性,如果没有 prop 接收会自动设置到子组件内部最外层标签上,如果是class和style的话,会合并最外层标签的class 和 style
- 如果子组件中不想继承父组件传入的非 prop 属性,可以使用 inheritAttrs 禁用继承 然后通过 v-bind="$attrs" 把外部传入的非 prop属性设置给希望的标签上,不会改变class和style
快速原型开发
- VueCLI 中提供了一个插件可以进行原型快速开发
- 需要先额外安装一个全局的扩展
- npm install -g @vue/cli-service-global
- 使用 vue serve 快速查看组件的运行效果
vue serve
- vue serve 如果不指定参数默认会在当前目录找以下的入口文件
- main.js ,index.js,App.vue, app.vue
- 可以指定要加载的组件
- vue serve ./src/login.vue
快速原型开发 - ElementUI
安装 ElementUI
- 初始化 package.json
- npm init -y
- 安装 ElementUI
- vue add element
- 加载 ElementUI,使用 Vue.use() 安装插件
组件分类
- 第三方组件
- 基础组件
- 业务组件
两种项目的组织方式
- Multirepo(Multiple Repository)
- 每一个包对应一个项目
- Monorepo(Monolithic Repository)
- 一个项目仓库中管理多个模块/包
-
项目中有一个packages 文件夹,文件夹中所有文件都是一个包,每个包就是一个组件。
-
- 一个项目仓库中管理多个模块/包
Storybook
- 可视化的组件展示平台
- 在隔离的开发环境中,以交互式的方式展示组件
- 在主程序之外运行,独立开发组件
- 支持的框架
- React,React Native,Vue,Angular,Ember,HTML,Svelte,Mithril,Riot
Storybook 安装
- 自动安装
- npx -p @storybook/cli sb init --type vue (在当前已有的项目中创建 在空项目中 --type vue 强制使用vue)
- yarn add vue
- vue yarn add vue vue-loader vue-template-compiler --dev
npx -p @storybook/cli sb init --type vue安装过程中出现以下报错
这里可能有两种情况
1、npm的版本过低
输入npm install -g install 对版本进行更新
- npm 无法更新 可能与node版本不匹配,npm用的还是原来的,在c盘 user下找到npm,npm-cache两个文件 将其删除后重新执行npm install -g install 便可
2、node_cache的路径中带有空格
输入npm config list查看cache路径
输入npm config set cache “D:\Nodejs\node_cache" 把cache的路径指定到"D:\Nodejs\node_cache”,这里的路径是自定义的,不包含空格即可以
storybook-demo代码地址
yarn workspaces 工作区
packages下不同的组件中可能依赖不同的第三方包,也有可能几个依赖同一个包,如果各自安装 会出现重复下载相同依赖的情况,使用yarn workspaces不同组件依赖相同包只会下载一次 并且将依赖包提升到根目录中的node_modules中
开启yarn的工作区
- 项目根目录的 package.json
"private":true, //提交github或者发布到npm时,禁止把当前根目录的内容进行提交
"workspaces":[ //设置工作区的子目录 packages目录下
"packages/*"
]
开启 yarn workspaces 使用
- 给工作区根目录安装开发依赖 -D(开发依赖) -W(工作区) 安装到工作区根目录
- yarn add jest -D -W
- 给指定工作区安装依赖 my-button(包对应的package.json 中的name)
- yarn workspace my-button add loadsh@4
- 给所有的工作区安装依赖
- yarn install
Lerna
- Lerna 是一个优化使用 git 和 npm 管理多包仓库的工作流工具
- 用于管理具有多个包的 JavaScript 项目
- 它可以一键把代码提交到 git 和 npm 仓库
Lerna使用
- 全局安装
- yarn global add lerna
- 初始化
- lerna init
- 发布
- lerna publish
script命令中配置 lerna 命令 执行lerna publish 打包发布
1.连接远程仓库
2.登录npm
添加自己的npm账号
添加完成后 npm whoami 出现npm用户账号 此时登录成功
3.npm config get registry 查看当前镜像源是否是npmjs
4.yarn lerna 发布
Vue组件的单元测试
- 单元测试就是对一个函数的输入和输出进行测试,使用断言的方式 输入对应的值对输出的值进行判定 实际的输出与预测输出是否相同
- 对组件的各种状态,行为进行测试
组件单元测试好处 - 提供描述组件行为的文档
- 节省手动测试的时间
- 减少研发新特性时产生的bug
- 改进设计
- 促进重构
安装依赖
- Vue Test Utils
- Jest
- vue-jest
- babel-jest
- 安装
- yarn add jest @vue/test-utils vue-jest babel-jest -D -W
配置测试脚本
- package.json
"scripts":{
"test":"jest",
...
}
Jest 配置文件
- jest.config.js
Babel 配置文件 - babel.config.js
module.exports = {
presets:[
['@babel/preset-env']
]
}
Babel 桥接
- yarn add babel-core@bridge -D -W
** Jest 常用API**
**Vue Test Utils 常用 API **
storybook-demo代码地址
具体参考其中input组件
Rollup打包
项目发布之前,对项目打包处理
- Rollup 是一个模块打包器
- Rollup 支持 Tree-shaking
- 打包的结果比 Webpack要小
- 开发框架/组件库的时候使用 Rollup 更合适
安装依赖
- Rollup
- rollup-plugin-terser //对代码进行压缩
- rollup-plugin-vue@5.1.9 //将单文件组件编译成js代码 最新版将vue3.0转换 在此指定特定版本 对vue2.0编译
- vue-template-compiler
Rollup配置文件
单独包打包,在button包下配置后 执行 yarn workspace my-button run build
storybook-demo代码地址
具体参考其中button组件
通过一个命令将所有组件打包
- @rollup/plugin-json //让rollup可以把json文件作为模块加载
- rollup-plugin-postcss
- @rollup/plugin-node-resolve -D -W //打包过程中将依赖的第三方包 打包进来
设置环境变量
- yarn add cross-env -D -W
package.json
"scripts": {
"test": "jest",
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook",
"lerna": "lerna publish",
"build": "rollup -c",
"build:prod":"corss-env NODE_ENV=production rollup -c", //生产环境打包
"build:dev":"corss-env NODE_ENV=development rollup -c" //开发环境打包
}
生产环境打包后的代码是压缩后的代码
清理
- 清楚所有组件包中的node_modules,使用lerna clean清除
配置script
"scripts": {
"test": "jest",
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook",
"lerna": "lerna publish",
"build:prod":"corss-env NODE_ENV=production rollup -c",
"build:dev":"corss-env NODE_ENV=development rollup -c",
"clean": "lerna clean"
},
yarn clean
清理dist
使用第三方 rimraf
- yarn add rimraf -D -W
每个包下得package.json 中配置
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "rollup -c",
"del": "rimraf dist"
},
- yarn workspaces run del
运行所有包中的del命令
基于模板生成组件的基本结构
使用Plop构建模板文件
- yarn add plop -W -D
storybook-demo代码地址
具体参考其中plop-template文件
配置plopfile.js
package.json 配置plop命令
"scripts": {
"test": "jest",
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook",
"lerna": "lerna publish",
"build:prod": "corss-env NODE_ENV=production rollup -c",
"build:dev": "corss-env NODE_ENV=development rollup -c",
"clean": "lerna clean",
"plop":"plop"
},
- yarn plop
输入创建组件名 生成模板
web components 一个示例(与以上无关 在此记录下)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>web components</title>
</head>
<body>
<input is="my-input"></body>
<my-custom></my-custom>
<script>
customElements.define('my-input',class extends HTMLInputElement{
constructor(){
super()
this.placeholder = 'myinput'
}
},{extends:'input'})
customElements.define('my-custom',class extends HTMLElement {
constructor(){
super()
console.log(this) //<my-custom></my-custom>
this.innerHTML = 'abc'
}
static observedAttributes = ['color'] //相当于vue data
connectedCallback(){//相当于mounted
}
disconnectedCallback(){//相当于vue的unmounted
}
adoptedCallBack(){//当组件被收养,即剪切 document.adoptNode()
}
attributeChangedCallback(name,oldvalue,newvalue){//属性变化触发
if(name === 'color'){
this.style.color = newvalue
}
}
})
customElements.get('my-custom') //返回它的类
//customElements.whenDefined返回一个promise
customElements.whenDefined('my-custom').then(()=>{
}).catch(err=>{
})
customElements.upgrade('my-custom')
</script>
</body>
</html>