概述
今天查資料查到了一些有趣的東西,記錄下來,供以后開發時參考,相信對其他人也有用。
參考資料:
import、require、export、module.exports 混合使用詳解
從 import 講起
import { button, Select } from 'element-ui'這段代碼到底發生了什么?
babel 會將這段代碼進行轉碼,轉碼之后是這個樣子:
var a = require('element-ui');
var Button = a.Button;
var Select = a.Select;
所以,就算我們只想使用 element-ui 的 button 和 Select 這2個組件,但是實際上,我們把整個 elment-ui 庫引入進來了。
babel-plugin-component 做了什么
我們知道,在 element-ui 的文檔里面強調,如果要使用按需加載,就要使用 babel-plugin-component 庫。那么 babel-plugin-component 庫又做了什么?簡單來說,它把上面的代碼轉化成了下面的樣子:
import Button from 'element-ui/lib/button'
import Select from 'element-ui/lib/select'
這樣就只會引入 Button 和 Select 這兩個組件了。
類似的,e-charts 在按需引入組件的時候是這么引入的,也是一樣的道理。
import 'echarts/lib/chart/bar';
import 'echarts/lib/chart/line';
import 'echarts/lib/chart/scatter';
import 'echarts/lib/chart/effectScatter';
import 'echarts/lib/chart/treemap';
所以,所有支持按需引入的庫,都可以用上面的方法進行按需引入組件。
一個問題
如果我們有一個需求,就是在 app 加載的時候不引入 element-ui 庫,然后在/admin這個路由下面才引入 element-ui ,那要怎么做呢?
在 main.js 使用各種形式的按需加載肯定是不行的,因為會打包進入 app.js 里面去,從而在初次加載 app 的時候加載。
在/admin這個路由下,各個組件用到 element-ui 的組件的時候,各自按需加載。這個方法是可行的,但是非常繁瑣,每次用到 element-ui 的組件都需要引入一下,然后掛載一下。
我選擇的方法是,在/admin這個路由的組件下面,按需加載全部需要的 element-ui 組件,示例代碼如下:
// admin.element.js
import Vue from 'vue';
import Row from 'element-ui/lib/row';
import Col from 'element-ui/lib/col';
import Table from 'element-ui/lib/table';
import TableColumn from 'element-ui/lib/table-column';
import Button from 'element-ui/lib/button';
import Footer from 'element-ui/lib/footer';
import Form from 'element-ui/lib/form';
import FormItem from 'element-ui/lib/form-item';
import Input from 'element-ui/lib/input';
import Menu from 'element-ui/lib/menu';
import Submenu from 'element-ui/lib/submenu';
import MenuItem from 'element-ui/lib/menu-item';
import Loading from 'element-ui/lib/loading';
import Message from 'element-ui/lib/message';
const components = [
Row,
Col,
Table,
TableColumn,
Button,
Footer,
Form,
FormItem,
Input,
Menu,
Submenu,
MenuItem,
];
components.forEach((component) => {
Vue.component(component.name, component);
});
Vue.use(Loading.directive);
Vue.prototype.$message = Message;
內存泄漏
粗看上面的代碼是沒有問題的,但是仔細想的話,如果每次跳轉到/admin路由下面的話,那不是每次都會安裝引入的這些組件嗎?那如果跳轉多次就會安裝多次,造成內存泄漏啊~~~
雖然說 Vue 本身的插件安裝機制已經避免了這種情況,但是我們還是建議加上一行判斷代碼:
import Vue from 'vue';
import Row from 'element-ui/lib/row';
import Col from 'element-ui/lib/col';
import Table from 'element-ui/lib/table';
import TableColumn from 'element-ui/lib/table-column';
import Button from 'element-ui/lib/button';
import Footer from 'element-ui/lib/footer';
import Form from 'element-ui/lib/form';
import FormItem from 'element-ui/lib/form-item';
import Input from 'element-ui/lib/input';
import Menu from 'element-ui/lib/menu';
import Submenu from 'element-ui/lib/submenu';
import MenuItem from 'element-ui/lib/menu-item';
import Loading from 'element-ui/lib/loading';
import Message from 'element-ui/lib/message';
// hack: 防止多次引入導致內存泄漏
if (!Vue.hasAdminPageImportedElement) {
const components = [
Row,
Col,
Table,
TableColumn,
Button,
Footer,
Form,
FormItem,
Input,
Menu,
Submenu,
MenuItem,
];
components.forEach((component) => {
Vue.component(component.name, component);
});
Vue.use(Loading.directive);
Vue.prototype.$message = Message;
Vue.hasAdminPageImportedElement = true;
}
