引言
结合了后端的页面有多种代码复用技术,如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>
。