教你搭建按需加载的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 相关文章推荐
用javascript控制iframe滚动的代码
Apr 10 Javascript
浅析jQuery(function(){})与(function(){})(jQuery)之间的区别
Jan 09 Javascript
最流行的Node.js精简型和全栈型开发框架介绍
Feb 26 Javascript
JS扩展方法实例分析
Apr 15 Javascript
jQuery插件HighCharts绘制2D柱状图、折线图和饼图的组合图效果示例【附demo源码下载】
Mar 09 Javascript
微信小程序调用PHP后台接口 解析纯html文本
Jun 13 Javascript
Bootstrap提示框效果的实例代码
Jul 12 Javascript
JavaScript控制浏览器全屏显示简单示例
Jul 05 Javascript
使用React手写一个对话框或模态框的方法示例
Apr 25 Javascript
vue数据响应式原理知识点总结
Feb 16 Javascript
vue在图片上传的时候压缩图片
Nov 18 Vue.js
jQuery实现可以扩展的日历
Dec 01 jQuery
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的substr_replace将指定两位置之间的字符替换为*号
2011/05/04 PHP
php获取后台Job管理的实现代码
2011/06/10 PHP
php中instanceof 与 is_a()区别分析
2015/03/03 PHP
PhpSpreadsheet设置单元格常用操作汇总
2020/11/13 PHP
firefox插件Firebug的使用教程
2010/01/02 Javascript
Jquery实战_读书笔记2 选择器
2010/01/22 Javascript
JQuery中each()的使用方法说明
2010/08/19 Javascript
JS将所有对象s的属性复制给对象r(原生js+jquery)
2014/01/25 Javascript
web前端开发JQuery常用实例代码片段(50个)
2015/08/28 Javascript
每天一篇javascript学习小结(String对象)
2015/11/18 Javascript
JS动态改变浏览器标题的方法
2016/04/06 Javascript
javascript实现任务栏消息提示的简单实例
2016/05/31 Javascript
浅谈javascript中的Function和Arguments
2016/08/30 Javascript
JS高级运动实例分析
2016/12/20 Javascript
jQuery 1.9版本以上的浏览器判断方法代码分享
2017/08/28 jQuery
AngularJS路由删除#符号解决的办法
2017/09/28 Javascript
基于cropper.js封装vue实现在线图片裁剪组件功能
2018/03/01 Javascript
小程序云开发如何实现图片上传及发表文字
2019/05/17 Javascript
Vue CLI3基础学习之pages构建多页应用
2019/06/02 Javascript
微信小程序获取用户绑定手机号方法示例
2019/07/21 Javascript
[48:00]完美世界DOTA2联赛循环赛 Forest vs Inki BO2第二场 11.04
2020/11/04 DOTA
Python完全新手教程
2007/02/08 Python
使用PYTHON接收多播数据的代码
2012/03/01 Python
在Python中操作列表之List.append()方法的使用
2015/05/20 Python
python实现的二叉树定义与遍历算法实例
2017/06/30 Python
对python指数、幂数拟合curve_fit详解
2018/12/29 Python
关于python下cv.waitKey无响应的原因及解决方法
2019/01/10 Python
Python中有几个关键字
2020/06/04 Python
高清屏下canvas重置尺寸引发的问题的解决
2019/10/14 HTML / CSS
工程造价自荐信
2013/10/09 职场文书
教师自荐信范文
2013/12/09 职场文书
《中华少年》教学反思
2014/02/15 职场文书
高中学生会竞选演讲稿
2014/08/25 职场文书
小英雄雨来观后感
2015/06/09 职场文书
分享7个 Python 实战项目练习
2022/03/03 Python
SQL语句多表联合查询的方法示例
2022/04/18 MySQL