教你搭建按需加载的Vue组件库(小结)


Posted in Javascript onJuly 29, 2019

按需加载的原理

按需加载,本质上是把一个组件库的不同组件 拆分成不同文件 ,按照需要引用对应的文件,而该文件暴露一个 install方法 ,供Vue.use使用。 比如:我只想引用element库里的一个Button组件

import Button from 'element-ui/lib/Button.js'
import Button from 'element-ui/lib/theme-chalk/Button.css'

Vue.use(Button);

上面的写法比较繁琐,而且需要知道每个组件的实际路径,使用起来并不方便,所以我们还需要借助一个转换插件。

先来看看 element 是怎么做的,官方的的「快速手上」:

教你搭建按需加载的Vue组件库(小结)

element使用一个了babel插件,作用就是代码转换:

import { Button } from 'components'

// 转换为

var button = require('components/lib/button')
require('components/lib/button/style.css')

到这我们可以知道,要搭建一个按需加载的组件库。 主要工作 需要两点:

  1. 组件独立打包 ,单个文件对应单个组件
  2. 引入 代码转换 的插件

组件代码的编写规范

我们在项目的跟目录建一个文件夹packages,下面放我们的组件:

教你搭建按需加载的Vue组件库(小结)

packages下每一个文件夹对应一个组件所需要的资源,在index.js定义组件的install方法。而packages/index.js存放了在全量加载时用的install方法

packages/Button/index.js:

import Button from './src/main';

Button.install = function(Vue) {
 Vue.component(Button.name, Button);
};

export default Button;

packages/Button/src/main.vue:

<template>
 <div>
 我是一个Button组件
 </div>
</template>

packages/index.js:

import Button from './Button';
import Loading from './Loading';
import LoadMore from './LoadMore';

const components = [
 Button,
 LoadMore,
 Loading
];

const install = function(Vue) {
 components.forEach(component => {
 Vue.component(component.name, component);
 });
}

if (typeof window !== 'undefined' && window.Vue) {
 install(window.Vue)
}

export default {
 install, // 全量引入
 Button,
 LoadMore,
 Loading
};

webpack配置

组件代码写好了,接下来需要配置一下webpack的打包逻辑。我们复用vue-cli生成的模板,在上面做一些必要更改:

多入口

每个组件独立生成一个对应的js和css,这就需要我们在入口处就把组件的引用定义好:

webpack.prod.conf.js:

const entrys = {
 Button: path.resolve(__dirname, '../packages/Button'),
 index: path.resolve(__dirname, '../packages')
};

const webpackConfig = merge(baseWebpackConfig, {
 entry: entrys,
 // ......
});

上述配置每增加一个组件都需要修改entrys,我们可以优化一下,使其 动态生成

webpack.prod.conf.js:

const entrys = require(./getComponents.js)([组件目录入口]);
const webpackConfig = merge(baseWebpackConfig, {
 entry: entrys,
 ......
});

getComponents.js:

const fs = require('fs');
const path = require('path');

/**
 * 判断刚路径是否含有index.js
 * @param {String} dir 
 */
function hasIndexJs(dir) {
 let dirs = [];
 try {
  dirs = fs.readdirSync(dir);
 } catch(e) {
  dirs = null;
 }
 return dirs && dirs.includes('index.js');
}

/**
 * 获取指定入口和入口下包含index.js的文件夹的路径
 * @param {String} entryDir 
 */
const getPath = function(entryDir) {
 let dirs = fs.readdirSync(entryDir);
 
 const result = {
  index: entryDir
 };
 dirs = dirs.filter(dir => {
  return hasIndexJs(path.resolve(entryDir, dir));
 }).forEach(dir => {
  result[dir] = path.resolve(entryDir, dir); 
 });
 return result;
}

module.exports = getPath;

修改webpack的输出

默认生成的js文件并不支持ES6引入,在这里我们设置成 umd

output: {
 path: config.build.assetsRoot,
 filename: utils.assetsPath('[name].js'),
 library: 'LoadOnDemand',
 libraryTarget: 'umd'
},

配置 babel-plugin-component -D

上面的组件库打包发布到npm上之后。我们在使用的时候npm install babel-plugin-component -D之后,修改一下.babelrc.js:

"plugins": [
 [
  "component",
  {
  "libraryName": "load-on-demand", // 组件库的名字
  "camel2Dash": false, // 是否把驼峰转换成xx-xx的写法
  "styleLibrary": {
   "base": false, // 是否每个组件都默认引用base.css
   "name": "theme" // css目录的名字
  }
  }
 ]
 ],

这里提一下属性 camel2Dash ,默认是开启的,开启状态下假如你的组件名是vueCompoent,引用的css文件会变成vue-component.css。

结语

上面demo的代码放在了个人github github.com/jmx16449196… 大家如果有更好的实现方法,或者我上面还有什么需要更正的错误,欢迎交流。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jQuery中文入门指南,翻译加实例,jQuery的起点教程
Feb 09 Javascript
js调试工具 Javascript Debug Toolkit 2.0.0版本发布
Dec 02 Javascript
搭建pomelo 开发环境
Jun 24 Javascript
JS实现带缓冲效果打开、关闭、移动一个层的方法
May 09 Javascript
js实现的在线调色板功能完整实例
Dec 21 Javascript
利用transition实现文字上下抖动的效果
Jan 21 Javascript
React组件生命周期详解
Jul 03 Javascript
微信小程序实现image组件图片自适应宽度比例显示的方法
Jan 16 Javascript
Vue.js的动态组件模板的实现
Nov 26 Javascript
layui form表单提交后实现自动刷新
Oct 25 Javascript
javascript如何实现create方法
Nov 04 Javascript
vue实现移动端拖动排序
Aug 21 Javascript
JavaScript 继承 封装 多态实现及原理详解
Jul 29 #Javascript
Vue2.0实现简单分页及跳转效果
Jul 29 #Javascript
JavaScript面向对象程序设计中对象的定义和继承详解
Jul 29 #Javascript
js实现多张图片每隔一秒切换一张图片
Jul 29 #Javascript
javascript面向对象程序设计实践常用知识点总结
Jul 29 #Javascript
javascript中this的用法实践分析
Jul 29 #Javascript
学习LayUI时自研的表单参数校验框架案例分析
Jul 29 #Javascript
You might like
php 判断数组是几维数组
2013/03/20 PHP
php用户登录之cookie信息安全分析
2016/05/13 PHP
PHP分页初探 一个最简单的PHP分页代码的简单实现
2016/06/21 PHP
PHP遍历目录文件的常用方法小结
2017/02/03 PHP
php实现算术验证码功能
2018/12/05 PHP
laravel 修改.htaccess文件 重定向public的解决方法
2019/10/12 PHP
JS 进度条效果实现代码整理
2011/05/21 Javascript
Ext JS 4官方文档之三 -- 类体系概述与实践
2012/12/16 Javascript
jQuery之ajax技术的详细介绍
2013/06/19 Javascript
nodejs开发环境配置与使用
2014/11/17 NodeJs
Node.js抓取中文网页乱码问题和解决方法
2015/02/10 Javascript
flash+jQuery实现可关闭及重复播放的压顶广告
2015/04/15 Javascript
JavaScript实现简单图片翻转的方法
2015/04/17 Javascript
javascript省市区三级联动下拉框菜单实例演示
2015/11/29 Javascript
JavaScript知识点总结(五)之Javascript中两个等于号(==)和三个等于号(===)的区别
2016/05/31 Javascript
深入理解js generator数据类型
2016/08/16 Javascript
AngularJS过滤器详解及示例代码
2016/08/16 Javascript
Angular2入门--架构总览
2017/03/29 Javascript
JavaScript解析机制与闭包原理实例详解
2019/03/08 Javascript
JS面向对象编程基础篇(二) 封装操作实例详解
2020/03/03 Javascript
[03:57]DOTA2英雄梦之声_第03期_幻影刺客
2014/06/21 DOTA
浅谈Python中列表生成式和生成器的区别
2015/08/03 Python
TensorFlow平台下Python实现神经网络
2018/03/10 Python
对Python 获取类的成员变量及临时变量的方法详解
2019/01/22 Python
Python秒算24点实现及原理详解
2019/07/29 Python
Python3 requests文件下载 期间显示文件信息和下载进度代码实例
2019/08/16 Python
Python创建空列表的字典2种方法详解
2020/02/13 Python
贝尔帐篷精品店:Bell Tent Boutique
2019/06/12 全球购物
综合素质的自我鉴定
2013/10/07 职场文书
社区学雷锋活动策划方案
2014/01/30 职场文书
十八届三中全会个人学习材料
2014/02/13 职场文书
高中毕业生的个人自我评价
2014/02/21 职场文书
优秀纪检干部材料
2014/08/27 职场文书
写景作文评语集锦
2014/12/25 职场文书
2016年会开场白台词
2015/06/01 职场文书
企业团队精神心得体会
2016/01/19 职场文书