为了减小项目打包体积,提高项目性能,对 Element UI 组件进行按需引入,但是在实际实践过程中遇到了比较有意思的问题,官方写的 demo 也行不通,去 Issues 查找答案,虽然有开发者进行了提问,但是官方并没有给予解决,所以只能用另一种方式实现了,特此记录。
一、误区
这里有个误区,不使用babel-plugin-import
插件,而是如下这么写,依然打包的是整个 Element UI 模块。
import Vue from "vue" import { Button } from "element-ui" Vue.use(Button)
二、正确手法
使用babel-plugin-import
插件,组件库按需加载时在 babel 编译 js 阶段进行了代码转换,只加载使用的组件代码。
1、安装插件
npm install babel-plugin-component -D
2、更改 .babelrc 配置
若项目目录没有 .babelrc 文件,没有的话新建一个。在 babel 执行编译的过程中,会从项目的根目录下的 .babelrc 文件中读取配置。.babelrc 是一个 json 格式的文件。在 .babelrc 配置文件中,主要是对预设(presets) 和 插件(plugins) 进行配置。
{ "plugins": [ [ "component", { "libraryName": "element-ui", "styleLibraryName": "theme-chalk" } ] ] }
3、 新建 auto-import-elementUI.js 文件,注册需要用到的组件
这里以实际项目中使用为例,下面代码注释的是我项目中没有用到的组件。完整组件列表和引入方式(完整组件列表以 components.json 为准)
注意:官方给的例子和我下面写的不太一样,这就是为什么用官方例子就报错,官方是下面的写法,在实际过程就会报错,我所使用的 Element UI 版本为 2.15.13
//官方例子 import Vue from 'vue'; import { Pagination, Dialog, Autocomplete, Dropdown, DropdownMenu, DropdownItem, Menu, Submenu, MenuItem, MenuItemGroup, Input, InputNumber, Radio, RadioGroup, RadioButton, Checkbox, CheckboxButton, CheckboxGroup, Switch, Select, Option, OptionGroup, Button, ButtonGroup, Table, TableColumn, DatePicker, TimeSelect, TimePicker, Popover, Tooltip, Breadcrumb, BreadcrumbItem, Form, FormItem, Tabs, TabPane, Tag, Tree, Alert, Slider, Icon, Row, Col, Upload, Progress, Spinner, Badge, Card, Rate, Steps, Step, Carousel, CarouselItem, Collapse, CollapseItem, Cascader, ColorPicker, Transfer, Container, Header, Aside, Main, Footer, Timeline, TimelineItem, Link, Divider, Image, Calendar, Backtop, PageHeader, CascaderPanel, Loading, MessageBox, Message, Notification } from 'element-ui'; Vue.use(Pagination); Vue.use(Dialog); Vue.use(Autocomplete); Vue.use(Dropdown); Vue.use(DropdownMenu); Vue.use(DropdownItem); Vue.use(Menu); Vue.use(Submenu); Vue.use(MenuItem); Vue.use(MenuItemGroup); Vue.use(Input); Vue.use(InputNumber); Vue.use(Radio); Vue.use(RadioGroup); Vue.use(RadioButton); Vue.use(Checkbox); Vue.use(CheckboxButton); Vue.use(CheckboxGroup); Vue.use(Switch); Vue.use(Select); Vue.use(Option); Vue.use(OptionGroup); Vue.use(Button); Vue.use(ButtonGroup); Vue.use(Table); Vue.use(TableColumn); Vue.use(DatePicker); Vue.use(TimeSelect); Vue.use(TimePicker); Vue.use(Popover); Vue.use(Tooltip); Vue.use(Breadcrumb); Vue.use(BreadcrumbItem); Vue.use(Form); Vue.use(FormItem); Vue.use(Tabs); Vue.use(TabPane); Vue.use(Tag); Vue.use(Tree); Vue.use(Alert); Vue.use(Slider); Vue.use(Icon); Vue.use(Row); Vue.use(Col); Vue.use(Upload); Vue.use(Progress); Vue.use(Spinner); Vue.use(Badge); Vue.use(Card); Vue.use(Rate); Vue.use(Steps); Vue.use(Step); Vue.use(Carousel); Vue.use(CarouselItem); Vue.use(Collapse); Vue.use(CollapseItem); Vue.use(Cascader); Vue.use(ColorPicker); Vue.use(Transfer); Vue.use(Container); Vue.use(Header); Vue.use(Aside); Vue.use(Main); Vue.use(Footer); Vue.use(Timeline); Vue.use(TimelineItem); Vue.use(Link); Vue.use(Divider); Vue.use(Image); Vue.use(Calendar); Vue.use(Backtop); Vue.use(PageHeader); Vue.use(CascaderPanel); Vue.use(Loading.directive); Vue.prototype.$loading = Loading.service; Vue.prototype.$msgbox = MessageBox; Vue.prototype.$alert = MessageBox.alert; Vue.prototype.$confirm = MessageBox.confirm; Vue.prototype.$prompt = MessageBox.prompt; Vue.prototype.$notify = Notification; Vue.prototype.$message = Message;
报错如下:
为了避免出现上面的报错现象,下面的写法是 Issus 给出的正解,不会报错:
//Issus 给出的正解 import Vue from 'vue' import { Pagination, Dialog, // Autocomplete, Dropdown, DropdownMenu, DropdownItem, Menu, Submenu, MenuItem, MenuItemGroup, Input, InputNumber, Radio, RadioGroup, RadioButton, Checkbox, CheckboxButton, CheckboxGroup, Switch, Select, Option, OptionGroup, Button, ButtonGroup, Table, TableColumn, DatePicker, TimeSelect, TimePicker, Popover, Tooltip, Breadcrumb, BreadcrumbItem, Form, FormItem, Tabs, TabPane, Tag, Tree, Alert, Slider, Icon, Row, Col, Upload, Progress, // Spinner, Badge, Card, Rate, // Steps, // Step, // Carousel, // CarouselItem, // Collapse, // CollapseItem, Cascader, ColorPicker, // Transfer, // Container, // Header, // Aside, // Main, // Footer, Timeline, TimelineItem, Link, Divider, // Image, Calendar, // Backtop, // PageHeader, CascaderPanel, Loading, MessageBox, Message, Notification, Scrollbar } from 'element-ui'; Vue.use(Pagination); Vue.use(Dialog); // Vue.use(Autocomplete); Vue.use(Dropdown); Vue.use(DropdownMenu); Vue.use(DropdownItem); Vue.use(Menu); Vue.use(Submenu); Vue.use(MenuItem); Vue.use(MenuItemGroup); Vue.use(Input); Vue.use(InputNumber); Vue.use(Radio); Vue.use(RadioGroup); Vue.use(RadioButton); Vue.use(Checkbox); Vue.use(CheckboxButton); Vue.use(CheckboxGroup); Vue.use(Switch); Vue.use(Select); Vue.use(Option); Vue.use(OptionGroup); Vue.use(Button); Vue.use(ButtonGroup); Vue.use(Table); Vue.use(TableColumn); Vue.use(DatePicker); Vue.use(TimeSelect); Vue.use(TimePicker); Vue.use(Popover); Vue.use(Tooltip); Vue.use(Breadcrumb); Vue.use(BreadcrumbItem); Vue.use(Form); Vue.use(FormItem); Vue.use(Tabs); Vue.use(TabPane); Vue.use(Tag); Vue.use(Tree); Vue.use(Alert); Vue.use(Slider); Vue.use(Icon); Vue.use(Row); Vue.use(Col); Vue.use(Upload); Vue.use(Progress); // Vue.use(Spinner); Vue.use(Badge); Vue.use(Card); Vue.use(Rate); // Vue.use(Steps); // Vue.use(Step); // Vue.use(Carousel); // Vue.use(CarouselItem); // Vue.use(Collapse); // Vue.use(CollapseItem); Vue.use(Cascader); Vue.use(ColorPicker); // Vue.use(Transfer); // Vue.use(Container); // Vue.use(Header); // Vue.use(Aside); // Vue.use(Main); // Vue.use(Footer); Vue.use(Timeline); Vue.use(TimelineItem); Vue.use(Link); Vue.use(Divider); // Vue.use(Image); Vue.use(Calendar); // Vue.use(Backtop); // Vue.use(PageHeader); Vue.use(CascaderPanel); Vue.use(Scrollbar); const { directive: loadingDirective, service: loadingService } = Loading const msgbox = MessageBox const { alert, confirm, prompt } = msgbox Vue.use(loadingDirective) Vue.prototype.$loading = loadingService Vue.prototype.$msgbox = msgbox Vue.prototype.$alert = alert Vue.prototype.$confirm = confirm Vue.prototype.$prompt = prompt Vue.prototype.$notify = Notification Vue.prototype.$message = Message //设置项目中所有拥有 size 属性的组件 Vue.prototype.$ELEMENT = { size: 'small', zIndex: 3000 }
至于为什么这么写,就需要研究源码了。
4、main.js 引入
import "./auto-import-elementUI.js"
接下来启动项目就可以啦。