存个档
在时不时遇到”似曾相识“的 UI 模块时,我们下意识的反应一定是”不然把它抽成一个组件吧“。Element-UI 就是这样想法的集大成者。
感谢 Vue 的单文件组件,让开发者能把 HTML+CSS+JS 编写在同一个地方,方便开发、管理和引用。本文将要分享的是笔者使用 Vue CLI 3 打包-发布运营活动中常见的走马灯抽奖组件 — vmgr:
实现过程概括来说,用 CSS Grid+CSS Variables 做布局;用 TweenJS 做动画。
在执行打包之前,我们先明确组件是在哪里注册哪里调用的。
组件的入口文件为 index.js
,在这里,完成组件的全局注册:
// index.js
import vmgr from "./components/vmgr.vue";
vmgr.install = Vue => Vue.component("vmgr", vmgr);
export default vmgr;
然后在应用入口文件 main.js
中完成调用:
// main.js
import Vue from "vue";
import App from "./App.vue";
// component
import vmgr from "./index";
Vue.use(vmgr);
Vue.config.productionTip = false;
new Vue({
render: h => h(App)
}).$mount("#app");
打包组件的方式有两种,一种是 lib
,另一种是 Web Components
。因为考虑到后续的使用场景基本是在 Vue Cli 框架下,所以我采用了打包成库(也就是第一种)方式。在 package.json
中增加一行命令:
...
"scripts": {
...
"pkg": "vue-cli-service build --target lib --name vmgr --dest pkg ./src/index.js"
...
},
...
由于在 vue.config.js
中将 css extract 设置为 false,所以样式被强制内联:
// vue.config.js
...
css: {:
...
// 是否使用 css 分离插件 ExtractTextPlugin,采用独立样式文件载入,不采用 <style> 方式内联至 html 文件中
extract: false,
...
},
...
最终打包生成一下三份文件:
可以从官方文档上看到对于这三个文件的解释:
构建一个库会输出:
dist/myLib.common.js
:一个给打包器用的 CommonJS 包 (不幸的是,webpack 目前还并没有支持 ES modules 输出格式的包)
dist/myLib.umd.js
:一个直接给浏览器或 AMD loader 使用的 UMD 包
dist/myLib.umd.min.js
:压缩后的 UMD 构建版本
Web Components
的构建方式请参考官方文档。
第一次打包以后,我发现组件的体积比预想中大了不少(此处应有图,但当时忘截了)。
因为使用了 TweenJS(不可避免的也要使用到 RAF 的兼容库),把它们一起打包进去了。如果使用的时候,页面上只有走马灯用上了 Tween 也还好说,但要是同一页面上其他地方也需要,就会导致重复引入代码冗余。于是这里我选择全局引入。
在 vue.config.js 中配置 configureWebpack
:
const webpack = require("webpack");
module.exports = {
...
configureWebpack: {
plugins: [
new webpack.ProvidePlugin({
TWEEN: "@tweenjs/tween.js",
requestAnimationFrame: "raf"
})
]
}
...
}
打包方案也要因地制宜。上述场景会发生是因为全局引入的 TweenJS 和 RAF 方便在页面上随处可用。也许与你的组件关联的第三方库只会服务于这个组件,其他地方不大可能调用到,那自然和组件一起封装会更合理。但这样会有一个问题,需要通知使用者该组件依赖 Tween 和 raf,使用者要提前引入这两个库。
非常简单,顺带提一下,更新 ReadMe
,在 package.json
中填上必要的发布信息:
// package.json
{
"name": "vmgr",
"version": "0.1.821",
"private": false,
"main": "dist/vmgr.umd.min.js",
"description": "merry-go-round for activities",
...
}
vue create
命令创建一个空项目;tnpm install --save @tencent/vmgr
, 记得在 vue.config.js 中引入 TWEEN 和 raf 哦(见“优化打包体积”);// App.vue --- 语法高亮没有支持 .vue,将就看
<template>
<div id="app">
<vmgr
:count="count"
:options="options"
ref="vmgr1"
:animOpt="animOpt"
></vmgr>
</div>
</template>
<script>
export default = {
name: "app",
data() {
return {
count: 10,
animOpt: {
startIndex: 6,
stopIndex: 1 // 以排好序的index来算 1~12
},
options: []
};
},
....
}
</script>
mockjs
和 axios
模拟,安装成功后:// mock.js
const Mock = require("mockjs");
const Random = Mock.Random;
const getParam = function(url) {
let paramArr = url.slice(url.indexOf("?") + 1).split("&");
let paramObj = {};
paramArr.forEach(param => {
let tmp = param.split("=");
if (tmp[1]) paramObj[tmp[0]] = tmp[1];
});
return paramObj;
};
Mock.mock(/api\/data/, "get", (req, res) => {
const paramObj = getParam(req.url);
let list = [];
for (let i = 0; i < paramObj.len; i++) {
let listObj = {
name: Random.csentence(2, 5),
backgroundImage: Random.dataImage("80x80", Random.csentence(2, 5))
};
list.push(listObj);
}
return {
data: list
};
});
// App.vue
...
<script>
require("./mock.js");
import axios from "axios";
export default = {
....
mounted() {
axios({
method: "get",
url: "/api/data?len=12",
responseType: "json"
})
.then(res => {
this.options = res.data.data;
setTimeout(() => {
this.$refs.vmgr1.start();
}, 0);
})
.catch(res => {
console.log("error happens!");
console.log(res);
});
}
}
</script>
成功调用的效果大致如下:
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。