教你搭建按需加载的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 相关文章推荐
动态刷新 dorado树的js代码
Jun 12 Javascript
跟我一起学写jQuery插件开发方法(附完整实例及下载)
Apr 01 Javascript
简单的前端js+ajax 购物车框架(入门篇)
Oct 29 Javascript
基于jQuery的图片左右无缝滚动插件
May 23 Javascript
点击按钮或链接不跳转只刷新页面的脚本整理
Oct 22 Javascript
利用javaScript实现点击输入框弹出窗体选择信息
Dec 11 Javascript
使用JavaScript链式编程实现模拟Jquery函数
Dec 21 Javascript
JS JSOP跨域请求实例详解
Jul 04 Javascript
js原生日历的实例(推荐)
Oct 31 Javascript
react学习笔记之state以及setState的使用
Dec 07 Javascript
elementUI Vue 单个按钮显示和隐藏的变换功能(两种方法)
Sep 04 Javascript
django简单的前后端分离的数据传输实例 axios
May 18 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
怎么使 Mysql 数据同步
2006/10/09 PHP
PHP 高手之路(二)
2006/10/09 PHP
PHP设计模式之模板方法模式定义与用法详解
2018/04/02 PHP
PHP面向对象程序设计内置标准类,普通数据类型转为对象类型示例
2019/06/12 PHP
Laravel框架实现文件上传的方法分析
2019/09/29 PHP
jquery实现table鼠标经过变色代码
2013/09/25 Javascript
javascript实现客户端兼容各浏览器创建csv并下载的方法
2015/03/23 Javascript
javascript实现拖动元素交换位置
2015/11/29 Javascript
js实现兼容IE、Firefox的图片缩放代码
2015/12/08 Javascript
self.attachevent is not a function的解决方法
2017/04/04 Javascript
配置nodejs环境的方法
2017/05/13 NodeJs
Vue.js数据绑定之data属性
2017/07/07 Javascript
浅析Vue 生命周期
2018/06/21 Javascript
elementUI Tree 树形控件的官方使用文档
2019/04/25 Javascript
JS实现的对象去重功能示例
2019/06/04 Javascript
优雅的使用javascript递归画一棵结构树示例代码
2019/09/22 Javascript
小程序怎样让wx.navigateBack更好用的方法实现
2019/11/01 Javascript
javascript 设计模式之享元模式原理与应用详解
2020/04/08 Javascript
[44:15]DOTA2上海特级锦标赛主赛事日 - 5 败者组决赛Liquid VS EG第二局
2016/03/06 DOTA
[01:38]女王驾到——至宝魔廷新尊技能&特效展示
2020/06/16 DOTA
如何利用python查找电脑文件
2018/04/27 Python
Python使用post及get方式提交数据的实例
2019/01/24 Python
使用python读取.text文件特定行的数据方法
2019/01/28 Python
Python multiprocess pool模块报错pickling error问题解决方法分析
2019/03/20 Python
Python 实现将数组/矩阵转换成Image类
2020/01/09 Python
python判断两个序列的成员是否一样的实例代码
2020/03/01 Python
Python MySQL 日期时间格式化作为参数的操作
2020/03/02 Python
使用css3实现的windows8开机加载动画
2014/12/09 HTML / CSS
党政领导班子四风问题对照检查材料思想汇报
2014/10/02 职场文书
销售区域经理岗位职责
2015/04/10 职场文书
2016年党员学习廉政准则心得体会
2016/01/20 职场文书
pytest配置文件pytest.ini的详细使用
2021/04/17 Python
提取视频中的音频 Python只需要三行代码!
2021/05/10 Python
html中显示特殊符号(附带特殊字符对应表)
2021/06/21 HTML / CSS
Android自定义ScrollView实现阻尼回弹
2022/04/01 Java/Android
PostgreSQL聚合函数介绍以及分组和排序
2022/04/12 PostgreSQL