如何封装Vue组件并上传到npm

前言

环境准备

1.注册npm账号:npm | Home (npmjs.com)

2.保证当前环境安装了vue、webpack、node,以下工作将在该环境下进行(没有的小伙伴自行百度安装哈~)

3.一下用到的环境版本

  • webpack:v5.1.4
  • node:v12.10.0
  • vue:v2.6.14

4.创建一个基于webpack的vue项目,这个项目将会是我们的组件项目了。

目录结构构建

在我们日常开发的项目中,通常的目录结构可能会像下图,我们一般会在根目录下的src/views中进行我们所有页面的开发,App.vue作为主页面引入。

但是呢,我们现在是想要进行组件开发,那么在项目的目录结构上可根据个人习惯进行一定的调整和更改如下:

 这里我说明一下主要的目录

  • components:存放你所需要开发的所有组件的目录
  • components/lib:存放组件源码
  • components/css:存放可能需要用到的css样式(自定义)
  • components/lib/xxx/index.js:将组件注册魏全局组件
  • examples:最初项目的src,我们可以一边开发一边调试

注意:更改上述目录之后,配置文件也需要进行相应的改变,因为在webpack中,默认以sec/main.js作为入口文件,现我们已将scr->example,所以入口文件应该进行相应的修改

组件开发

这里以Loading组件为例,

  • components/lib/Loading/src/Loading.vue:组件源码
  • components/lib/Loading/src/index.js:单个注册全局组件
  • components/css/loading.scss:存放Loading组件的样式(这里使用的是scss方式,后面关于打包会提到)
  • components/lib/index.js:所有组件的全局注册

代码实例如下:

components/lib/Loading/src/Loading.vue

<template>
	<div class="beva-loading">
		<img class="loading-icon" :src="imgSrc" alt="">
	</div>
</template>
<script>
	export default {
  name: 'Loading',
  props: {
    imgSrc: {
      type: String,
      default: ''
    },
  },
  data() {
		return {}
	}
}
</script>

components/lib/Loading/src/index.js

import Loading from './src/Loading.vue'

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

components/css/loading.scss

	.beva-loading {
	  background-color: rgba(0, 0, 0, 0.7);
	  border-radius: 0.4rem;
	  color: #ffffff;
	  position: fixed;
	  z-index: 99;
	  width: 7.46rem;
	  height: auto;
	  padding: 0.8rem;
	  text-align: center;
	  top: 20vh;
	  box-sizing: border-box;
	  margin-left: -3.73rem;
	  left: 50%;
	}
	.loading-icon {
	  width: 4rem;
	  height: 4rem;
	  animation: rotatingright 1s linear infinite;
    }
	/*自定义动画类----顺时针旋转(使用这个动画的时候才设置动画执行时间)*/
	@keyframes rotatingright {
	  transform-origin: 50% 50%;
	  0% {
	    transform: rotate(0deg);
	  }
	  50% {
	    transform: rotate(180deg);
	  }
	  100% {
	    transform: rotate(360deg);
	  }
	}

	/*自定义动画类----逆时针旋转(使用这个动画的时候才设置动画执行时间)*/
	@-webkit-keyframes rotatingleft {
	  0% {
	    -webkit-transform: rotate(0deg);
	  }
	  50% {
	    -webkit-transform: rotate(-180deg);
	  }

	  100% {
	    -webkit-transform: rotate(-360deg);
	  }
	}

components/lib/index.js

// 将组件库中定义的所有组件引进来,然后再导出
import Demo from './demo';
import Card from './card';
import Loading from './Loading';

const components = {
  Demo,
  Card,
  Loading
}
const install = function (Vue) { 
  // 判断是否安装,安装过就不继续往下执行
  if (install.installed) return
  Object.keys(components).forEach(component => { 
    Vue.component(components[component].name, components[component])
  })
}
export default {
  install
}

新建webpack.components.js文件,其中主要是对组件打包的配置

1.对打包输出的文件进行处理

2.如果用到了scss、css,图片,则还需要对这些文件进行额外处理

主要配置如下(其中有相关的注释,有兴趣可以自行查看)

const { VueLoaderPlugin } = require('vue-loader');
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
const glob = require('glob')
const path = require('path')
const list = {}// 动态导入多个组件的入口文件
// 封装组件的一些配置,因为组件打包是单独打包的,所以需要单独配置
async function makeList (dirPath, list) {
  // 拿到所有的入口文件的路径
  const files = await glob.sync(`${dirPath}/**/index.js`)//[ 'components/lib/button/index.js', 'components/lib/icon/index.js']
  // 取出上一级目录的文件名
  files.forEach(file => {
    let name = file.split('/')[2]
    // 判断name是否有后缀名,有的话去除
    if (name.includes('.')) {
      name = name.split('.')[0]
    }
    list[name] = `./${file}`
  })
  // console.log(list)
}
makeList('components/lib', list)
module.exports = {
  entry: list,
  mode:'development',
  output: {
    filename: '[name].umd.js',// webpack打包的时候会将name替换成入口的name名字,例如card.umd.js
    path: path.resolve(__dirname, 'dist'),
    library:'mui',
    libraryTarget: 'umd',// 指定输出格式,umd是一种模块,兼容了CommonJS、AMD、CMD
  },
  plugins: [
    new VueLoaderPlugin(),
    new CleanWebpackPlugin()
  ],
  module: {
    // 配置rules,即什么样的文件,使用什么样的loader
    rules: [
      {
        test: /\.vue$/,
        use: [
          {
            loader: 'vue-loader',
          }
        ]
      },
      {
        test: /\.css$/,
        use: ['style-loader','css-loader']
      },// 这里只处理了css,而项目中组件中使用了scss文件,对于scss文件的处理这里使用的是gulp,下面会提到
      {
        test: /\.(png|jpg|gif|svg)$/i, // 匹配图片文件格式
        type: 'asset/resource', // 使用内置的asset模块处理资源文件
        generator: {
          filename: 'images/[name][ext]', // 输出的文件名格式
        },
      },
    ],
  },
}
  

ps:对于组件中使用的scss文件的处理,这里用到的是gulp,具体设置如下:

新建gulpfile.js,对css文件单独打包(下方用到的第三方依赖需要自定下载

const gulp = require('gulp');
// 需要把样式代码导入
const sass = require('gulp-sass')(require('sass'));
// 对css代码进行压缩
const minifyCSS = require('gulp-minify-css');
gulp.task('sass', async function () {
  return gulp.src('components/css/**/*.scss')
    .pipe(sass())// 将scss代码转换成css代码
    .pipe(minifyCSS())// 压缩css代码
    .pipe(gulp.dest('dist/css'))// 输出到打包目录
})

接下来就是新增打包命令:

在package.json文件中

最后的打包文件如下:

上传npm

修改package.json文件

在上传npm之前呢,我们有必要对这个组件库信息进行相应的配置,因为npm上发布的包是根据package.json的文件进行匹配的,所以,进行如下信息修改,一般指定如下信息

  • 删除私有属性private
  • description:描述
  • main:入口文件
  • keywords:关键字(方便用户搜索)
  • author:作者信息
  • files:望发布的文件目录(不需要将所有文件都上传到npm中)

距离如下:

添加md文件

打包&&发布

由于这里封装组件的方式是打包发布的方式,所以切记在发布之前进行打包,生成dist文件!

维护版本

手动修改package.json中的version或者执行npm version patch生成迭代一个版本

执行打包命令

npm run build

登陆npm

注意这一需要登陆官方仓库,如果之前连接的是淘宝镜像需要线切换回来。下面是查看仓库源和切换仓库的命令。

npm config get registry  // 查看仓库源
npm config set registry https://registry.npm.taobao.org
npm config set registry http://registry.npmjs.org 

 登陆npm,输入账号、密码、邮箱

npm login

 发布

npm publish

测试组件

安装

npm i vue-library-ui

引入&&使用 

 页面

 扩展

我在这个的基础上封装了另外一个组件vue2-edit-cron,主要是可以快速构建cron表达式,有兴趣也可以看看~:vue2-edit-cron - npm (npmjs.com)

总结

        该文组件封装的方式其实是打包发布的方式,这种方式是将装好的组件最终打包成一个或者多个js文件发布。这种方式使得开发和调试时更接近于一个前端项目。但是一旦引入图片等静态资源需要同个BASE64的方式打包到js,而对于字体一类较大的静态资源则根本无法引用

适用范围:没有或极少的依赖第三方插件、图片的组件的封装或JS方法的封装

后面经过了解知道,其实还有另外一种方式即,非打包方式,具体的对比如下:

打包发布非打包发布
webpack需要配置无需配置
发布发布前需要打包发布前无需打包
引用静态文件较小的图片可以通过BASE64方式打包仅js文件随意使用
引用第三方依赖可以引用,但如果第三方依赖包含较多的静态文件时可能会出现引用不到的情况随意引用
被应用的文件一个打包好的js组件的入口文件
调试方法在组件项目中即可调试需要在引用组件的项目中的node_module中对用模块中调试

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/563569.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

编程实践:使用C语言计算k阶常系数线性递归序列

开篇 本文的目的是使用C语言模拟k阶常系数线性递归的运算过程&#xff0c;题目来源为《编程珠玑》第3章【数据决定程序结构】的课后习题2。具体的题目概要和代码实现&#xff0c;请看下文。 问题概要 因为这种问题涉及到的数学公式不太方便打出来&#xff0c;我直接用我笔记的原…

c++ 二分查找

二分查找&#xff08;Binary Search&#xff09;是一种在有序数组中查找特定元素的高效算法。它通过不断将搜索范围减半来查找目标元素。其时间复杂度为 O(log n)&#xff0c;这是因为每一步都将搜索范围减半&#xff0c;因此算法的性能非常高。 二分查找的基本思想是&#xf…

openwrt局域网配置多个IP

在局域网配置过程中&#xff0c;若是DHCP服务器关闭&#xff0c;又忘记了配置的ip&#xff0c;将很难访问到路由器重新进行配置。这种情况可以在路由器出厂时做一个备用ip去避免。 1.配置 以下是备用ip的配置方法&#xff0c;以SKYLAB的SKW99 WIFI模组为例进行说明&#xff1…

Java 网络编程之TCP(一):基于BIO

环境&#xff1a; jdk 17 IntelliJ IDEA 2023.1.1 (Ultimate Edition) Windows 10 专业版 22H2 TCP&#xff1a;面向连接的&#xff0c;可靠的数据传送协议 Java中的TCP网络编程&#xff0c;其实就是基于常用的BIO和NIO来实现的&#xff0c;本文先讨论BIO&#xff1b; BIO…

Xilinx 7系列FPGA 高性能(HP)接口与2.5V/3.3V 外设IO接口设计考虑

引言&#xff1a;Xilinx 7系列FPGA IO Bank分为HP Bank和HR Bank&#xff0c;HP IO接口电压范围为1.2V~1.8V&#xff0c;可以实现高性能&#xff0c;HR IO接口电压范围为1.2V~3.3V。当HR Bank与2.5V或者3.3V外设互联时&#xff0c;需要考虑接口电平的兼容性。根据性能需求、功能…

在Linux操作系统中介绍文件属性

查看文件属性&#xff0c;&#xff0c;可以使用命令lsattr 文件路径 使用命令lsattr 文件路径 查看文件属性 如上图所示&#xff0c;没有给文件 /etc/fstab 文件设置任何属性。 设置文件属性&#xff0c;&#xff0c;可以使用命令chattr 需要为文件加上的属性&#xff0…

葡萄书--深度学习基础

卷积神经网络 卷积神经网络具有的特性&#xff1a; 平移不变性&#xff08;translation invariance&#xff09;&#xff1a;不管检测对象出现在图像中的哪个位置&#xff0c;神经网络的前面几层应该对相同的图像区域具有相似的反应&#xff0c;即为“平移不变性”。图像的平移…

DHT11实验

文章目录 11.11.2 234 DS18B20 只能检测温度 右边这几个 都能 1 1.1 数字信号输出 指 0/1使用单总线通信 1个IO口就能获取温湿度 T/H要有 模数转化&#xff08;内部还有个8位单片机&#xff09;电容感湿元件 白色的 还有个ic NTC测温 可能在ic内部 使用单片机内部测温 精确度不…

服务器渲染技术(JSPELJSTL)

目录 前言 一.JSP 1.基本介绍 3.page指令(常用) 4.JSP三种常用脚本 4.1 声明脚本 <%! code %> 4.2 表达式脚本 <% code %> 4.3 代码脚本 <% code %> 4.4 注释 <%-- 注释 --%> 5. JSP 内置对象 5.1 基本介绍 5.2 九个内置对象 6.JSP域对象 二…

Python 物联网入门指南(六)

原文&#xff1a;zh.annas-archive.org/md5/4fe4273add75ed738e70f3d05e428b06 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 第十七章&#xff1a;机器人学 101 一提到机器人&#xff0c;我们就会被科幻小说所包围。我们可能会想起动画片《杰森一家》或者电影《终结…

MySQL如何避免全表扫描?

MySQL如何避免全表扫描&#xff1f; 这篇文章解释了何时以及为什么MySQL会执行全表扫描来解析查询&#xff0c;以及如何避免在大型表上进行不必要的全表扫描。 何时会发生全表扫描 MySQL使用全表扫描&#xff08;在EXPLAIN输出中的type列显示为ALL&#xff09;来解析查询的几…

汇智知了堂晨会聚焦:NAS应用如何赋能网络安全实战

在近期汇智知了堂网络安全75班的晨会上&#xff0c;一场关于NAS应用的深入分享完美展开。学员们以饱满的热情投入到这场安全讨论中&#xff0c;共同探索网络安全的新天地。 此次分享会聚焦于NAS的应用&#xff0c;旨在帮助学员们更好地了解NAS的定义与功能&#xff0c;掌握其在…

Reddit数据API 获取reddit的帖子、评论、按关键字搜索

近期调研发现 iDataRiver平台 https://www.idatariver.com/zh-cn/ 提供开箱即用的Reddit数据采集API&#xff0c;是目前用下来最方便简单的API&#xff0c;可以抓取 reddit 公开数据&#xff0c;例如 subreddit 中的帖子、按关键字搜索以及文章评论等&#xff0c;供用户按需调用…

智慧养老平台|基于SprinBoot+vue的智慧养老平台系统(源码+数据库+文档)

智慧养老平台目录 基于SprinBootvue的外贸平台系统 一、前言 二、系统设计 三、系统功能设计 前台 后台 管理员功能 老人功能 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌️大厂码农…

【计算机组成原理】定点数的乘法运算

定点数的乘法运算 定点乘法运算人工算法和机器的矛盾不带符号的阵列乘法器带符号的阵列乘法器求补电路求补电路的思想 ✨️间接补码乘法运算的步骤 定点乘法运算 在定点计算机中&#xff0c;两个原码表示的数相乘的运算规则是&#xff1a;乘积的符号位 两数的符号位异或&…

python文件 成绩分析

‘’文件score.txt中存储了学生的考试信息,内容如下 小明,98 小刚,90 小红,91 小王,98 小刘,80 请写代码,读取文件数据,并进行如下分析 最高分和最低分分别是多少&#xff1f;得最高分的学生有几个&#xff1f; 得最低分的学生有几个平均分是多少&#xff1f; ‘’’ def rea…

使用Python比较两张人脸图像并获得准确度

使用 Python、OpenCV 和人脸识别模块比较两张图像并获得这些图像之间的准确度水平。 一、原理 使用Face Recognition python 模块来获取两张图像的128 个面部编码&#xff0c;并比较这些编码。比较结果返回 True 或 False。如果结果为True &#xff0c;那么两个图像将是相同的…

第一届 _帕鲁杯_ - CTF挑战赛

Mis 签到 题目附件&#xff1a; 27880 30693 25915 21892 38450 23454 39564 23460 21457 36865 112 108 98 99 116 102 33719 21462 21069 27573 102 108 97 103 20851 27880 79 110 101 45 70 111 120 23433 20840 22242 38431 22238 22797 112 108 98 99 116 102 33719 2…

前端开发攻略---合并表格单元格,表格内嵌套表格实现手风琴效果。

1、演示 2、思路 1、用传统的 <table></table> 表格标签来实现比较麻烦。因此通过模拟 表格标签 的写法用<div></div>来实现 2、表头和表格列数是相同的&#xff0c;因此可以确定代码结构 <div class"table"><div class"head…

【开发篇】本章包括消息订阅、客服配置与使用实战(小程序之云函数开发入门到使用发布上线实操)

客服回复效果图展示 消息订阅效果图展示 一、客服配置 客服消息使用指南传送门 <button open-type="contact" class="fab" ><view class="item"