Discuz教程网

在多个页面使用同一个HTML片段的代码

[复制链接]
authicon smile 发表于 2011-3-4 19:36:19 | 显示全部楼层 |阅读模式
有一个比较复杂的HTML片段(A),如果把这个HTML片段嵌入到其他页面中(B,C,D....)。 问题的关键是在HTML片段中有大量的JavaScript逻辑需要处理,比如说分页,点击事件响应等。
问题描述
有一个比较复杂的HTML片段(A),如果把这个HTML片段嵌入到其他页面中(B,C,D....)。
问题的关键是在HTML片段中有大量的JavaScript逻辑需要处理,比如说分页,点击事件响应等。
对于这个问题,我们用一个简单的例子来说明:
“页面上有一个按钮,点击此按钮引入一个HTML片段,此HTML片段中有分页按钮。”
1. 使用IFrame
主页面,点击一个按钮向页面引入一个IFrame:

代码如下:

  1. <script type="text/javascript">
  2. $(function() {
  3. $("#clickToInsert").click(function() {
  4. $("#placeholder").html('<iframe src="iframe.htm"></iframe>');
  5. });
  6. });
  7. </script>
  8. <input type="button" id="clickToInsert" value="Insert HTML" />
  9. <div id="placeholder">
  10. </div>
  11. IFrame页面,模拟分页的情况:
  12. <script type="text/javascript">
  13. $(function() {
  14. var parent = $("#complex_page_segment");
  15. $(".previous", parent).click(function() {
  16. $(".content", parent).html("Previous Page Content");
  17. });
  18. $(".next", parent).click(function() {
  19. $(".content", parent).html("Next Page Content");
  20. });
  21. });
  22. </script>
  23. <div id="complex_page_segment">
  24. <input type="button" value="Previous Page" class="previous" />
  25. <input type="button" value="Next Page" class="next" />
  26. <div class="content">
  27. Page Content</div>
  28. </div>
复制代码


2. AJAX返回页面片段,并注册事件
注:我们通过textarea来模拟返回的HTML片段。

代码如下:

  1. <script type="text/javascript">
  2. $(function() {
  3. $("#clickToInsert").click(function() {
  4. $("#placeholder").html($("#clone").val());
  5. var parent = $("#complex_page_segment");
  6. $(".previous", parent).click(function() {
  7. $(".content", parent).html("Previous Page Content");
  8. });
  9. $(".next", parent).click(function() {
  10. $(".content", parent).html("Next Page Content");
  11. });
  12. });
  13. });
  14. </script>
  15. <input type="button" id="clickToInsert" value="Insert HTML" />
  16. <div id="placeholder">
  17. </div>
  18. <textarea id="clone" style="display: none;">
  19. <div id="complex_page_segment">
  20. <input type="button" value="Previous Page" class="previous" />
  21. <input type="button" value="Next Page" class="next" />
  22. <div class="content">Page Content</div>
  23. </div>
  24. </textarea>
复制代码

由于我们需要在多个页面引用同一个HTML片段,这种方法导致大量事情处理被重复性的拷贝粘贴,明显我们需要将公共的方法提取出来。
3. AJAX返回页面片段,并调用页面片段中的函数注册事件
代码如下:

  1. <script type="text/javascript">
  2. $(function() {
  3. $("#clickToInsert").click(function() {
  4. $("#placeholder").html($("#clone").val());
  5. init_complex_page_segment();
  6. });
  7. });
  8. </script>
  9. <input type="button" id="clickToInsert" value="Insert HTML" />
  10. <div id="placeholder">
  11. </div>
  12. <textarea id="clone" style="display: none;">
  13. <script type="text/javascript">
  14. function init_complex_page_segment() {
  15. var parent = $("#complex_page_segment");
  16. $(".previous", parent).click(function() {
  17. $(".content", parent).html("Previous Page Content");
  18. });
  19. $(".next", parent).click(function() {
  20. $(".content", parent).html("Next Page Content");
  21. });
  22. }
  23. </script>
  24. <div id="complex_page_segment">
  25. <input type="button" value="Previous Page" class="previous" />
  26. <input type="button" value="Next Page" class="next" />
  27. <div class="content">Page Content</div>
  28. </div>
  29. </textarea>
复制代码

其实我们可以更进一步,完全没必要手工调用这个函数,而是可以在返回的HTML片段中让其自动执行。
4. AJAX返回页面片段,其事件自动注册

代码如下:

  1. <script type="text/javascript">
  2. $(function() {
  3. $("#clickToInsert").click(function() {
  4. $("#placeholder").html($("#clone").val());
  5. });
  6. });
  7. </script>
  8. <input type="button" id="clickToInsert" value="Insert HTML" />
  9. <div id="placeholder">
  10. </div>
  11. <textarea id="clone" style="display: none;">
  12. <script type="text/javascript">
  13. $(function() {
  14. var parent = $("#complex_page_segment");
  15. $(".previous", parent).click(function() {
  16. $(".content", parent).html("Previous Page Content");
  17. });
  18. $(".next", parent).click(function() {
  19. $(".content", parent).html("Next Page Content");
  20. });
  21. });
  22. </script>
  23. <div id="complex_page_segment">
  24. <input type="button" value="Previous Page" class="previous" />
  25. <input type="button" value="Next Page" class="next" />
  26. <div class="content">Page Content</div>
  27. </div>
  28. </textarea>
复制代码

最后一种方法和第一种IFrame的方式是我们所推荐的。
下载代码:点击进入下载-pages.rar



上一篇:【Discuz X1.5】汉王手写云输入法1.0
下一篇:比较不错的js退弹窗口代码,测试可以突破ie7
authicon  楼主| smile 发表于 2011-3-4 19:49:49 | 显示全部楼层
本帖最后由 smile 于 2011-3-4 20:06 编辑

上一篇文章中我们使用textarea来模拟AJAX的返回结果,造成了一些误解。 这里我们首先用asp.net的Generic Handler做一个简单的后台来重现这个AJAX过程。
-
-
1. HTML页面:
代码如下:

  1. <script type="text/javascript">
  2. $(function() {
  3. $("#clickToInsert").click(function() {
  4. $.get("service.ashx?file=pages2_1.txt", function(data) {
  5. $("#placeholder").html(data);
  6. }, "text");
  7. });
  8. });
  9. </script>
  10. <input type="button" id="clickToInsert" value="Insert HTML" />
  11. <div id="placeholder">
  12. </div>
复制代码

2. service.ashx 后台代码:
代码如下:

  1. public void ProcessRequest(HttpContext context)
  2. {
  3. string filePath = context.Request["file"].ToString();
  4. string fileContent = String.Empty;
  5. using (StreamReader sr = new StreamReader(context.Server.MapPath(filePath)))
  6. {
  7. fileContent = sr.ReadToEnd();
  8. }
  9. context.Response.ContentType = "text/plain";
  10. context.Response.Write(fileContent);
  11. }
复制代码

3. pages2_1.txt 文件:
代码如下:

  1. <script type="text/javascript">
  2. $(function() {
  3. var parent = $("#complex_page_segment");
  4. $(".previous", parent).click(function() {
  5. $(".content", parent).html("Previous Page Content");
  6. });
  7. $(".next", parent).click(function() {
  8. $(".content", parent).html("Next Page Content");
  9. });
  10. });
  11. </script>
  12. <div id="complex_page_segment">
  13. <input type="button" value="Previous Page" class="previous" />
  14. <input type="button" value="Next Page" class="next" />
  15. <div class="content">Page Content</div>
  16. </div>
复制代码

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

  1. <script type="text/javascript">
  2. $(function() {
  3. setup();
  4. });
  5. </script>
  6. <script src="pages2_2.js" type="text/javascript"></script>
  7. <div id="complex_page_segment">
  8. <input type="button" value="Previous Page" class="previous" />
  9. <input type="button" value="Next Page" class="next" />
  10. <div class="content">Page Content</div>
  11. </div>
复制代码

2. pages2_2.js
代码如下:

  1. function setup() {
  2. var parent = $("#complex_page_segment");
  3. $(".previous", parent).click(function() {
  4. $(".content", parent).html("Previous Page Content");
  5. });
  6. $(".next", parent).click(function() {
  7. $(".content", parent).html("Next Page Content");
  8. });
  9. }
复制代码

3. 运行,居然报错!


问题分析
错误信息是 setup 这个函数没有定义,但是从Firebug中我们明显看到pages2_2.js的确被加载了。
那个极有可能是在 pages2_2.js 加载之前就调用了 setup 这个函数。
但是我们的setup 函数调用是放在jQuery的 $(function(){ }) 之中的,也就是在页面加载完毕才调用的。
其实现在问题已经很明显了,在AJAX返回页面片段的时候,整个页面是已经加载完成了,也就是DOM Ready。
所以在页面片段中:
代码如下:

  1. $(function() {
  2. setup();
  3. });
复制代码

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

  1. setup();
复制代码

解决问题
对于这个问题,我们有三种解决办法。
1. 将外部JS文件在页面中加载,而不是在AJAX返回的HTML片段。
2. 我们可以通过JavaScript先加载外部JS,再加载纯粹的HTML片段。
看一下pages2_3.htm的实现:
复制代码 代码如下:

  1. <script type="text/javascript">
  2. $(function() {
  3. $("#clickToInsert").click(function() {
  4. $.getScript("pages2_2.js", function() {
  5. $.get("service.ashx?file=pages2_3.txt", function(data) {
  6. $("#placeholder").html(data);
  7. }, "text");
  8. });
  9. });
  10. });
  11. </script>
  12. <input type="button" id="clickToInsert" value="Insert HTML" />
  13. <div id="placeholder">
  14. </div>
复制代码

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

  1. <script type="text/javascript">
  2. $(function() {
  3. $("#clickToInsert").click(function() {
  4. $.get("service.ashx?file=pages2_4.txt", function(data) {
  5. $("#placeholder").html(data);
  6. }, "text");
  7. });
  8. });
  9. </script>
  10. <input type="button" id="clickToInsert" value="Insert HTML" />
  11. <div id="placeholder">
  12. </div>
复制代码

pages2_4.txt:
代码如下:

  1. <script src="pages2_2.js" type="text/javascript"></script>
  2. <script type="text/javascript">
  3. setup();
  4. </script>
  5. <div id="complex_page_segment">
  6. <input type="button" value="Previous Page" class="previous" />
  7. <input type="button" value="Next Page" class="next" />
  8. <div class="content">
  9. Page Content</div>
  10. </div>
复制代码

可能你会觉得第三种方法没有必要,但是如果你碰到这样的需求,你就知道第三种方法的重要性了。
不要在每个页面都加载这个JS文件
调用者不知道一个HTML片段关联哪些JS文件
============================================================
关于JS的顺序执行特性
可能有人对这个特性并不是很清楚,我就通过一个例子来说明。
代码如下:

  1. <html>
  2. <head>
  3. <title></title>
  4. <script src="js1.js" type="text/javascript"></script>
  5. <script src="js2.js" type="text/javascript"></script>
  6. <script type="text/javascript">
  7. console.log("after js2:" + new Date().toLocaleTimeString());
  8. </script>
  9. </head>
  10. <body>
  11. </body>
  12. </html>
复制代码

js1.js:
代码如下:

  1. console.log("start load js1:" + new Date().toLocaleTimeString());
复制代码

// 中间是很长很长的一段JavaScript,有12M之多

  1. console.log("end load js2:" + new Date().toLocaleTimeString());
复制代码

js2.js:
代码如下:

  1. console.log("load js2:" + new Date().toLocaleTimeString());
复制代码

我们来看下Firebug的记录:



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

代码下载:点击进入下载-pages2.rar
authicon lkfv 发表于 2011-3-5 06:05:45 | 显示全部楼层
楼主太厉害了!楼主,I*老*虎*U!我觉得1314学习网真是个好地方!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

1314学习网 ( 浙ICP备10214163号 )

GMT+8, 2025-5-3 03:42

Powered by Discuz! X3.4

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表