一、编写组件
1. 初始化项目并运行
vue create vue-digital-count
npm run serve
2. 组件封装
- 新建package文件夹
因为我们可能会封装多个组件,所以在src下面新建一个package
文件夹用来存放所有需要上传的组件。
当然,如果只有一个组件,直接放到src
下面也无可厚非。
- 编写组件代码
digitalCount
可通过正常组件使用流程引入进行开发、调试
<template>
<div class="module-count-box">
<div v-for="(site, index) in list" :key="index">
<div v-if="site.num !== ','" class="site-item">
<!-- :style 动态移动距离 -->
<div class="num-list-box" :style="{ top:'-'+site.top+'px' }">
<p v-for="num in numList" :key="num + '-' + Math.random()" class="num-item">{{ num }}</p>
</div>
</div>
<div v-else class="comma-item">,</div>
</div>
</div>
</template>
<script>
export default {
// 必须要有name属性哦,便于后期组件引入并作为组件名
name: 'VueDigitalCount',
props: {
number: { // 显示的数字
type: [Number, String],
default: 0
},
showLength: { // 最长显示多少位数字
type: Number,
default: 9
},
autoFillLength: { // 是否自动用0补齐显示的长度
type: Boolean,
default: true
}
},
data() {
return {
list: [],
numList: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
}
},
watch: {
number: {
handler(newValue, oldValue) {
this.initNumber()
},
}
},
mounted() {
this.initNumber(true)
},
methods: {
// 在指定位置添加逗号; 参数是字符串
addCommaToStr(str) {
let tempArr = str.split('').reverse(); // 实际显示多少位
for (let i = tempArr.length - 1; i >= 0; i--) {
if ((i + 1) % 3 === 0) {
tempArr.splice(i + 1, 0, ',');
}
}
// 如果最后一个元素为,则删除
if (tempArr.at(-1) === ',') {
tempArr.pop();
}
// 反过来展示,变成从后面往前,每隔3位加逗号
return tempArr.reverse();
},
// 给数组计算要偏移的高度
calcMoveHeight(dealArr, isReset) {
let result = dealArr.map(value => {
return { num: value }
});
if (isReset) { // 只有第一次需要重置数据
result = result.map(item => {
return {
...item,
top: 0
}
})
}
let itemHeight = 80; // 每一个元素的高度
result.forEach((value, index) => {
setTimeout(() => {
// value.top = parseFloat((value.num * itemHeight)) || 0;
// 使用$set保证数据更新时能触发页面更新
this.$set(value, 'top', parseFloat((value.num * itemHeight)) || 0)
}, (index === null ? 0 : index) * 150); // 每个元素间隔150ms去计算偏移的距离
});
return result;
},
initNumber(isReset = false) {
let fillContent = ''; // 前面填充的字符串(全是0)
const numStr = this.number.toString(); // 将props转成字符串
let showNumber = numStr; // 最终展示的字符串,默认就是传过来的数据
if (this.autoFillLength) { // 需要自动填充
if (numStr.length < this.showLength) { // 小于指定显示的位数
fillContent = new Array(this.showLength - numStr.length).fill(0).join(''); // 生成指定位数的0的数组并转化为字符串
}
showNumber = fillContent + showNumber; // 在前面填充0,达到指定位数
}
// 通过方法,往字符串里添加逗号
const resultArr = this.addCommaToStr(showNumber);
// 计算每个数字需要滚动的距离
this.list = this.calcMoveHeight(resultArr, isReset);
},
}
}
</script>
<style scoped>
.module-count-box {
display: flex;
}
.module-count-box .site-item {
width: 66px;
height: 80px;
overflow: hidden;
text-align: center;
display: flex;
margin: 0 4px;
background: url("@/assets/count_num_bg.png") no-repeat;
background-size: 100% 100%;
position: relative;
}
.module-count-box .site-item .num-list-box {
position: absolute;
top: 0;
left: 0;
transition: all 1.5s ease-in-out 0s;
/* top: -80px; */
}
.module-count-box .site-item .num-list-box > .num-item {
width: 66px;
height: 80px;
font-size: 56px;
font-weight: 600;
display: flex;
justify-content: center;
align-items: center;
margin: 0px;
color: #fff
}
.module-count-box .comma-item {
font-size: 100px;
color: #BBD7FF;
margin-top: -26px;
}
</style>
3. 使用vue插件模式
该步骤时组件封装的重点,即利用vue的公开方法: install
install
方法会在你使用 Vue.use(plugin)
时被调用,这样使得我们的插件注册到了全局,在子组件的任何地方都可以使用。
在package目录下新建index.js
文件,代码如下:
// 1. 引入组件
import VueDigitalCount from './digitalCount';
// 2. 用数组保存组件,便于遍历
const components = { VueDigitalCount };
// 3. 定义 install 方法,接收 Vue 作为参数。如果使用 use 注册插件,则所有的组件都将被注册
const install = function (Vue) {
// 判断是否安装
if (install.installed) return;
install.installed = true; //标识已经安装
// 遍历并注册全局组件
Object.keys(components).forEach(key => {
Vue.component(key, components[key]);
});
}
// 对于那些没有在应用中使用模块化系统的用户(如在html中直接使用vue),他们往往将通过 <script> 标签引用你的插件,并期待插件无需调用 Vue.use() 便会自动安装
// 添加如下几行代码来实现自动安装:
if (typeof window !== 'undefined' && window.Vue) {
install(window.Vue)
};
// 4. 导出组件
// 将每个组件导出,便于不全局注册时,单个使用component注册为页面级组件
export {
VueDigitalCount
};
// 导出install方法,用于vue.use 注册全局插件
export default install;
二、使用 vue-cli 打包库
首页,来看看官网的描述:构建模板 - 应用
注意: css: { extract: false } 这个配置;
因为vue-cli
默认打包后是将css抽离出来成为一个单独的文件;所以在使用的时候就需要单独将css引入,相对麻烦。类似element-ui
有这么一步:
import 'element-ui/lib/theme-chalk/index.css';
1. 修改 package.json
文件,在scripts
配置打包命令
"package": "vue-cli-service build --target lib ./src/package/index.js --name vue-digital-count --dest dist"
打包命令解释:
- target lib 关键字, 指定打包的目录
- name 打包后的文件名字
- dest 打包后的文件夹的名称
打包后的文件如下:
因为我在 vue.config.js
配置了 css: { extract: false }
;所以没有单独的css文件
修改package.json
其他配置,适用于npm
发包
- 重要:新增配置入口文件 mian ,使用umd.min.js(适用于所有平台)
- 去除
"private": true,
private字段可以防止我们意外地将私有库发布到npm服务器。只需要将该字段设置为true - 新增
author
、license
、keywords
、description
、repository
、homepage
等字段,没有的可以不用配置
配置详情:
{
// 发布的包名,默认是上级文件夹名。不得与现在npm中的包名重复。包名不能有大写字母/空格/下滑线!
"name": "#####",
// 版本号,每次要更新
"version": "1.0.0",
// 包的描述
"description": "仅供测试,别下载",
// 文件入口,默认是 index.js,可修改
"main": "index.js",
"scripts": {
// 测试命令,可以不填直接回车
"test": "echo \"Error: no test specified\" && exit 1"
},
// 作者名称
"author": "###",
// 包遵循的开源协议,默认是ISC
"license": "ISC",
// 因为组件包是公用的,所以 private 为 false
"private": false,
// 当前包需要依赖的第三方组件,如何安装使用依赖包,可以看看文章顶部的NPM命令介绍文章
"dependencies": {},
// "devDependencies": {}
// 指定代码所在的仓库地址
"repository": {
"type": "git",
"url": "https://github.com/dengzemiao/DZMFullPage.git"
},
// bug在哪里提
"bugs": {
"url": "https://github.com/dengzemiao/DZMFullPage/issues"
},
// 项目官网的地址
"homepage": "https://github.com/dengzemiao/DZMFullPage",
// 指定打包后,包中存在的文件夹
"files": [
"dist",
"src"
],
// 指定了项目的目标浏览器的范围
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
],
// 项目关键词,供搜索
"keywords": [
"测试"
]
}
三、上传至 npm
ps: 想要发布到npm仓库,就必须要有一个账号,先去npm官网注册一个账号,注意记住用户名、密码和邮箱,发布的时候可能会用到。
1. 设置npm源
如果本地npm
采用的是淘宝镜像源或者其它,需要改成 npm
官方源
npm config set registry=https://registry.npmjs.org
npm 查看使用的包源是哪一个:`npm config get registry`
2. 添加npm用户
进入 vue-digital-count
目录,执行命令:
npm adduser
需要输入账号、密码、邮箱和邮箱验证码;第一次才需要
3. 发布
npm publish
发布包前最后提前在npm官网
查询报名是否重名,避免发布失败。发布成功后即可到npm官网
上查看自己发布的npm
包。
4. 更新包
修改package.json
文件里面的version
字段,然后重新 npm publish
即可
文章仅为本人学习过程的一个记录,仅供参考,如有问题,欢迎指出!