教你一步步封装vue组件并发布到npm

前言

在开发项目过程中,通常会用到很多功能和设计相类似的组件,为了避免重复造轮子,我们经常会用到一些第三方组件,比如 vux,vant。但是这样会引入太多没用到的组件,造成打包体积过大。所以我们有必要封装一些基础的组件用于开发。

下面我为大家介绍如何封装vue的toast和dialog组件并上传到npm。

GitHub: github.com/Michael-lzg…
掘金:https://juejin.im/post/5dc8c1...

扫码以下二维码可以先睹为快哦

组件封装必要性

  • 提高开发效率,避免重复造轮子
  • 调用同一组件,统一 UI 样式
  • 便于协同开发,提高可维护性
  • 减少对第三方组件的使用,定制个性化的组件

toast 和 dialog 组件封装

toast 和 dialog 组件基本是每一个移动端项目都会用到的,下面我将介绍如何封装这两个组件,并发布到 npm 供下载使用。

1.必备知识储备

  • vue 的基础知识
  • Vue.extend 构造器
  • $mount 手动挂载实例
  • vue 组件的传值传参
  • 理解 Vue 构造函数及 prototype
  • webpack 打包
  • npm 基础知识

最终我们要达到这样的效果,从 npm 下载依赖包,直接调用

this.$toast({ msg: '手机号码不能为空' })

this.$toast({
  msg: '成功提示',
  type: 'success'
})

this.$dialog({
  title: '删除提示',
  text: '是否确定删除此标签?',
  showCancelBtn: true,
  confirmText: '确认',
  confirm(content) {
    alert('删除成功')
  }
})

效果图如下

2.编写组件

  • 根据传入的 type 确定弹窗的类型(成功提示,失败提示,警告,加载,纯文字)
  • 设置弹窗消失的时间
<template>
  <div>
    <transition name="fade">
      <div class="little-tip" v-show="showTip">
        <img src="assets/img/success.png" alt="" width="36" v-if="type=='success'"/>
        <img src="assets/img/fail.png" alt="" width="36" v-if="type=='fail'"/>
        <img src="assets/img/warning.png" alt="" width="36" v-if="type=='warning'"/>
        <img src="assets/img/loading.png" alt="" width="36" v-if="type=='loading'" class="loading"/>
        <span>{{msg}}</span>
      </div>
    </transition>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        showTip: true,
        msg: '',
        type: ''
      }
    },
    mounted() {
      setTimeout(() => {
        this.showTip = false
      }, 1500)
    }
  }
</script>
<style lang="less" scoped="">
  /* 样式略 */
</style>

3.注册 toast 组件

3.1、利用 Vue.extend 构造器把 toast 组件挂载到 vue 实例下

import Vue from 'vue'
import Main from './main.vue'

let Toast = Vue.extend(Main)

let instance
const toast = function(options) {
  options = options || {}
  instance = new Toast({
    data: options
  })
  instance.vm = instance.$mount()
  document.body.appendChild(instance.vm.$el)
  return instance.vm
}
export default toast

3.2 在 main.js 引入 toast 组价并挂载在 vue 原型上

import Vue from 'vue'
import toast from './components/toast'
Vue.prototype.$toast = toast

至此就可以在项目中直接调用组件了。dialog 组件的封装也是同样的方法。
下面介绍如何把组件发布到 npm 上。

发布 npm 组件

1. 在 src 下新建 index.js 文件,引入需要上传的组件

这里主要用到 vue 两种注册组件和插件的方法

  • Vue.component(key, val)
  • Vueu.use()
import toast from './components/toast'
import dialog from './components/dialog'
const YMUI = {
  // 这里是后续补充的组件
}

const install = function(Vue, opts = {}) {
  if (install.installed) return
  Object.keys(YMUI).forEach(key => {
    Vue.component(key, YMUI[key])
  })

  Vue.prototype.$toast = toast
  Vue.prototype.$dialog = dialog
}

// auto install
if (typ window !== 'undefined' && window.Vue) {
  install(window.Vue) // 通过use方式全部引入
}

const API = {
  install,
  ...YMUI
}

export default API // 通过插件单独引入

2.修改 webpack.dist.prod.conf 的打包配置

  • entry: 入口文件配置,打包时入口文件为 index.js
  • filename: 是打包生成文件的名字
  • libraryTarget: 配置 webpack 打包内容的模块方式的参数
module.exports = {
  context: path.resolve(__dirname, '../'),
  entry: {
    app: './src/index.js'
  },
  output: {
    path: config.build.assetsRoot,
    filename: 'vue-mobile-ymui.js',
    libraryTarget: 'umd',
    umdNamedDefine: true,
    publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath
  }
}

3.修改 package.json 的配置

  • name: 组件名字
  • version: 版本号
  • main: 字段,指定了该 npm 包引用的入口(记住一定要记得添加,并且文件名应与上面第二点提到的保持一致)
{
  "name": "vue-mobile-ymui",
  "version": "1.0.3",
  "description": "a mobile compoment",
  "author": "lzg",
  "private": false,
  "main": "./dist/vue-mobile-ymui.js",
  "scripts": {
    "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
    "start": "npm run dev",
    "lint": "eslint --ext .js,.vue src",
    "build": "node build/build.js",
    "build-js": "webpack --config build/webpack.dist.prod.conf.js"
  },
}

4.发布 npm 组件

1.npm login 注册并登陆 npm 账号
2.npm publish 发布组件

注意点:

  • 邮箱必须要先注册
  • 包名不能有大写字母/空格/下滑线,不能重复

5.升级 npm 包

1.打包修改后的代码
2.修改包的版本(package.json 里的 version 字段) version 的字段表现为:”version“:"x.y.z"

  • 有很大的改动,无法向后兼容,增加 x
  • 增加了新特性,但仍能向后兼容,增加 y
  • 修复 bug,小改动,增加 z

使用 npm 组件

1.安装依赖

npm install vue-mobile-ymui

2.在 mian.js 引入并 use()

import UI from 'vue-mobile-ymui'
Vue.use(UI)

3.在页面直接调用

this.$toast({
  msg: '成功提示',
  type: 'success'
})

后续展望

至此,封装vue组件并发布到npm并调用的方法就接受完了。
后续的继续封装其他组件,敬请关注

相关文章

搭建一个vue-cli的移动端H5开发模板
从零开始构建一个webpack项目
总结几个webpack打包优化的方法
一文读尽前端路由、后端路由、单页面应用、多页面应用
从一道面试题中总结JS作用域,this 指向和箭头函数
关于几个移动端软键盘的坑及其解决方案
浅谈JavaScript的防抖与节流
总结几种数组去重的方法
浅谈JavaScript的 深拷贝和浅拷贝







原文链接:segmentfault.com

上一篇:前端项目中复杂的流程控制
下一篇:jjencode|JS混淆手工解析编码过程以及自定义混淆变体改装

相关推荐

  • 🚩Vue源码——组件是如何注册的

    最近参加了很多场面试,几乎每场面试中都会问到Vue源码方面的问题。在此开一个系列的专栏,来总结一下这方面的经验,如果觉得对您有帮助的,不妨点个赞支持一下呗。 前言 在上一篇 🚩Vue源码——组件...

    4 天前
  • 🚩Vue源码——组件如何渲染成最终的DOM

    最近参加了很多场面试,几乎每场面试中都会问到Vue源码方面的问题。在此开一个系列的专栏,来总结一下这方面的经验,如果觉得对您有帮助的,不妨点个赞支持一下呗。 前言 Vue有两个核心思想,一个是数据...

    9 天前
  • 🔥基于vue3.0.1 beta搭建仿京东淘宝的电商商城项目!

    前言 就在前段时间,vue官方发布了3.0.0-beta.1 版本,趁着五一假期有时间,就把之前的一个电商商城的项目,用最新的Composition API拿来改造一下! 👉GitHub地址请访问�...

    5 个月前
  • 🍊仿Element自定义Vue组件库

    前言 🍊 市面上目前已有各种各样的UI组件库,他们的强大毋庸置疑。但是有时候我们有必要开发一套属于自己团队的定制化组件库。还有时候原有的组件不能满足我们的各种需求,就需要在原有的组件上进行改造...

    3 个月前
  • 🌓vue页面换肤实践

    前言 最近要做一个换肤的功能,不过只是对一个页面换肤,换一下背景图呀,背景、边框、字体颜色呀之类的,并非整个项目换肤,相对比较简单,所以以下介绍的换肤方法仅适用于页面换肤而非整个项目换肤。

    23 天前
  • (记录)vue、element表格首行跑到最后一行去了

    问题 项目中,我们一般会对 Element 进行二次封装,因为这样更好的全局管理组件,一处改动即可全局改动。比如你有十个表格,因为表格需要新增一个小功能(比如:右上角新增一个控制列显示的按钮),这时...

    6 天前
  • (源码分析)为什么 Vue 中 template 有且只能一个 root ?

    引言 今年,疫情并没有影响到各种面经的正常出现,可谓是络绎不绝(学不动...)。然后,在前段时间也看到一个这样的关于 Vue 的问题,为什么每个组件 template 中有且只能一个 root? 可能...

    6 个月前
  • (小白篇)vue-cli3.0创建项目+引入element-ui

    vue-cli在2018年8月份发布了3.0版本,经过重构之后,可以说是一个船心版本! 在项目都落地之后,就想升级一下cli版本,尝一尝3.0带来的舒适,也是为后面项目的开展做一个准备。

    1 年前
  • (小小黑科技)vue+echarts实现半圆图表

    如何用echarts实现半圆图表?在echarts官方实例倒腾一波,发现官方并没有提供半圆图表的写法,那怎么办呢?官方没提供,但需求还是要实现的。 半圆图表其实就是饼图的一半,那么简单的思路如下:设置...

    1 年前
  • (原创)vue-router的Import() 异步加载模块问题的解决方案

    关注不迷路,如果解决了问题,留下个赞。 1、问题现象 2、出现问题的代码点 3、替代方案: 把import() 替换成如下: Promise.resolve().then(()=&...

    5 个月前

官方社区

扫码加入 JavaScript 社区