weixin_33713707 2018-07-18 01:17 采纳率: 0%
浏览 48

为什么脚本不执行?

I'm trying to make a web app that refreshes its content, its styles and scripts using AJAX, so the site updates everything without reloading the page.

So what happens is that I get the page first of all and when it loads I use ajax to make a request to the server and get the html content then another request to get the styles and finally another request to get the script and put it inside a script tag

<script> //The script goes here </script>

then, I put the script tag at the end of the html content and update the body completely with the content

<body>
  The HTML content goes here
  <script> //and here is the script </script>
</body>

The requests are successful and the content loads and so the styles and when I use the browser inspector tool I can see the script loaded inside the script tag but the script doesn't execute.

This was an overview of the question, you can see the code here https://codepen.io/Yousef-Essam/project/editor/ZJGxea

app.js serves the index.html file and then the index file gets the script.js file which sends two requests with ajax to get the content.html file and content.js file and sets the href attribute of the link tag to the style file. The content.js file then is put inside a script tag with the new content. Although the content.html loaded and the style file as well and the script loads in the script tag, the script isn't executed.

Why did that happen and how can I fix it?

--Update--

The problem may be really in using the innerHTML but why doesn't it really work.

Also, I think that eval may be a solution but I want a better solution as using eval is discouraged

  • 写回答

2条回答 默认 最新

  • ?Briella 2018-07-18 02:28
    关注

    The HTML specification dis-allows parsing SCRIPT elements dynamically added as HTML tags after page load using innerHTML (as per the note under the text property description in the living standard).

    SO answers to similar questions without using eval to parse the script were not apparent in a simple search - while they may exist, I've only seen alternative techniques presented off-site.

    Here's a dynamic loader that doesn't use eval. Because loading the script is asynchronous it uses a callback function of the (err, data) type to signal when the script can be called.

    function loadScript( url, callback) {
        var el = document.createElement("SCRIPT");
        el.type = "text/javascript";
        function finish( err) {
            callback( err, err ? false : true);
        }
        el.onerror = finish;
        if( el.readyState){  // <= IE 10
            el.onreadystatechange = function(){
                if( this.readyState == "complete"){
                    finish( null);
                }
            };
        }
        else { 
            el.onload = function() { finish(null) };
        }
        el.setAttribute("async", true);
        el.src = url;
        document.getElementsByTagName("HEAD")[0].appendChild( el);
    } 
    
    // example call to load jQuery 3.2.1         
    
    loadScript( "https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js",
       function (err, ok) {
           if( err) {
               console.log( "loading failed: " + err);
            }
            else {
             console.log( "loading success");
            }
        }
    );
    
    评论
  • 衫裤跑路 2018-07-18 03:23
    关注

    This is too long to post as a comment so I'm posting as an answer.

    You correctly note that:

    I think that eval may be a solution but I want a better solution as using eval is discouraged

    Indeed eval is problematic in any language because it essentially allows the running program to treat a string as code. The big problem with this is that this open the door to code injection (in layman's term: hacking). But this advice is more of a theoretical advice instead of an advice of what functions to use.

    So what does the advice mean by eval?

    Eval is any function or mechanism that allows strings to be interpreted as code. Different languages have different functions or features that allows eval to happen. Some languages for example allows recursive string interpolation. Some languages have a function called interp() that spawns a sub-interpreter. Some languages literally have a function called eval().

    Javascript has four eval mechanisms:

    1. Using the eval() function.

      • Any string passed to eval() is treated as code.
    2. Setting the src attribute of script tags

      • The value of the src attribute is assumed to be a javascript file to be downloaded
      • This works in both literal code (actual code in HTML itself) or dynamically generated script tag (creating script element in javascript and set it's src property)
    3. The body of script tags

      • Any text inside a script tag is treated as code
      • This only works in literal code. As you found out, setting script body using innerHTML is banned (and has been since Netscape 4 - the first browser with javascript)
    4. The javascript: URI protocol

      • Everything after the : is treated as code
      • This only works if the user clicks the link

    So, what you are trying to do is to perform an eval. It does not matter weather you use the eval function or not, you are still trying to do an eval using innerHTML (though it doesn't work)

    So, is there a safe way to run javascript on the page if everything is an eval?

    There is - at least for modern browsers.

    Modern browsers implement a feature called subresource integrity. Unfortunately, at the time this answer is written, it is not supported on Edge. Basically you can calculate the hash of the js file (such as sha1) and declare it in the script tag so the browser can confirm that the js file has not been tampered with. The following is an example:

    <script src="https://cdn.example.com/script.js"
     integrity="sha384-+/M6kredJcxdsqkczBUjMLvqyHb1K/JThDXWsBVxMEeZHEaMKEOEct339VItX1zB"></script>
    

    Are you this paranoid?

    It depends. The eval issue might really be important to you. If so, loading javascript from an external source with subresource integrity set up is the ONLY safe way to execute javascript.

    But not everybody is that paranoid. We have been generally doing OK so far without this feature. Here are a few rules of thumb that can mitigate evaling code regardless if you use the script tag or call eval():

    1. Always make sure you ONLY execute static javascript code. Do not try to construct code from strings.

    2. If you must construct code from strings (for example using a templating language like Handlebars or using a bundler like Webpack or Browserify) then never include any user generated content in the code. You can still load content by making ajax requests instead of including them in the code.

    3. If you must have user generated content in your code than make sure you sanitise the content. There are several generally accepted strategies such as banning the use of special characters like < and > and " or escaping special characters. There are even libraries that will do this for you.

    Basically what we want to avoid is situations like users entering their name as John"; console.log("gotcha");" and somehow being able to execute code.

    评论

报告相同问题?

悬赏问题

  • ¥15 请教一下simulink中S函数相关问题
  • ¥15 Hadoop中eclipse运行问题
  • ¥15 在二层网络中,掩码存在包含关系即可通信
  • ¥15 端口转发器解析失败不知道电脑设置了啥
  • ¥15 Latex算法流程图行号自定义
  • ¥15 关于#python#的问题:我在自己的电脑上运行起来总是报错,希望能给我一个详细的教程,(开发工具-github)
  • ¥40 基于51单片机实现球赛计分器功能
  • ¥15 cs2游戏画面卡住,应用程序sid与指挥者sid不匹配
  • ¥15 实验七:Pandas要有实验截图和代码
  • ¥15 TypeError: Make sure that the iterable only contains strings.