vue2二次封装element组件库

350 阅读2分钟

参考文章juejin.cn/post/721394…

创建vue2项目

创建vue2项目,因为是npm​因此不需要安装vue全家桶​,只是安装了vue​、less

image

E:\otherCode\npmBag>vue create avui


Vue CLI v4.5.17
┌──────────────────────────────────────────┐
│                                          │
│   New version available 4.5.17 → 5.0.8   │
│                                          │
└──────────────────────────────────────────┘

? Please pick a preset: Manually select features
? Check the features needed for your project: Choose Vue version, Babel, PWA, CSS Pre-processors
? Choose a version of Vue.js that you want to start the project with 2.x
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): Less
? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated config files
? Save this as a preset for future projects? No


Vue CLI v4.5.17

删除无用的代码和目录,将src​改为examples

修改vue.config.js​文件

const path = require("path");
module.exports = {
  // 修改 src 目录 为 examples 目录
  pages: {
    index: {
      entry: "examples/main.js",
      template: "public/index.html",
      filename: "index.html",
    },
  },
  // 强制内联CSS(使用组件时,不需要再引入css)
  css: {
    extract: false,
  },
  //   别名
  // 别名配置通过 configureWebpack
  configureWebpack: {
    resolve: {
      alias: {
        "@": path.resolve(__dirname, "examples"), //配置src目录的别名
        "components": path.resolve(__dirname, "examples/components"), //配置公共组件目录的别名
        "~": path.resolve(__dirname, "packages"),
      },
    },
  },
};

创建docs​后面会用来创建组件文档,packages​组件源码,删除无用的文件

avui
 ├── babel.config.js  
 ├── docs # 组件库文档
 ├── examples  # 原src目录  项目主文件
 │   ├── App.vue
 │   ├── components
 │   │   └── HelloWorld.vue
 │   ├── main.js
 │   └── registerServiceWorker.js
 ├── folder-alias.json # vscode插件
 ├── package-lock.json
 ├── package.json
 ├── packages # 组件源码
 ├── public
 │   ├── favicon.ico
 │   ├── index.html
 │   └── robots.txt
 ├── README.md
 └── vue.config.js

完善项目

pc端​一般都是使用element ui​,因此安装element ui​,并且全局引入

npm i element-ui -S

main.js

import Vue from "vue";
import App from "./App.vue";
import "./registerServiceWorker";
import ElementUI from "element-ui";
import "element-ui/lib/theme-chalk/index.css";

Vue.config.productionTip = false;

Vue.use(ElementUI);

new Vue({
  render: h => h(App),
}).$mount("#app");

创建组件

components​下面,简单创建一个组件einp.vue

<template>
  <div>
    <el-input v-model="input" placeholder="请输入内容" clearable></el-input>
  </div>
</template>

<script>
  export default {
    name: "EInp",
    data() {
      return {
        input: "",
      };
    },
  };
</script>

<style></style>

app.vue​中引入验证

将验证好的组件拷贝到packages​文件夹中,结构如下

image

每个组件都是一个文件夹,文件夹里面是src​文件夹和index.js​,src​是每个组件单独的开发目录,因为一个组件可能会有多个文件,index.js​是用来注册组件的

import EInp from "./src";

EInp.install = function (Vue) {
  Vue.component(EInp.name, EInp);
};
export default EInp;

packages​创建index.js​用来导出整合所有的组件并对外导出

导入组件,组件必须要声明name

定义install​,接受Vue​作为参数,使用use​注册为组件,这一块没怎么看懂,后面在研究

继续按需导出,

默认导出版本号和install​暂时没了解

// 导入所有的组件
import EInput from "./EInp";

import { version } from "../package.json";

// 组件列表
const components = [EInput];

// 定义 install 方法,接收 Vue 作为参数。如果使用 use 注册插件,则所有的组件都将被注册
const install = function (Vue) {
  // 判断是否安装
  if (install.installed) return;
  install.installed = true;
  // 遍历注册全局组件
  components.map(component => Vue.component(component.name, component));
};

// 判断是否是直接引入文件
if (typeof window !== "undefined" && window.Vue) {
  install(window.Vue);
}

// 按需导出
export { EInput };

export default {
  version,
  // 导出的对象必须具有 install,才能被 Vue.use() 方法安装
  install,
};

install​函数的作用:

  1. 注册组件install​ 函数接收 Vue​ 构造器作为参数。在函数内部,它遍历了一个名为 components​ 的数组,该数组包含了要注册的自定义Vue组件(例如 EInput​)。通过 Vue.component​ 方法,将这些组件注册为全局组件,使得它们可以在任何Vue实例中直接使用。
  2. 防止重复安装install​ 函数中有一个条件判断 if (install.installed) return;​,这是为了避免插件被多次安装。如果插件已经安装过(install.installed​ 为 true​),则直接返回,避免重复注册组件,这通常发生在用户意外地多次引入插件库时。
  3. 自动安装: 通过 if (typeof window !== "undefined" && window.Vue) { install(window.Vue); }​,代码检查当前环境是否存在全局的 window.Vue​ 对象。如果存在,这意味着Vue已经被加载到全局环境中,因此install​函数会立即调用自身,自动将插件安装到当前的Vue实例中。
  4. 暴露组件和插件信息: 最后,代码导出了组件 EInput​ 和整个插件对象,其中包含了版本信息 version​ 和 install​ 函数。这样,用户既可以按需导入单个组件,也可以通过 Vue.use()​ 方法全局安装整个插件。

总结来说,install​ 函数是实现Vue插件的关键,它负责组件的注册和插件的安装逻辑,确保组件能够在Vue应用中正常使用。

默认导出版本号​和install​的用途:

默认导出版本号 (version​) 和 install​ 函数通常是Vue.js插件开发中的两个关键元素,它们各自承担着特定的用途:

默认导出版本号 (version)

  • 用途:版本号用于标识插件的当前版本状态。这对于用户管理和追踪他们正在使用的插件版本非常重要。当发布新功能、修复错误或进行重大更改时,版本号会相应更新,用户可以通过比对版本号来决定是否需要更新插件。
  • 好处:明确的版本信息有助于开发者在遇到问题时快速定位问题所在,是否为特定版本的已知问题;同时也便于在社区交流、文档查阅时,确保参考的信息与当前使用插件版本相匹配。

install函数

  • 用途install​ 函数是Vue插件机制的核心部分,它定义了如何将插件的功能集成到Vue应用中。Vue框架在调用 Vue.use(plugin)​ 方法时,会执行此函数。

    • 注册全局组件/指令/过滤器:在 install​ 函数内部,可以注册全局的Vue组件、自定义指令、过滤器等,使得这些功能在整个Vue应用中可用。
    • 配置全局选项:可以用来修改Vue的全局配置,比如改变Vue的原型链(Vue.prototype​),添加全局混入(mixin)等。
    • 初始化插件逻辑:执行任何插件所需的初始化逻辑,比如设置监听器、初始化数据等。
  • 好处:通过统一的接口 (Vue.use()​),使得插件的安装过程标准化,易于理解和维护。开发者无需关心每个插件的具体集成方式,提高了代码的可复用性和可维护性。

综上所述,默认导出的版本号方便了版本管理和问题追踪,而 install​ 函数则是Vue插件集成的核心机制,确保了插件能够以一种统一且高效的方式被Vue应用所采用。

经过搜索资料得知疑惑的地方

修改package.json

修改package.json​文件里面有很多字段要填写,否则不能正确发布。最重要的是以下几个:

  • name: 包名,该名字是唯一的。可在 npm 官网搜索名字,如果存在则需换个名字。
  • version: 版本号,不能和历史版本号相同。
  • main: 入口文件,默认为 index.js,这里改为 lib/t-ui-plus.umd.cjs。
  • module: 模块入口,这里改为 lib/t-ui.umd.min.js。
  • private:false
  • repository----仓库地址
  • homepage----组件文档或demo示例
  • keywords-----关键字(便于搜索)
  • files ---- npm打包上传的文件

添加一条打包命令

Vue CLI 中提供了构建库的方法,你可以通过下面的命令将一个单独的入口构建为一个库:

vue-cli-service build --target lib --name myLib [entry]

target: 改为 lib 可启用构建库模式应用模式
name: 构建库输出的文件名;
dest: 构建的输出目录,默认为 dist;
entry: 打包入口文件路径;

vue-cli-service build --target lib --name aiui --dest ui packages/index.js
{
  "name": "aw-v2-el-ui",
  "version": "0.0.1",
  "description": "描述",
  "main": "ui/awUi-plus.umd.cjs",
  "module": "ui/awUi.umd.min.js",
  "private": false,
  "repository": "仓库地址",
  "homepage": "说明文档地址",
  "keywords": "关键词",
  "author": "作者",
  "files": [
    "ui"
  ],
  "scripts": {
    "dev": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lib": "vue-cli-service build --target lib --name awUi --dest ui packages/index.js"
  },
  "dependencies": {
    "core-js": "^3.6.5",
    "element-ui": "^2.15.14",
    "register-service-worker": "^1.7.1",
    "vue": "^2.6.11"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "~4.5.17",
    "@vue/cli-plugin-pwa": "~4.5.17",
    "@vue/cli-service": "~4.5.17",
    "less": "^3.0.4",
    "less-loader": "^5.0.0",
    "vue-template-compiler": "^2.6.11"
  }
}

验证

在终端执行npm run lib​进行打包,打包之后会多出ui​文件夹

将打好的包发布到npm

 E:\otherCode\npmBag\avui> npm login  
npm notice Log in on http://***********/
Username: 账号
Password: 密码                                                                    
Email: (this IS public) 邮箱                                         
Logged in as luzhibin on http://******/.
E:\otherCode\npmBag\avui> npm   publish 

注:上传的 npm 包,在 72小时 后不可删除,如果是测试用的包,记得 72小时 内删除

创建一个新的vue2​项目,下载我们上传的包

main.js​中引入并注册包

import Vue from "vue";
import App from "./App.vue";
import "./registerServiceWorker";
import router from "./router";
import store from "./store";
import ElementUI from "element-ui";
import "element-ui/lib/theme-chalk/index.css";

import awV2ElUi from "aw-v2-el-ui";

Vue.config.productionTip = false;

Vue.use(ElementUI);
Vue.use(awV2ElUi);
new Vue({
  router,
  store,
  render: h => h(App),
}).$mount("#app");

按需引入

 import { Inp } from "aw-v2-el-ui";
  export default {
    components: { Inp },
{

创建说明文档

直接将原项目中的docs​文件夹复制过来,删除多余的文件,删除之后的目录结构如下

docs
 ├── .vuepress
 │   ├── components
 │   │   ├── common
 │   │   │   └── code-format.vue # 封装的组件  
 │   │   └── docsComponents  # 封装的组件 demo
 │   │       ├── EInp # 组件的demo  里面包含组件的各种用法
 │   │       └── TButton
 │   ├── config.js # 配置文件
 │   ├── enhanceApp.js # 使用各种插件
 │   └── public  # 保持原来的不动
 │       ├── css
 │       │   ├── antd.scss
 │       │   ├── element-ui.scss
 │       │   ├── element-variables.scss
 │       │   ├── iconfont
 │       │   ├── index.scss
 │       │   └── variables.scss
 │       ├── favicon.ico
 │       ├── hero.jpg
 │       ├── utils
 │       │   ├── constants.js
 │       │   ├── directive.js
 │       │   ├── directives
 │       │   ├── filters.js
 │       │   ├── index.js
 │       │   └── resetMessage.js
 │       └── wocwin.jpg
 ├── baseComponents # 组件文档
 │   ├── EInp  # 每一个组件的文档
 │   │   └── base.md
 │   ├── README.md # 组件文档的入口
 │   └── TButton
 │       └── base.md
 ├── changeLog # 升级记录
 │   └── log.md
 ├── projectProblem # 项目问题  暂时没有用到
 │   ├── axios.md
 │   ├── keepAlive.md
 │   └── permission.md
 └── README.md  # 项目首页

docs\.vuepress\components\docsComponents​目录下创建组件的demo

组件库在docs\.vuepress\enhanceApp.js​中已经全局引入了,因此组件可以直接使用

<template>
  <div>
    <EInp />
  </div>
</template>

<script>
  export default {
    name: "t-EInp-demo",
  };
</script>

<style></style>

docs\baseComponents​目录下创建组件的说明文档

# EInp 输入框

---
<!-- 固定写法 -->
<common-code-format>
<!-- 相对于.vuepress文件夹的绝对路径  -->
  <docsComponents-EInp-index slot="source"></docsComponents-EInp-index>
在组建中的配置:

`继承el-button所有属性` <br/>

新增`time`属性(多少时间内点击;默认 1 秒)<br/>

<!-- 引入代码 -->
<<< @/docs/.vuepress/components/docsComponents/EInp/index.vue =
</common-code-format>

仓库地址 banmag.cn:6080/npmbag/v2co…