`
cyfgod
  • 浏览: 65059 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Javascript动态执行问题浅析

    博客分类:
  • Web
阅读更多
现在web2.0/ajax大行其道,我们会经常碰到这种应用case:前端浏览器通过ajax发请求到后端,后端生成html代码返回,前端接收后将html代码插入一个div容器内。这个应用很普遍,一般情况下也不会有什么问题,特别是返回的是单纯的数据的情况下。但如果返回的html代码包含javascript函数或是css style定义,哪可能就会出现问题了。特别是在IE浏览器下(由此看出,IE浏览器真是垃圾!!真是WEB程序开发者的噩梦啊。),Javascript动态执行的问题很突出。相对来说,Firefox支持的较好。

下面是一段示例代码:
__cb_render : function( containerId, htmlContent )
{
    var oDiv = document.getElementById( containerId );
    while( oDiv.childNodes.length > 0 )
    {
        oDiv.removeChild( oDiv.firstChild );
    }

    try
    {
        var container = document.createElement( "div" );
        container.innerHTML = htmlContent;
        oDiv.appendChild( container );
    }
    catch ( error )
    {
        // ignore exception
    }
}

这段代码很简单,将soap返回的html代码插入到页面的一个Div容器里。在firefox里执行,okay,一切都没问题。html代码里的Javascript也能正确得以执行。但在IE浏览器里,很抱歉,一堆问题就来了。

首先,如果返回的html代码以<script开头,哪IE浏览器会直接忽略这些Javascript片断(很奇怪吧,你可以试试。)。而且,中间的Javascript代码根本得不到正确执行,还有就是采用<script src="test.js"/>这种方式引入Javascript函数,也无法成功。

所以,对IE浏览器,我们就需要采取一些特殊的解决方案。有一种解决方案,是强行在每个script tag中添加一个属性<script defer="true"......。Defer属性是指浏览器先load完所有html代码,然后去执行相应的Javascript函数。这种解决方案,一般情况下也能得到正确的结果。但笔者并不推荐,尽量少用defer属性。

以下是另一可行的解决方案,也经过了多种主流浏览器的测试。
__cb_render : function( containerId, htmlContent )
{
    var oDiv = document.getElementById( containerId );
    while( oDiv.childNodes.length > 0 )
    {
        oDiv.removeChild( oDiv.firstChild );
    }

    if( BrowserUtility.isIE( ) )
    {
       // 在html代码开头添加一段空白代码,主要是为了解决script放在开头而被IE忽略的问题
        htmlContent = '<span style="display: none">&nbsp;</span>' + htmlContent;
       // 去掉html代码中script tag的defer属性,防止函数被执行两次
        htmlContent = htmlContent .replace(/<script(.*)defer([^\s|^>]*)([^>]*)>/gi,'<script$1$3>');
    }

    try
    {
        // 先将新的节点append到DOM中
        var container = document.createElement( "div" );
       container.innerHTML = htmlContent;
       oDiv.appendChild( container );
    }
    catch ( error )
    {
        // ignore exception
    }

    var scripts = container.getElementsByTagName( "script" );
    for( var i = 0; i < scripts.length; i++ )
    {
        if( scripts[i].src )
        {
            // 添加script src到head中
              if( BrowserUtility.isIE( ) )
            {
                var scriptObj = document.createElement( "script" );
                scriptObj.setAttribute( "type", "text/javascript" );
                scriptObj.setAttribute( "src", scripts[i].src );

                var head = document.getElementsByTagName( "head" )[0];
                if( head )
                    head.appendChild( scriptObj );
            }
        }
        else if ( scripts[i].innerHTML )
        {    
             //  IE支持该方法去动态执行javascript代码
             if ( window.execScript )
               window.execScript( scripts[i].innerHTML );
        }
    }

    // 如果是safari或是KHTML浏览器,需要将html代码中包含的css style代码显示的append到head中。
    if ( BrowserUtility.isSafari() || BrowserUtility.isKHTML() )
    {
        var styles = container.getElementsByTagName("style");
        for ( var i = 0; i < styles.length; i++ )
        {
            var styleContent = styles[i].innerHTML;
            if ( styleContent )
            {
                var element = document.createElement("style");
                element.type = "text/css";
                if ( element.styleSheet )
                {
                    element.styleSheet.cssText = styleContent;
                }
                else
                {
                    element.appendChild( document.createTextNode( styleContent ) );
                }

                var head = document.getElementsByTagName( "head" )[0];
                if( head )
                {
                    head.appendChild( element );
                }       
            }
        }
    }
}

以上代码中,还有一点要注意的,就是一定先要将container节点append到DOM中,也就是一定要先落地。不然,在javascript执行顺序上会有些问题的。

好了,就到这吧。搞WEB开发,真是很烦啊!!!
5
0
分享到:
评论
4 楼 cyfgod 2008-12-09  
呵呵,你还是没有搞清楚这段代码哦。你可以完全参照我的这段代码去写,不会有什么问题的。有一个地方你忽略了,就是不可以直接:
document.getElementById('d').innerHTML=text;

你必须先要创建一个DIV才行。
   try
    {
       // 先将新的节点append到DOM中
        var container = document.createElement( "div" );
       container.innerHTML = text;
       document.getElementById('d')..appendChild( container );
    }
    catch ( error )
    {
        // ignore exception
    }

然后直接复用我后面的代码(对IE的处理),就没有问题了。在IE和Firefox下,都是正确执行的。

顺便说一句,你用document.write可以得到正确的结果,是因为它在输出的时候,可以执行。
3 楼 butnet 2008-12-08  
<BODY>
  <div id='d'>
  </div>
  <script>
  var text = ""
		+'<input type="button" onclick="myclick()" name="btn1" value="Click me"/>  '
        +'<'+'script language="javascript">  '
		+'function myclick()  '
		+'{'  
	    +'alert("Clicking me");  '
		+'}'  
		+'<'+'/'+'script>  ';
 document.getElementById('d').innerHTML=text;//这样不行
 //document.write(text);这样行
 </script>
 </BODY>


你试试这个呢?
我也在IE 和 FF 里没过,
但不行呢...
2 楼 cyfgod 2008-12-04  
butnet 写道

这样运行会有问题我在innerHTML里的内容大概如下function XX (){}我在一个按钮点击时调用会出现XX没有定义的错误.请问:你是怎么解决这个问题的?我后来把函数的定义全改成了window.XX = function(){}这样的就OK了


我试过IE7和Firefox3,都没有你说的哪个问题,这个是返回的html代码。
<input type="button" onclick="myclick()" name="btn1" value="Click me"/>

<script language="javascript">
function myclick()
{
    alert("Clicking me");
}
</script>


无论是script放前还是后面,都是运行正常。
1 楼 butnet 2008-12-04  
这样运行会有问题
我在innerHTML里的内容大概如下
function XX (){}
我在一个按钮点击时调用
会出现XX没有定义的错误.

请问:你是怎么解决这个问题的?

我后来把函数的定义全改成了
window.XX = function(){}
这样的就OK了

相关推荐

    浅析JavaScript的安全性和执行效率.pdf

    "浅析JavaScript的安全性和执行效率" JavaScript 作为一门广泛应用于 Web 客户端的编程语言,其安全性和执行效率是非常重要的考虑因素。在这个文件中,我们将浅析 JavaScript 的安全性和执行效率,并讨论一些相关的...

    JavaScript教学方法浅析.pdf

    JavaScript教学方法浅析 JavaScript是一种流行的Internet脚本语言,是网页设计的核心技术之一。作为计算机专业的一门专业技能课,JavaScript旨在培养学生动态网页设计制作的专业技术基础能力。本文中笔者结合教学...

    Javascript自执行匿名函数(function() { })()的原理浅析_.docx

    ### JavaScript自执行匿名函数(function() { })()的原理解析 #### 概述 JavaScript作为一种广泛应用于Web开发的脚本语言,其灵活性和强大功能在很大程度上归功于其独特的特性之一——自执行匿名函数(Immediately ...

    JavaScript中闭包之浅析解读(必看篇)_.docx

    JavaScript中的闭包是一种重要的编程概念,它涉及到函数和作用域的高级用法。闭包简单来说,就是一个函数能够访问并操作其外部作用域中的变量,即使在其外部函数已经执行完毕后,仍然能保持对外部作用域的访问权限。...

    理解Javascript_12_执行模型浅析

    eval代码环境涉及使用`eval()`函数动态执行的代码,它的执行环境取决于`eval()`调用的位置。函数执行环境则与每个函数调用关联,为函数提供独立的作用域。 在每个执行环境中,都会有一个Variable Object(变量对象...

    【JavaScript源代码】浅析Promise的介绍及基本用法.docx

    《深入理解JavaScript Promise:从基础到实践》 Promise,作为ES6引入的一种异步编程解决方案,极大地改善了JavaScript中处理回调地狱的困境。它提供了一种更为优雅的方式来组织和管理异步操作,使得代码结构清晰,...

    javascript动画浅析

    通过计算出每一个时间点上元素应该有的CSS值,然后通过JavaScript动态设置到元素上,就可以实现基本的动画效果。 JavaScript动画库的设计 在设计一个动画库时,需要考虑多个动画的执行顺序和效率。初始的思路可能是...

    浅析JavaScript异步代码优化

    本文将深入探讨JavaScript异步编程的问题及其优化策略。 首先,我们来关注最常见的一个问题——回调地狱(Callback Hell)。在处理一系列相互依赖的异步操作时,如果每个操作都嵌套在前一个操作的回调函数中,就会...

    NativeJS随记 - 浅析JavaScript Events

    标题中的“NativeJS随记 - 浅析JavaScript Events”表明这篇博客主要讨论的是JavaScript中的事件处理机制。JavaScript事件是Web开发中的重要组成部分,它允许我们响应用户的交互或浏览器的内部变化。在这里,我们将...

    浅析JavaScript 箭头函数 generator Date JSON

    ### 知识点一:JavaScript 箭头函数 ES6(ECMAScript 2015)标准中引入了一种新的函数表达式——箭头函数(Arrow Function)。箭头函数提供了一种更简洁的函数写法,它主要有以下几个特点: 1. **简洁语法**:箭头...

    深入浅析JavaScript中的作用域和上下文

    JavaScript中,作用域和上下文是理解代码执行逻辑的关键概念。作用域指的是变量和函数的可见性和生命周期,而上下文则关乎`this`关键字的值,它指示了当前代码执行的环境。 **作用域(Scope)** 1. **全局作用域**...

    浅析页面中Java与JavaScript脚本的区别.pdf

    浅析页面中Java与JavaScript脚本的区别 Java 与 JavaScript 脚本是两种不同的编程语言,它们在 Web 开发中扮演着重要的角色。虽然它们都可以嵌入到 HTML 页面中,但是它们的表示方式、执行过程和应用场景都是不...

    浅析JavaScript回调函数应用_.docx

    1. **资源加载**:例如动态加载JavaScript文件、iframe、Ajax请求等,通常会在加载完成后执行回调。 2. **DOM事件**:当DOM事件触发时,可以注册回调函数进行处理。 3. **setTimeout和setInterval**:这两个函数的...

    JavaScript错误处理和堆栈追踪浅析.doc

    JavaScript错误处理和堆栈追踪是JavaScript编程中至关重要的部分,特别是在进行复杂应用开发和测试时。错误处理确保程序在遇到问题时能够优雅地失败,而不是崩溃,而堆栈追踪则帮助开发者快速定位错误发生的位置,...

    深入浅析javascript立即执行函数

    在JavaScript中,由于其动态特性和宽松的语法,IIFE通常用来封装变量和逻辑,保护它们不受全局作用域污染。 首先,我们来探讨一下JavaScript的函数语法。函数在JavaScript中是一个一等公民,可以作为变量赋值,作为...

    浅析javascript异步执行函数导致的变量变化问题解决思路

    本文将深入探讨JavaScript异步执行函数导致的变量变化问题,并提供解决思路。 首先,让我们看一个常见的例子,该例子中`setTimeout`函数用于异步执行一个回调: ```javascript for (var i = 0; i ; i++) { ...

    深化浅析JavaScript中的作用域和上下文_.docx

    JavaScript中的作用域和上下文是编程时必须理解的关键概念,特别是在JavaScript这种动态类型的脚本语言中。作用域决定了变量的可见性和生命周期,而上下文则与`this`关键字的值有关,它指定了当前执行代码的对象。 ...

    浅析JavaScript动画模拟拖拽原理

    2. **监听鼠标事件**: 分别为`mousedown`、`mousemove`和`mouseup`事件添加事件监听器,以便在用户按下鼠标、移动鼠标以及松开鼠标时执行相应的操作。 3. **计算初始坐标**: 在`mousedown`事件中,获取鼠标相对于...

    JavaScript异步加载浅析

    JavaScript异步加载浅析 在Web开发中,JavaScript的加载方式对用户体验和页面性能有着显著影响。主要关注的两个核心问题是同步脚本和异步脚本的加载与执行顺序,以及由此带来的性能优化问题。 首先,同步脚本的...

Global site tag (gtag.js) - Google Analytics