【JS】純前端程式碼複用技術
引言
結合了後端的頁面有多種程式碼複用技術,如jsp使用<%@ include file="" %>
即可引入公共的頁面成分,如header,footer等結構。但在純前端實現上就很具有侷限性,本文將會介紹網上流傳的幾種純前端程式碼複用方法,以及筆者本人使用的方法。
1.預編譯
通過在靜態頁面中引入類似jsp<%@ include file="" %>
的標籤,然後利用gulp-file-include等預編譯工具進行一次替換,之後頁面就是完整的。
優點:生成的頁面完整,相對於各種非預編譯方法,減少了使用者訪問時的實際請求數,也就提供了最快的訪問速度。
缺點:編碼時不太方便,想要預覽完整頁面需要先預編譯。
2.使用document.writeln()
將需要的HTML程式碼轉成document.writeln()
形式的JS檔案,在需要的地方<script src='' ></script>
一下即可。
優點:簡單粗暴,有自動的HTML轉JS工具,速度快。
缺點:document.writeln()可能會引起頁面重繪,不建議使用。同時生成的JS檔案不便於修改。
3.使用vue.js component
日漸流行的新興前端框架,如Vue,React,Angular,都可以通過類似引入component的形式引入程式碼。
4.使用jQuery .append()
使用ajax方法獲取到HTML程式碼,然後新增到指定的元素內。除了.append()
方法,類似的還有.prepend()
.html()
.data()
.load()
等方法,都可以實現類似的效果。
優點:較為靈活,ajax獲取到後還可以進行一些處理,比如替換一些變數值。
缺點:增加了使用者訪問的請求數,每新增一個重用元素,都會增加使用者訪問時的請求。
筆者的方法
筆者也在做一個小型的Web專案,目前採用的方法是類似於上述第4種的方法,只是加上了一些自己的封裝,具體如下:
common-main.js
function initTry () {
/**
* 修改剩餘待載入的資源,如果全部載入完成,呼叫init()
*/
--global.leftLoadingRes;
if(!global.leftLoadingRes) {
init();
}
}
function loadResAsync(url, doFunc) {
/**
* ajax非同步載入資源,如果載入成功,呼叫initTry()
* @param {string} url - 需要獲取資源的Url
* @callback requestCallback
*/
/**
* @param {requestCallback} doFunc(data) - ajax請求完成後執行的CallBack
* @return {Boolean} 返回true表示資源載入成功,返回false表示資源載入失敗
*/
$.ajax({
url: url,
type: 'get',
//async:false,
success: function(data, status) {
var result = doFunc(data);
if(result) {
initTry();
}
}
});
}
normal.html
<script src='各種lib.js'></script>
<script src='common-main.js'></script>
<script>
global = {
leftLoadingRes: 2
}
//所有resource載入完成後執行的init
function init() {
//先對非動態部分init
tbm_init();
sm_init();
//最後對動態載入部分init
main_init();
}
loadResAsync('header.html', function(data) {
//沒資源依賴的在這個資源載入完畢後直接init
$('#header').append(data);
header_init();
return true;
});
loadResAsync('searchCollapse.html', function(data) {
$('#searchCollapse').append(data);
return true;
});
function main_init() {
//有資源依賴的放在這裡等到所有資源載入完成後統一init
}
</script>
通過loadResAsync()
裡的CallBack
,不依賴其他動態載入資源的init直接在CallBack
裡init;有依賴的放在main_init()
裡,等最後所有資源都載入完了統一init,既保證了資源載入的正確性,又儘可能地提高資源載入的效率。由於loadResAsync()
中的ajax是非同步請求,所以不會因為某個請求響應過慢而導致下面的請求無法執行。
但是要注意,因為使用了非同步請求,所以相應的程式碼有可能需要變動。如:
- 我引入的sb-admin-2.js,init是在
$(function() {})
中,但是頁面載入完成時可能我的header資源還在載入,導致init失敗。這種情況下就要修改sb-admin-2.js,把init方法改名為sba_init()
,並在對應資源的CallBack
中予以呼叫,即可正確載入。 - 對於形如
$('selector').click(function(){})
的函式,如果在資源載入前載入完畢,就會導致函式未繫結到對應元素。這種情況下就需要改為$('parentSelector').on('click','selector',function(){})
,讓對應的事件繫結到頁面中非動態載入的元素,如<body>
或者<html>
。