省略廢話。css
1.ES6以前兩個比較流行的模塊機制CommonJS和AMD。CommonJS模塊就是對象,加載模塊時加載的是拷貝;而ES6加載的是對export的變量的引用。vue
2.ES6模塊不是對象,使用可出如今模塊頂層任何位置的export顯式指定輸出的代碼(變量、函數、class):webpack
export:git
export var name='microsoft'; github
---another example 推薦在底部用{}輸出須要的代碼web
var value_x='microsoft'; vue-router
export { value_x,value_y ,method_y};vuex
若是想給export的變量更名字,可使用as:api
export { value_x,value_y as alias_name ,method_y};數組
export function fn_name(){};
*export的變量是動態綁定其所在模塊的。好比setTimeout後改變value_x的值,接收者獲得的value_x也會定時改變。
import:
import { value_x,mothed_y } from strUrl;
value_x,mothed_y的名稱必須與 strUr 中export的名稱相同。若是想給import的變量更名字,可使用as:
import { value_x as value_z,mothed_y } from strUrl;
*import具備提高效果。
*import會執行所加載的模塊。
*import命令中接收的變量名要在{}中
總體加載:
能夠用*指定一個對象,全部import的東西都加載到這對象上:
import * as mod from strUrl;
var x=mod.value_x;
也能夠用module命令:
module mod from strUrl;
var x=mod.value_x;
export default:
上面說了import命令中加載的變量名稱要和export輸出的名稱一致,咱們也能夠在輸出模塊中用export default指定默認輸出:
export default function(){}; --好比一個匿名函數或對象
而後本身在加載的時候給接收的函數/對象命名:
import customName from strUrl;
*import後不用加{}。由於export default在模塊中只能使用一次,只輸出一個變量/方法/class。
*不管export default輸出的是否是匿名,都視爲匿名。
*除了默認輸出外還想加載其餘變量:
import customName,{value_x,method_x} from strUrl;
*export * from strOtherMod 命令,先加載strOtherMod 再將其輸出,*會忽略strOtherMod 的默認輸出。
-------------------------------------------------------------分割線----------------------------------------------------------------
在實際生產中經常使用到webpack。webpack有code-spliting功能,容許咱們分割代碼,實現模塊靜態/動態加載。
webpack有三種代碼分離方法:
1.打包時在entry部署要打包幾個chunk。
2.使用CommonsChunkPlugin插件去重和分離chunk。
3.Dynamic Imports:經過模塊的內聯函數動態導入代碼(重點)。
import:
webpack使用import語法來實現模塊的動態導入,這裏import會生成一個promise對象:import('path/to/module') -> Promise,如下是官方例子:
if ( module.hot ) {
import('lodash').then(_ => {
// Do something with lodash (a.k.a '_')...
})
} --記住,then()中return的變量會做爲後續then(param)的參數prama
在這裏,import()會被webpack看成一個代碼分割點(split point),所要import的文件會被另外打包成一個chunk,等須要時再加載。
使用時報錯:
Module build failed: SyntaxError: D:/te/src/js/third.js: 'import' and 'export' may only appear at the top level (251:1)
根據webpack官網案例,案例中能成功,這裏的報錯有說是webpack並無按正確的語法來對待import,有網友說須要插件如:syntax-dynamic-import,
也有說babel的presets要加latest和es2015,個人babel配置和presets是沒問題的,估計是插件,這裏留下這個問題。
lazy-loading(須要時加載):
button.onclick = e => import(/* webpackChunkName: "print" */ './print')
.then(module => {
var print = module.default;
print();
});
官網例子很淺顯,觸發某個事件的時候再import模塊,就像圖片廊等用戶滾動的時候再加載更多圖片一個道理。
CommonJS:
webpack也支持commonjs,commonjs模塊主要分爲三塊:模塊引用require、模塊定義exports、模塊標誌module(即模塊自己)。
在服務器端,require(strUrl)是同步的,因爲服務器在本地硬盤讀取文件,速度很快,故而沒問題,但瀏覽器端必須使用異步方法,於是有了AMD/CMD。
webpack實現的commonjs有:
1.require(strUrl); --同步
2.require.resolve(strUrl) --檢索(或者說返回)strUrl模塊的id。
3.require.cache(module.id)
--模塊被require後只執行一次,也只返回一個exports對象。官網表示,在某些極端狀況會須要屢次require同一個模塊,也即重複執行某個require(獲取module並執行回調);
於是能夠執行那面的代碼:
delete require.cache[require.resolve("dependency")];
大意是刪除本來加載完的模塊的id,讓js能夠再次加載模塊並執行回調。
4.require.ensure([dependencies],callback(require),chunkName_str);
--這是webpack的require api裏惟一一個能夠實現異步加載的函數。
第一個參數是模塊依賴的名稱數組(這些依賴是執行callback須要的);
第二個是回調,qi,其形參require容許咱們執行進一步的require.ensure;
第三個是chunk名稱,require.ensure的代碼會被打包到另外一個chunk乘機加載,該參數就是這個chunk的名稱。同名的chunk會被打包在一塊兒。
//------------------------------------------------------------------------分割線---------------------------------------------------------------------------------------------------------------
使用vue的異步組件:
vue定義全局組件的方式是:
Vue.component('name',optionObj);
文檔說,「Vue.js 容許將組件定義爲一個工廠函數,動態地解析組件的定義」:
--------------------------------------引用-------------------------------------------
Vue.component('async-example', function (resolve, reject) {
setTimeout(function () {
// Pass the component definition to the resolve callback
resolve({
template: '<div>I am async!</div>'
})
}, 1000)
})
工廠函數接收一個 resolve 回調,在收到從服務器下載的組件定義時調用。也能夠調用 reject(reason) 指示加載失敗。
這裏 setTimeout 只是爲了演示。怎麼獲取組件徹底由你決定。
---------------------------------------------------------------------------------------------
因此肯定第一點:vue中異步組件的實現,是把 Vue.component('name',optionObj)中optionObj替換爲一個函數,
這個函數執行異步任務,獲取組件的定義並執行回調。
第二點是:當須要用到異步組件的時候,每每是模塊已經足夠大,這時候每每是使用.vue單文件組件,自包含template、css和其餘options。
我我的對文檔中的方法不太能理解:
後來有人解釋說;這總方式是能夠的,但省略了一些生產上的具體代碼,實際上應該這樣寫:
<script>
import Vue from 'vue'
const name_ = Vue.component('name', function (resolve) {
require(['./service-search.vue'], resolve)
})
export default{
data(){
return {}
},
methods: {},
components: {
name: name_ //也能夠更簡便地將function (resolve){}替換這裏的name_
}
}
</script>
vue路由:
另外,我也在學習vue路由時使用異步組件,用的是github上同行的寫法:
import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'
import VueResource from 'vue-resource'
import Vuex from 'vuex'
const setting = resolve => require.ensure([], () => resolve(require('./components/setting.vue')), 'setting');
Vue.use(VueRouter);
Vue.use(VueResource);
Vue.use(Vuex);
const routes=[
{path:'/setting',component:setting},
];
const router = new VueRouter({
mode: 'history',
base: __dirname,
routes
})
new Vue({
router,
store,
el: '#app',
render: h => h(App)
});
實測可行。今天先到這裏。