隨著應用的功能逐漸豐富,邏輯的復雜度不斷的增加,多人協(xié)作等問題, BUI有了自己的模塊化方案, 類似
requirejs
的AMD. 熟悉requirejs
,seajs
都可以很好的適應過來.
window.loader
默認注冊給了bui.loader
. 關于loader的用法,可以查看 bui.loader API.
loader.define 定義一個匿名模塊.
loader.define(function(require,exports,module){
// 以下幾個參數(shù)非必須,如果前面加載了依賴,則這三個參數(shù)后移;
// require : 相當于 loader.require, 獲取依賴的模塊
// exports : 如果沒有return 可以采用這種方式輸出模塊
// module : 拿到當前模塊信息
// 第一次加載會執(zhí)行一次
// 模塊如果需要給其它模塊加載,通過 return 的方式拋出來,或者module.exports的方式
return {};
})
定義模塊需要遵循什么?
loader.define
的匿名模塊;loader.define
里面,防止加載其它模塊的時候沖突;假設我們定義了一個匿名模塊, 是在pages/page2/目錄下, 目錄下有 page2.html ,page2.js 兩個文件. 則默認匿名模塊的 模塊名是 pages/page2/page2 會根據(jù).html 文件提取前面路徑作為模塊名.
page2.js
loader.define(function(require,exports,module){
// 定義初始化
function init(text){
// console.log("init:"+text)
}
// 自執(zhí)行初始化, 如果要給tab 使用,建議不要自執(zhí)行.
init("第一次會自執(zhí)行");
// 拋出方法及變量給外部訪問.
return {
init: init,
pageName: "page2"
}
})
現(xiàn)在我們想在剛剛的main.js里面加載這個模塊,調(diào)用pages/page2/page2 的名稱.
main.js
loader.define(function(require,exports,module){
// 1. 加載pages/page2/page2模塊 方法1: 這里會自執(zhí)行一次 init. 輸出自執(zhí)行. 如果該模塊已經(jīng)加載過了,這里則不會執(zhí)行.
require("pages/page2/page2");
// 2. 有回調(diào)的時候,是會每次都執(zhí)行, 如果define的時候,有一次自執(zhí)行, 會變成執(zhí)行2次.
require("pages/page2/page2",function(page2){
// 這里會執(zhí)行第2次.
page2.init("回調(diào)執(zhí)行")
})
return {
pageName: "main"
}
})
這樣打開首頁的時候,就會加載main.js
, main.js
會去加載pages/page2/page2
模塊,并調(diào)用對應的方法.
造成重復執(zhí)行一般在tab比較常見,
bui.tab
的to
事件是會每次都執(zhí)行, 如果loader.require
的模塊有相同init
回調(diào), 則每次都會執(zhí)行兩次, 解決的辦法是, 外部要操作里面的init
方法時,define
的時候,不要自執(zhí)行init
.
模塊的定義及加載更多用法,請大家自行查閱 bui.loader API
沒有經(jīng)過define的第三方資源,又不想全局引用,可以使用
loader.import
動態(tài)引入進來. 例如,圖表控件.
例子1: 動態(tài)加載單個樣式
loader.import("main.css",function(){
// 創(chuàng)建成功以后執(zhí)行回調(diào)
});
例子2: 動態(tài)加載單個腳本
loader.import("main.js",function(){
// 創(chuàng)建成功以后執(zhí)行回調(diào)
});
例子3: 動態(tài)加載多個腳本
loader.import(["js/plugins/baiduTemplate.js","js/plugins/map.js"],function(){
// 創(chuàng)建成功以后執(zhí)行回調(diào)
});
例子4: 1.5.2新增, 動態(tài)加載模板,回調(diào)每次都執(zhí)行, 如果放在 loader.require 里面執(zhí)行,則默認只初始化一次;
loader.import("pages/ui/list.html",function(res){
// 拿到模板信息
});
例子5: 1.5.4新增, 把html,渲染到某個id下,只渲染一次. 有回調(diào)也只執(zhí)行一次
loader.import("pages/ui/list.html","#id",function(res){
// 在渲染模板到#id以后,回調(diào)只執(zhí)行一次
});
樣式的引入沒有局部作用域,所以加載樣式文件可能會造成影響全局,最好樣式還是統(tǒng)一
sass模塊化
管理.
如果需要同步加載多個文件, 應該使用loader.importSync
來替代loader.import
;
例子: 動態(tài)加載多個腳本
loader.importSync(["js/plugins/baiduTemplate.js","js/plugins/map.js"],function(){
// 創(chuàng)建成功以后執(zhí)行回調(diào)
});
可以用于設置或者獲取已經(jīng)加載的模塊的相關信息
例子1: 獲取所有模塊的配置信息
var map = loader.map();
例子2: 聲明單個模塊, router路由默認聲明了main模塊,頁面打開會自動加載該模板下的資源,也可以通過map去修改
修改首頁,必須在 window.router=bui.router(); 之后;
loader.map({
moduleName: "main",
template: "pages/main/main.html",
script: "pages/main/main.js"
})
例子3: 定義多個模塊,并修改路徑
loader.map({
baseUrl: "",
modules: {
"main": {
moduleName: "main",
template: "pages/main/main.html",
script: "pages/main/main.js"
}
"home": {
moduleName: "home",
template: "pages/main/home.html",
script: "pages/main/home.js"
}
}
})
注意:
router.load({url:"home"})
loader.define
的第一個參數(shù)有自定義名稱, 則還需要通過loader.map
配置下模塊的路徑及模板指向.1.5.3 新增
var main = loader.get("main");
1.5.3 新增
如要設置main模塊, 必須在
window.router = bui.router()
之后,router.init
之前.
loader.set("main",{
template:"pages/login/login.html",
script: "pages/login/login.js"
});
1.5.3 新增. 需要配合路由使用,路由里面會去調(diào)用模塊定義的生命周期.
beforeCreate
,create
只在模塊第一次創(chuàng)建的時候執(zhí)行,如果相同模塊第2次拿的是緩存, 不會觸發(fā);beforeLoad
,loaded
每次進入頁面都會執(zhí)行, loaded
就相當于 loader.define(function(){})
里面的function;show
,hide
每次頁面前進后退都會分別執(zhí)行, 可以通過形參拿到 show,hide 的 type 是 load, 還是 back, 默認當前頁刷新, 也會觸發(fā) show, type 則等于 firstload;beforeDestroy
,destroyed
每次后退前跟后退后執(zhí)行;注意:
beforeLoad
這里return false 并不能阻止頁面跳轉及執(zhí)行, 如果要阻止應該在bui.load({url:"",beforeLoad:function(){ return false; }})
.
loader.define({
beforeCreate: function() {
// 只在創(chuàng)建腳本前執(zhí)行,緩存的時候不執(zhí)行
console.log(this.moduleName + " before create")
},
created: function() {
// 只在創(chuàng)建后執(zhí)行,緩存的時候不執(zhí)行
console.log(this.moduleName + " createed")
},
beforeLoad: function() {
// 頁面每次跳轉前都會執(zhí)行
console.log(this.moduleName + " before load")
},
loaded: function() {
// 頁面每次跳轉后都會執(zhí)行
console.log(this.moduleName + " loaded")
},
hide: function(e) {
// 頁面每次跳轉后退都會執(zhí)行當前模塊的觸發(fā)
console.log(this.moduleName + " hide")
console.log(e.type)
},
show: function(e) {
// 頁面每次跳轉后退都會執(zhí)行當前模塊的觸發(fā)
console.log(this.moduleName + " show")
console.log(e.type)
},
beforeDestroy: function() {
// 頁面每次后退前執(zhí)行
console.log(this.moduleName + " before destroy")
},
destroyed: function() {
// 頁面每次后退后執(zhí)行
console.log(this.moduleName + " destroyed")
}
})
當然,你依然可以使用默認最簡單的模塊創(chuàng)建方式, 只是特殊模塊你可以給它自己的生命周期, 比方我在列表頁面,進去詳情頁, 后退到列表頁, 是不會刷新的, 之前的方式是在后退的時候執(zhí)行某個方法. 現(xiàn)在只要在
show
的這個生命周期里, 我可以調(diào)用這個頁面的某個局部刷新的方法, 不管是前進后退, 都可以執(zhí)行.
例子: 利用生命周期實現(xiàn)后退刷新.
loader.define({
loaded: function() {
this.pageview = {};
// 初始化
this.pageview.init = function(){
}
// 局部刷新
this.pageview.refresh = function(){
}
// 這個是拋出給 loader.require 訪問的, 不能return this
return this.pageview;
},
show: function(e) {
// 后退才觸發(fā)刷新操作
if( e.type == "back" ){
this.pageview.refresh();
}
}
})
比方跳轉的頁面里面有個定時器, 后退的時候, 需要清理掉這個定時器, 這些是需要自己清除的.
loader.define({
loaded: function() {
// 頁面每次跳轉后都會執(zhí)行
console.log(this.moduleName + " loaded")
// 定時刷新
this.timetoRefresh = window.setInterval(function(){
// 4秒后執(zhí)行刷新
},2000)
},
beforeDestroy: function() {
// 頁面每次后退前執(zhí)行
console.log(this.moduleName + " before destroy")
if( this.timetoRefresh ){
window.clearInterval(this.timetoRefresh);
}
}
})
還有一些比較有用的方法, 會在組件那里介紹.
1.如何拋出當前模塊的方法共享
- 推薦 使用return 的方式 ;
2. 使用module.exports 的方式;
3. exports 的方式;
使用任意一種就可以.
2.微信調(diào)試的緩存問題怎么解決?
在 index.js 配置bui.loader
的cache參數(shù) 初始化必須在 window.router
前面
window.loader = bui.loader({
cache: false
})
3.為什么不直接采用requirejs或者seajs呢?
這兩種方式都有在項目中使用,這樣模塊的復用及開發(fā)方式就無法統(tǒng)一,A項目開發(fā)完的部分模塊,可能B項目也能用,但兩者各自用的模塊化方式不同, 這就需要熟悉的人去做一定的修改. 采用我們自己的模塊化方式,可以跟bui.router路由更好的配合, 后面模塊化的公共插件也會越來越多, 這是我們以后希望看到的.
4.如何定義模塊的依賴呢?
main.js
// 依賴前置, 這種會優(yōu)先加載完 page2,page3模塊以后再執(zhí)行main的回調(diào). page2,page3 只定義,不執(zhí)行.
loader.define(["pages/page2/page2","pages/page3/page3"],function(page2,page3,require,exports,module){
// 如果需要用到當前模塊信息的話, page3后面依次還有 require,exports,module
})
5.如何定義一個自定義名字的模塊呢?
第1種:
pages/page2/page2.js
loader.define("page2",function(require,exports,module){
// 這里是page2的業(yè)務邏輯
})
index.html
<script src="js/bui.js"></script>
<!-- 加入自定義模塊 -->
<script src="pages/page2/page2.js"></script>
第2種:
index.js
// 映射腳本路徑
loader.map({
moduleName: "page2",
script: "pages/page2/page2.js"
})
// 把路由實例化給 window.router
window.router = bui.router();
bui.ready(function(){
})
pages/page2/page2.js
loader.define("page2",function(require,exports,module){
// 這里是page2的業(yè)務邏輯
})
模塊的定義及加載更多用法,請大家自行查閱 bui.loader API
更多建議: