2015-09-17 91 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