1. 程式人生 > >自行封裝js實現單頁功能

自行封裝js實現單頁功能

話不多說,先奉上程式碼,再慢慢細聊!

/****author: XYB****/

(function() {
var util = {
//獲取路由的路徑和詳細引數
getParamsUrl:function(){
var hashDeatail = location.hash.split("?"),
hashName = hashDeatail[0].split("#")[1],//路由地址
params = hashDeatail[1] ? hashDeatail[1].split("&") : [],//引數內容
query = {};
for(var i = 0;i<params.length ; i++){
var item = params[i].split("=");
query[item[0]] = item[1]
}
return {
path:hashName,
query:query
}
}
}
function spaRouters(){
this.routers = {};//儲存註冊的所有路由
this.beforeFun = null;//切換前
this.afterFun = null;
}
spaRouters.prototype={
init:function(){
var self = this;
//頁面載入匹配路由
window.addEventListener('load',function(){
self.urlChange()
})
//路由切換
window.addEventListener('hashchange',function(){
self.urlChange()
})
//非同步引入js通過回撥傳遞引數
window.SPA_RESOLVE_INIT = null;
},
refresh:function(currentHash){
var self = this;
if(self.beforeFun){
self.beforeFun({
to:{
path:currentHash.path,
query:currentHash.query
},
next:function(){
self.routers[currentHash.path].callback.call(self,currentHash)
}
})
}else{
self.routers[currentHash.path].callback.call(self,currentHash)
}
},
//路由處理
urlChange:function(){
var currentHash = util.getParamsUrl();
if(this.routers[currentHash.path]){
this.refresh(currentHash)
}else{
//不存在的地址重定向到首頁
location.hash = '/index'
}
},
//單層路由註冊
map:function(path,callback){
path = path.replace(/\s*/g,"");//過濾空格
if(callback && Object.prototype.toString.call(callback) === '[object Function]' ){
this.routers[path] ={
callback:callback,//回撥
fn:null //儲存非同步檔案狀態
}
}else{
console.trace('註冊'+path+'地址需要提供正確的的註冊回撥')
}
},
//切換之前一些處理
beforeEach:function(callback){
if(Object.prototype.toString.call(callback) === '[object Function]'){
this.beforeFun = callback;
}else{
console.trace('路由切換前鉤子函式不正確')
}
},
//切換成功之後
afterEach:function(callback){
if(Object.prototype.toString.call(callback) === '[object Function]'){
this.afterFun = callback;
}else{
console.trace('路由切換後回撥函式不正確')
}
},
//路由非同步懶載入js檔案
asyncFun:function(file,transition){
var self = this;
if(self.routers[transition.path].fn){
self.afterFun && self.afterFun(transition)
self.routers[transition.path].fn(transition)
}else{
console.log("開始非同步下載js檔案"+file)
var _body= document.getElementsByTagName('body')[0];
var scriptEle= document.createElement('script');
scriptEle.type= 'text/javascript';
scriptEle.src= file;
scriptEle.async = true;
SPA_RESOLVE_INIT = null;
scriptEle.onload= function(){
console.log('下載'+file+'完成')
self.afterFun && self.afterFun(transition)
self.routers[transition.path].fn = SPA_RESOLVE_INIT;
self.routers[transition.path].fn(transition)
}
_body.appendChild(scriptEle);
}
},
//同步操作
syncFun:function(callback,transition){
this.afterFun && this.afterFun(transition)
callback && callback(transition)
}

}
//註冊到window全域性
window.spaRouters = new spaRouters();
})()


案例如下:

1、建立靜態.html/.htm檔案;

2、在html中建立文件元素
<a href="#/login">測試1</a>,
<a href="#/register">測試2</a>
<a href="#/main">測試3</a>
“#”後代表的是相對應的內容;

3、分別建立3個
login.js
index.js
main.js指令碼檔案;
4、註冊路由 : 
spaRouters.map('/index',function(transition){
//非同步載入js
spaRouters.asyncFun('index.js',transition)
//或者同步執行回撥
//spaRouters.syncFun(function(transition){},transition)
})

5、login.js指令碼程式碼如下:
   SPA_RESOLVE_INIT = function(transition) {
  alert("請登入");
}
5、index.js指令碼程式碼如下:
   SPA_RESOLVE_INIT = function(transition) {
  alert("測試1");
}

5、main.js指令碼程式碼如下:
   SPA_RESOLVE_INIT = function(transition) {
  alert("測試2");
}

6、初始化:spaRouters.init();


結束語:

   本文下筆之處還以為會發現一些好玩的東西,後來發現自己想多了。

  整理來整理去,最後就成了一個比較詳盡的文件了。

  之後寫元件,我會藉助些原生的已經內建好的方法來實現,可以省去不少功夫,會很有意思。

  日後的精彩演繹源自平時平淡的積累。

  對於大部分的人,對於本文這些是無感的,想不到如何在實際專案中應用,覺得很雞肋,實際上大有可為的,我已經想要躍躍欲試了,嘿嘿。

  如有疑問,請各位基佬們私聊或留言,我的大哥大25英寸的手機一直帶著身上,可隨時聯絡我......