基于element-ui二次封装vue组件发布到npm

5,976 阅读3分钟

公司vue项目基于element-ui实现,很多地方都回多次用到表格、表单、弹窗等组件,于是就基于element-ui的这几个组件进行二次封装发布到npm上,保证任何基于element-ui的vue项目都可以使用这套插件。

下面是vue2.X的项目,vue3对应的element-plus不是很稳定,就没用。

一、准备

1. 创建一个vue2的工程项目

目录结构

image.png

2. 安装element-ui并引入

npm i element-ui -S

3. 新建文件

src文件下自定义elementPlugin文件夹,用于封装用。
elementPlugin文件夹下自定义添加index.js文件(总的入口文件)和Cz-Table文件夹。
Cz-Table文件夹下定义一个index.vue文件。
如图:

image.png

二、开发

1. 写要封装的组件

index.vue文件中封装element-ui的Table组件,这里就不封装了,测试用,直接用放入官网组件案例。

<template>
  <div class="tt">
    <el-table :data="tableData" style="width: 100%">
      <el-table-column prop="date" label="日期" width="180"> </el-table-column>
      <el-table-column prop="name" label="姓名" width="180"> </el-table-column>
      <el-table-column prop="address" label="地址"> </el-table-column>
    </el-table>
  </div>
</template>

<script>
export default {
  name: "Cz-Table",
  data() {
    return {
      tableData: [
        {
          date: "2016-05-02",
          name: "王小虎",
          address: "上海市普陀区金沙江路 1518 弄",
        },
        {
          date: "2016-05-04",
          name: "王小虎",
          address: "上海市普陀区金沙江路 1517 弄",
        },
        {
          date: "2016-05-01",
          name: "王小虎",
          address: "上海市普陀区金沙江路 1519 弄",
        },
        {
          date: "2016-05-03",
          name: "王小虎",
          address: "上海市普陀区金沙江路 1516 弄",
        },
      ],
    };
  },
};
</script>

<style scoped>
.tt {
  width: 1000px;
  border: 1px solid #999;
}
</style>

ps: vue文件中必须要写name, 下面组件引入注册会用到

2.入口文件index.js

在入口文件中引入书写好的index.vue文件,然后进行注册

两种方法:
1、使用import导入操作

import CzTable from './Cz-Table/index.vue';
...
...
import xxx from './xxx/xxx.vue';

const components = [ CzTable, ..., xxx ]
/*
*  install的固定写法
*/
const install = (Vue) => {
    if (install.installed) return   // 判断是否安装注册过
    components.forEach(component => Vue.component(component.name, component)) // 遍历并注册组件
}

if (typeof window !== 'undefined' && window.Vue) {
    install(window.Vue) // window中有Vue时去install()
}

export default {
    install
}

2、使用脚手架中的require.context()获取vue文件

const requireComponents = require.context('./', true, /\.vue$/) // 代替import进行动态引入,webpack中方法

const install = (Vue) => {
    if (install.installed) return
    // 遍历引入组件
    requireComponents.keys().forEach(fileName => {
        const config = requireComponents(fileName) // 当前组件
        const componentName = config.default.name  // 获取组件名,即vue文件中的name
        Vue.component(componentName, config.default) // 注册组件
    })
}

if (typeof window !== 'undefined' && window.Vue) {
    install(window.Vue)
}

export default {
    install
}

image.png

三、发布

1.准备工作

首先要有一个npm的账号,没有就先注册

然后在package.json文件中修改信息

{
  "name": "cz-element",   // 包名
  "version": "0.0.8",   // 版本号
  "private": false,   // 是否私有
  "main": "src/elementPlugin/index.js",   // 入口文件
  "author": "村长", // 作者
  "description": "基于element-ui实现的二次封装", // 简介
  "license": "MIT", // 协议
  "keywords": [  // 关键字
    "vue2",
    "element-ui"
  ],
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint",
    "lib": "vue-cli-service build --target lib --name cz-element --dest lib src/elementPlugin/index.js" // 组件打包命令
  },
  ...
  ...
  }

其中必填的有:
name:要发布的包名,方便npm上搜索,名字不能是npm上已经存在的。
version:版本号,每次发布到npm前要修改版本号。
private:改为false或删掉private,如果是true会发布失败的。
main:入口文件地址,可以是src/elementPlugin/index.js文件,也可以是打包后的js文件。
scripts下自定义的打包命令:打包后发布上去才能正常使用(我是这样的)。

image.png 接下来可以对README.md进行编写

image.png

最后打包

npm run lib

打包完成后会有如下图的一个包

image.png

2.使用命令发布

npm login

先进行登录,依次输入npm的账号、密码、邮箱

image.png

npm publish

然后发布,成功后结尾会有包名+@+版本号

image.png

发布成功就能在npm官网检索到了

image.png

image.png

ps:如果首次发布时报错可能有以下原因:

1、注册npm的邮箱没有验证;
2、package.json中的文件名是npm上已存在的,可以打包发布前去官网搜索验证;
3、没有进行npm login登录;
4、网络问题。

发布流程:修改版本号——> 打包——> npm login——> npm publish

项目没关闭npm login登录一次就可以

四、使用

找个element-ui的项目,安装发布的插件

npm i cz-element

就可以在node_modules中看到了安装的插件了

image.png

然后在main.js中导入

import CZ from 'cz-element'
import 'cz-element/lib/cz-element.css'

Vue.use(CZ)

vue文件中使用

<Cz-Table></Cz-Table>  // 标签名和上面index.vue中的name保持一致

效果图

image.png


end...