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

news2024/12/26 12:48:18

前言

环境准备

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中对用模块中调试

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

每日一题---OJ题: 旋转数组

片头 嗨! 小伙伴们,咱们又见面啦,今天我们一起来学习一道OJ题---旋转数组 emmm,看上去好像没有那么难,我们一起来分析分析 比如: 数组里面有7个元素,分别为 1, 2, 3, 4, 5, 6, 7 , 现在我们将数组中的元素向右轮转3个位置 第一次轮转:将最后一个元素"7"放在第一个…

【spring】@Resource注解学习

Resource介绍 在Spring框架中&#xff0c;Resource 注解是一个JSR-250标准注解&#xff0c;用于自动装配&#xff08;autowiring&#xff09;Spring容器中的bean。Resource 注解可以用于字段、方法和方法参数上&#xff0c;以声明依赖注入。 Resource源码 Target({TYPE, FIE…

通付盾APP尽职调查报告:守护移动应用安全新篇章

在数字化浪潮席卷全球的今天&#xff0c;移动应用程序已经成为我们生活中不可或缺的一部分。无论是购物、社交、娱乐还是工作&#xff0c;我们几乎每天都在与各种各样的APP打交道。然而&#xff0c;随着APP的广泛应用&#xff0c;其安全问题也日益凸显&#xff0c;成为开发者和…

初学python记录:力扣928. 尽量减少恶意软件的传播 II

题目&#xff1a; 给定一个由 n 个节点组成的网络&#xff0c;用 n x n 个邻接矩阵 graph 表示。在节点网络中&#xff0c;只有当 graph[i][j] 1 时&#xff0c;节点 i 能够直接连接到另一个节点 j。 一些节点 initial 最初被恶意软件感染。只要两个节点直接连接&#xff0c…

Python LEGB规则

Python在查找“名称”时&#xff0c;是按照LEGB规则查找的&#xff1a; Local&#xff1a; 指的就是函数或者类的方法内部 Enclosed&#xff1a; 指的是嵌套函数&#xff08;一个函数包裹另一个函数&#xff0c;闭包&#xff09; Global&#xff1a; 指的是模块中的全局变量 Bu…

【服务器部署篇】Linux下Nginx的安装和配置

作者介绍&#xff1a;本人笔名姑苏老陈&#xff0c;从事JAVA开发工作十多年了&#xff0c;带过刚毕业的实习生&#xff0c;也带过技术团队。最近有个朋友的表弟&#xff0c;马上要大学毕业了&#xff0c;想从事JAVA开发工作&#xff0c;但不知道从何处入手。于是&#xff0c;产…

MySQL事务的性情很“原子“,要么执行要么不执行

各位小伙伴有没遇到这个奇葩情况&#xff1a;业务逻辑对两个表加了事务操作&#xff0c;A表的存储引擎是InnoDB&#xff0c;B表的存储引擎却是MyISAM。事务要回滚时&#xff0c;麻烦就来了hhh&#xff0c;B表它回滚不了&#xff0c;那小伙伴打算要怎么处理~ &#x1f331;以【…

C#创建随机更换背景图片的窗体的方法:创建特殊窗体

目录 一、涉及到的知识点 1.图片资源管理器设计Resources.Designer.cs 2.把图片集按Random.Next方法随机化 3.BackgroundImage属性 二、实例设计 1. Resources.Designer.cs 2.Form1.Designer.cs 3.Form1.cs 4.生成效果 很多时候&#xff0c;我们需要每次打开窗体时能够…

如何创建二级域名并解析到服务器

&#x1f468;&#x1f3fb;‍&#x1f4bb; 热爱摄影的程序员 &#x1f468;&#x1f3fb;‍&#x1f3a8; 喜欢编码的设计师 &#x1f9d5;&#x1f3fb; 擅长设计的剪辑师 &#x1f9d1;&#x1f3fb;‍&#x1f3eb; 一位高冷无情的全栈工程师 欢迎分享 / 收藏 / 赞 / 在看…

【图像分割】光流生成标签(matlab)

文章目录 1. 框架2. opticalFlow_label3. 光流1. 框架 2. opticalFlow_label close all; clear; clc; % 使用光流进行标签的生成 %% 视频帧的读取 npy_data = readNPY(train.npy);%% 提取标签的坐标 first_label = squeeze(npy_data(2,1,:,:)); h = fspecial("gaussian&q…

TCP/IP协议—MQTT

TCP/IP协议—MQTT MQTT协议MQTT协议特点MQTT通信流程MQTT协议概念 MQTT报文固定报头可变报头有效载荷 MQTT协议 消息队列遥测传输&#xff08;Message Queuing Telemetry Transport&#xff0c;MQTT&#xff09;是一个基于客户端-服务器的消息发布/订阅传输协议。它的设计思想…

HalconLen5-定位特征步步逼近

read_image(Image, C:/Users/86173/Desktop/test/2.png) get_image_size(Image, Width, Height)dev_close_window() dev_open_window(0, 0, Width, Height, black, WindowHandle)dev_display(Image)threshold(Image, Region, 128, 255) //阈值处理connection(Region, Connected…

人事管理软件全解析:高效团队管理的必备利器

本文为您详细介绍六款备受推崇的人力资源管理系统有&#xff1a;Zoho People、SAP SuccessFactors、Workday、Zenefits、BambooHR、TalentSoft。 一、Zoho People Zoho People 是一款全球领先的人事管理软件&#xff0c;以其全面的功能覆盖、出色的用户体验及高度的定制化能力…

02_Fixture定位,Caliper卡尺工具,几何学工具

Fixture定位工具 需求: 测量工件的尺寸 使用Caliper(卡尺)工具 这个时候需要借助Fixture工具 VisionPro中的图像空间 “” 图像的当前空间&#xff0c;即CogImage中的“SelectedSpaceName”表示的名字空间 “#” 像素空间&#xff0c;即坐标原点为图片左上角的坐标空间&am…

【模板自取】项目管理必会的思维分析工具之5W2H分析法

5W2H法是二战中美国陆军兵器修理部首创。简单、方便&#xff0c;易于理解、使用&#xff0c;广泛用于项目管理和思维分析等活动终&#xff0c;对于决策和执行性的活动措施也非常有帮助&#xff0c;也有助于弥补考虑问题的疏漏。产品管理、项目管理中&#xff0c;5W2H法也广泛应…

原子的内部结构

原子非常神奇&#xff0c;花时间思考它是非常有价值的。尽管传统的太阳系示意图存在致命的缺点&#xff0c;但我们还是可以局部应用于原子。 首先&#xff0c;原子与太阳系具有相似性一原子的中心质量大&#xff0c;外部质量小。我们用最简单的氢原子做分析&#xff0c;氢原子…

工作流JBPM系统数据库表介绍

文章目录 ☃️4.1 建表☃️4.2 数据库逻辑关系4.2.1 资源库与运行时的表4.2.2 历史数据表 ☃️4.3 表结构☃️4.4 流程操作与数表交互说明 ☃️4.1 建表 该系统自带18张表&#xff0c;用于支撑该系统的逻辑与流程业务&#xff1b; 建表语句如下&#xff1a; create database…

ROS实现无人驾驶控制算法(一)——pure pursuit

引言 对于导航系统来说&#xff0c;在规划好全局路径后&#xff0c;使机器人根据路径行驶这部分被称为轨迹跟踪。轨迹跟踪主要分为两类&#xff1a;基于几何追踪的方法和基于模型预测的方法。而pure pursuit算法就是最基本的基于几何的控制算法&#xff0c;因其鲁棒性高&#…

bonding原理分析和问题排查

bonding原理 发送端&#xff1a; 使用网卡bond3模式&#xff08;广播模式BOND_MODE_BROADCAST&#xff09;将报文从两个网卡同时发出&#xff0c;无需修改报文。 接收端&#xff1a; 根据发送节点时间的链路通断状态&#xff0c;接收端设置一条线路为活动线&#xff0c;另一条…

yolov7模型输出层预测方法解读

本文从代码的角度分析模型训练阶段输出层的预测包括以下几个方面&#xff1a; 标注数据&#xff08;下文统称targets&#xff09;的正样本分配策略&#xff0c;代码实现位于find_3_positive。候选框的生成&#xff0c;会介绍输出层的预测值、GT、grid、 anchor之间的联系损失函…