当前位置: 首页>数据库>正文

封装Vue.js组件库

处理组件的边界情况

  • $root

  • $parent

  • $children

  • $refs

  • 依赖注入 provide / inject

  • $attrs

    • 把父组件中非 prop 属性绑定到内部组件
  • $listeners

    • 把父组件中的DOM对象的原生事件绑定到内部组件
  1. 从父组件传给自定义子组件的属性,如果没有 prop 接收会自动设置到子组件内部最外层标签上,如果是class和style的话,会合并最外层标签的class 和 style
  2. 如果子组件中不想继承父组件传入的非 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 文件夹,文件夹中所有文件都是一个包,每个包就是一个组件。


        封装Vue.js组件库,第1张
        Monorepo目录结构.png

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安装过程中出现以下报错


封装Vue.js组件库,第2张
图片.png

这里可能有两种情况
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 工作区

封装Vue.js组件库,第3张
图片.png

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
封装Vue.js组件库,第4张
图片.png

script命令中配置 lerna 命令 执行lerna publish 打包发布

1.连接远程仓库
2.登录npm


封装Vue.js组件库,第5张
图片.png

添加自己的npm账号


封装Vue.js组件库,第6张
图片.png

添加完成后 npm whoami 出现npm用户账号 此时登录成功
3.npm config get registry 查看当前镜像源是否是npmjs
封装Vue.js组件库,第7张
图片.png

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
    封装Vue.js组件库,第8张
    jest.config.js.png

    Babel 配置文件
  • babel.config.js
module.exports = {
  presets:[
    ['@babel/preset-env']
  ]
}

Babel 桥接

  • yarn add babel-core@bridge -D -W

** Jest 常用API**


封装Vue.js组件库,第9张
Jest 常用API.png

**Vue Test Utils 常用 API **


封装Vue.js组件库,第10张
Vue Test Utils 常用 API.png

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配置文件
    封装Vue.js组件库,第11张
    Rollup配置文件.png

单独包打包,在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>

https://www.xamrdz.com/database/6rk1997459.html

相关文章: