为了账号安全,请及时绑定邮箱和手机立即绑定

在多个页面使用同一个HTML片段方法


上一篇文章中我们使用textarea来模拟AJAX的返回结果,造成了一些误解。

这里我们首先用asp.net的Generic Handler做一个简单的后台来重现这个AJAX过程。
1. HTML页面:

<script type="text/javascript">
    $(function() {
        $("#clickToInsert").click(function() {
            $.get("service.ashx?file=pages2_1.txt", function(data) {
                $("#placeholder").html(data);
            }, "text");
        });
    });
</script>
<input type="button" id="clickToInsert" value="Insert HTML" />
<div id="placeholder">
</div>

2. service.ashx 后台代码:

public void ProcessRequest(HttpContext context)
{
    string filePath = context.Request["file"].ToString();
    string fileContent = String.Empty;
    using (StreamReader sr = new StreamReader(context.Server.MapPath(filePath)))
    {
        fileContent = sr.ReadToEnd();
    }
    context.Response.ContentType = "text/plain";
    context.Response.Write(fileContent);
}


3. pages2_1.txt 文件:

<script type="text/javascript">
    $(function() {
        var parent = $("#complex_page_segment");
        $(".previous", parent).click(function() {
            $(".content", parent).html("Previous Page Content");
        });
        $(".next", parent).click(function() {
            $(".content", parent).html("Next Page Content");
        });
    });
</script>
<div id="complex_page_segment">
    <input type="button" value="Previous Page" class="previous" />
    <input type="button" value="Next Page" class="next" />
    <div class="content">Page Content</div>
</div>



将HTML片段中的JavaScript提取为一个文件
这也是自然而然就想到的,特别是HTML片段中JavaScript代码比较多的情况下,
提取为一个JS文件,让浏览器帮忙缓存不失为一种好方法。
1. 重新定义pages2_2.txt 

<script type="text/javascript">
    $(function() {
        setup();
    });
</script>
<script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="pages2_2.js" type="text/javascript"></script>
<div id="complex_page_segment">
    <input type="button" value="Previous Page" class="previous" />
    <input type="button" value="Next Page" class="next" />
    <div class="content">Page Content</div>
</div>

2. pages2_2.js

function setup() {
    var parent = $("#complex_page_segment");
    $(".previous", parent).click(function() {
        $(".content", parent).html("Previous Page Content");
    });
    $(".next", parent).click(function() {
        $(".content", parent).html("Next Page Content");
    });
}


3. 运行,居然报错! 
https://img1.sycdn.imooc.com//5aeabc8d0001e6ad04250232.jpg
问题分析
错误信息是 setup 这个函数没有定义,但是从Firebug中我们明显看到pages2_2.js的确被加载了。
那个极有可能是在 pages2_2.js 加载之前就调用了 setup 这个函数。
但是我们的setup 函数调用是放在jQuery的 $(function(){ }) 之中的,也就是在页面加载完毕才调用的。

其实现在问题已经很明显了,在AJAX返回页面片段的时候,整个页面是已经加载完成了,也就是DOM Ready。
所以在页面片段中:

$(function() {
    setup();
});

和下面直接调用是等价的:

setup();



解决问题
对于这个问题,我们有三种解决办法。
1. 将外部JS文件在页面中加载,而不是在AJAX返回的HTML片段。

2. 我们可以通过JavaScript先加载外部JS,再加载纯粹的HTML片段。
看一下pages2_3.htm的实现: 

<script type="text/javascript">
    $(function() {
        $("#clickToInsert").click(function() {
            $.getScript("pages2_2.js", function() {
                $.get("service.ashx?file=pages2_3.txt", function(data) {
                    $("#placeholder").html(data);
                }, "text");
            });
        });
    });
</script>
<input type="button" id="clickToInsert" value="Insert HTML" />
<div id="placeholder">
</div>


3. 利用JavaScript在页面上是顺序加载的特性,将HTML片段中外部JS引用放在最上面

pages2_4.htm: 

<script type="text/javascript">
    $(function() {
        $("#clickToInsert").click(function() {
            $.get("service.ashx?file=pages2_4.txt", function(data) {
                $("#placeholder").html(data);
            }, "text");
        });
    });
</script>
<input type="button" id="clickToInsert" value="Insert HTML" />
<div id="placeholder">
</div>

pages2_4.txt:

<script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="pages2_2.js" type="text/javascript"></script>
<script type="text/javascript">
    setup();
</script>
<div id="complex_page_segment">
    <input type="button" value="Previous Page" class="previous" />
    <input type="button" value="Next Page" class="next" />
    <div class="content">
        Page Content</div>
</div>


可能你会觉得第三种方法没有必要,但是如果你碰到这样的需求,你就知道第三种方法的重要性了。

  • 不要在每个页面都加载这个JS文件

  • 调用者不知道一个HTML片段关联哪些JS文件



============================================================
关于JS的顺序执行特性
可能有人对这个特性并不是很清楚,我就通过一个例子来说明。

<html>
<head>
    <title></title>
    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="js1.js" type="text/javascript"></script>
    <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="js2.js" type="text/javascript"></script>
    <script type="text/javascript">
        console.log("after js2:" + new Date().toLocaleTimeString());
    </script>
</head>
<body>
</body>
</html>


js1.js: 

console.log("start load js1:" + new Date().toLocaleTimeString());
// 中间是很长很长的一段JavaScript,有12M之多
console.log("end load js2:" + new Date().toLocaleTimeString());

js2.js:

console.log("load js2:" + new Date().toLocaleTimeString());


我们来看下Firebug的记录: 
 

https://img1.sycdn.imooc.com//5aeabd1a0001423f01970140.jpg

https://img1.sycdn.imooc.com//5aeabd1b0001fbd204840137.jpg

可以看到,虽然js2.js更早的被加载,但是还是js1.js执行结束之后,才开始执行js2.js。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消