2015-09-17 92 views
0

我有一个问题了解一般的JavaScript/jQuery执行顺序,以及适当的地方存储您的js的位置。我现在正在尝试重新组织我的代码,并且遇到同样的问题,只会让我对所有javascript感到越来越沮丧。jquery引用错误和执行顺序?

我正在用Jinja2模板构建一个Python + Flask webapp,并且整合了各种jquery的东西。起初我有一些标准的HTML代码,看起来有点像这样...

<html> 
<head> 
    <script type="text/javascript" src="{{url_for('static',filename='js/jquery/jquery-1.11.2.min.js')}}"></script> 
    <script type="text/javascript" src="{{url_for('static',filename='js/bootstrap/bootstrap.min.js')}}"></script> 
    <script type="text/javascript" src="{{url_for('static',filename='js/utils.js')}}"></script> 

    <script type='text/javascript'> 
     # get hash from page 
     function getHash() { 
      var hash = window.location.hash; 
      var newhash = hash.slice(hash.search('_')).replace('_','#'); 
      return newhash; 
     } 

     // Load ifu div element if hash present when page loads 
     $(function(){ 
     var ifuhash = getHash(); 
     var ifu = ifuhash.slice(ifuhash.search('#')+1); 
     $(String(ifuhash)).fadeIn();  
     if (hash.search('comment') >= 0) $(String(hash)).fadeIn(); 
     });   

     ... other js .... 

    </script> 
</head> 

<body> 
    {% include 'header.html' %} 
</body> 
</html> 

它运行得很好。但是,由于一个好的做法似乎是把所有的JS放在他们自己的文件中,为了避免混淆html,我试图将我当前的JavaScript代码重新组织到我认为应该工作的地方,但是我遇到了问题。

功能getHash是常见的几页,所以我拉了这一点,把它贴在一个单独的一块JS,叫plateinfo.js的,这样我的代码现在

<html> 
<head> 
    <script type="text/javascript" src="{{url_for('static',filename='js/jquery/jquery-1.11.2.min.js')}}"></script> 
    <script type="text/javascript" src="{{url_for('static',filename='js/bootstrap/bootstrap.min.js')}}"></script> 
    <script type="text/javascript" src="{{url_for('static',filename='js/utils.js')}}"></script> 
    <script type="text/javascript" src="{{url_for('static',filename='js/plateinfo.js')}}"></script> 

    <script type='text/javascript'> 
     // Load ifu div element if hash present when page loads 
     $(function(){ 
     var ifuhash = getHash(); 
     var ifu = ifuhash.slice(ifuhash.search('#')+1); 
     $(String(ifuhash)).fadeIn();  
     if (hash.search('comment') >= 0) $(String(hash)).fadeIn(); 
     });   

     ... other js .... 

    </script> 
</head> 

<body> 
    {% include 'header.html' %} 
</body> 
</html> 

和plateinfo.js外观像

// Toggle add comment login function 
$(function() { 
    $('#addcommentbut').click(function() { 
     var fxn = 'grabComments'; 
     $('#fxn').val(fxn); 
    }); 
}); 

// Get IFU hash from page 
function getHash() { 
    var hash = window.location.hash; 
    var newhash = hash.slice(hash.search('_')).replace('_','#'); 
    return newhash; 
} 

// Render Tags in div 
function renderTags(hash) { 
    ..does stuff 
} 

然而,当我这样做,我现在得到的错误

的ReferenceError:未定义getHash

该函数在DOM范围之外,应该是可导入的。我之前成功地做到了这一点。 utils.js文件包含完美工作的独立函数。我已清除缓存,重新启动浏览器以刷新会话,重新启动计算机,但似乎没有任何工作。那么交易是什么?我认为html/js代码的执行顺序是直接从上到下。那么这里最好的做法是什么?什么是正确的导入/执行命令?

更新,以显示执行顺序:
所以我把一堆console.logs像这样

<html> 
<head> 
    <script type="text/javascript" src="{{url_for('static',filename='js/jquery/jquery-1.11.2.min.js')}}"></script> 
    <script type="text/javascript" src="{{url_for('static',filename='js/bootstrap/bootstrap.min.js')}}"></script> 

<script type='text/javascript'>$(function() {console.log('before utils.js');});</script> 
    <script type="text/javascript" src="{{url_for('static',filename='js/utils.js')}}"></script> 
<script type='text/javascript'>$(function() {console.log('after utils.js');});</script> 

<script type='text/javascript'>$(function() {console.log('before plateinfo.js');});</script> 
    <script type="text/javascript" src="{{url_for('static',filename='js/plateinfo.js')}}"></script> 
<script type='text/javascript'>$(function() {console.log('after plateinfo.js, before last script');});</script> 

    <script type='text/javascript'> 
     console.log('start of last script'); 

     // Load ifu div element if hash present when page loads 
     $(function(){ 
     console.log('calling gethash'); 
     var ifuhash = getHash(); 
     var ifu = ifuhash.slice(ifuhash.search('#')+1); 
     $(String(ifuhash)).fadeIn();  
     if (hash.search('comment') >= 0) $(String(hash)).fadeIn(); 
     });   

     ... other js .... 

    </script> 
</head> 

<body> 
    {% include 'header.html' %} 
</body> 
</html> 

和这里的日志输出

before utils.js plateInfo.html:40:1 
after utils.js plateInfo.html:44:1 
start of last script plateInfo.html:204:5 
before plateinfo.js plateInfo.html:185:3 
after plateinfo.js, before last script plateInfo.html:189:15 
calling gethash plateInfo.html:221:3 
ReferenceError: getHash is not defined plateInfo.html:222:6 

这是为什么?

另外: 我也有单独但相关的问题引用我的Jinja2模板变量内的JavaScript。这是发生在我包含的这个header.html文件中。如果我将所有的js代码包含在同一个html文件中,它可以正常工作。但是当我将js移动到单独的header.js时,模板变量不再被正确引用。也许这值得一个单独的职位。

+0

我认为{{url_for(“静”,文件名=” js/plateinfo.js')}}在DOM准备就绪后进行评估,以便在脚本全部加载之前,内联脚本正在触发。我可能会尝试在代码中的各个位置插入console.logs,以便跟踪何时加载组件。 –

+0

所以是的,我试过了,看起来好像它把所有的方式都叫做乱糟糟的。它正在跳过console.logs,然后再回到它们。我不知道发生了什么事。如果它以正确的顺序发生,那么为什么方法没有被定义。我编辑了文本以更新日志顺序。 – havok2063

+0

@Neil Jinja是一种Python模板语言;我几乎肯定它会在服务器上进行评估,而不是在浏览器中进行评估。 –

回答

0

getHash()未被定义为全局函数。它是私有的,只属于plateinfo.js中的函数,它告诉jQuery在页面加载时运行。您的代码当前的设置方式,无法在其他地方找到。但是,在你的内联JS,这就是你想要做什么:

var ifuhash = getHash(); 

您可以getHash()全球上市:

function getHash() { 
    // ... 
} 

window.getHash = getHash; 

但是这通常被认为是编码不良做法。一种更好的方式来构建你的代码是用namespaces让您所有的自定义功能和对象在一个地方,并附上到window

<script type="text/javascript"> 
    window.myNamespace = window.myNamespace || {}; 
    window.myNamespace.getHash = function() { 
    return 123; 
    }; 
</script> 
<script type="text/javascript"> 
    $(function() { 
    var foo = window.myNamespace.getHash(); // foo now equals 123 
    }); 
<script> 
+0

啊,我错误地解析了你的'plateinfo.js'文件。但我仍然认为你的问题与你声明你的函数的范围以及你试图运行它的范围有关。 –

+0

他已经在全局命名空间中声明了getHash,它不是闭包。仅仅因为函数声明在一个单独的文件中,并不意味着它不在全局范围内声明。 –

+0

我认为这就是答案。我最终重写了整个plateinfo.js,所以它是一个对象,我在我的主代码块中实例化。我将getHash转换为一个在初始化时运行的函数,并将结果存储在对象中的变量中。这似乎简化并解决了我的问题。 – havok2063