【新手向】jQuery Mobile中动态加载或执行脚本的分析
jQuery Mobile是我新的項目中要用到的移動端框架,之所以要使用它,僅僅是因為它的兼容性很好,頁面之間的輪轉及其優雅。但是jQuery Mobile的UI我并不喜歡,因此又引入bootstrap。在開發中發現,因為JQM采用ajax的方法加載鏈接到的頁面,所以無法像我們之前的設計 一樣,把不同頁面的腳本放在head之間,即使將這些腳本轉移到body之間,也可能造成一些代碼無法執行。本文簡單的提幾個我自己開發中遇到的情況。
1.框架的init初始事件
使用jquery的習慣就是$(document).ready開頭,然而這在jqm中行不通,因為ready事件只執行一次。當你打開一個URL 時,jqm攔截了jquery的ready事件,在ready之前要執行一大通,其中主要的是mobileinit事件。因此,如果對mobile的一些 核心配置,應該放在mobileinit事件鉤子中。
$(document).on('mobileinit',function(){
? $.mobile.pageLoadErrorMessage="加載出錯了!"
});
但是有一個非常重要的點是,mobileinit之后DOM還沒有加載完,因此如果你把對DOM的操作放在mobileinit事件鉤子中的話,是沒有用的,比如說append、remove等。
ready事件發生在DOM剛剛加載完的時候,這個時候基本上各種操作都可以做了。如果你的移動端web用了jqm,你要記住,點擊一個鏈接雖然 URL變化了,看到的頁面也變化了,但是ready事件早都執行完畢了,所以不會再執行ready事件了,除非再刷新一下頁面。如果你通過審查元素查看, 可以發現,加載的頁面其實是將鏈接指向的頁面的body內容抓取過來,放在一個div data-role=’page’中,把前面的一個頁面隱藏起來。所以實際上很簡單,如果你在ready中使用了on或者古老的live等函數來綁定新事 件,還是可以的,例如:
$(document).ready(function(){
? $(document).on('click','.btn',function(){
???? alert('ok');
? });
});
上面這段代碼中因為使用了on來綁定click事件,所以通過ajax加載出來的頁面中的.btn點擊時也可以響應。但是有些插件要求在DOM加載時就執行的,那就沒有辦法了。JQM提供了新的事件來解決這個問題,即pageinit。
pageinit發生在通過點擊鏈接加載新頁面的時候,因為整個應用都是通過ajax實現的加載,所以當一個新頁面打開的時候,僅僅是一個DOM append和element hide的就可以實現的,要在一個新頁面打開的時候執行某個動作怎辦呢?靠pageinit。比如你現在有兩個頁面A、B,同時使用了一個幻燈插件,但是 幻燈插件只在ready事件中執行了,入口如果是A頁面,你進入A時可以看到幻燈,但是點擊進入B的時候發現幻燈沒有加載。這個時候把幻燈的代碼放到 pageinit事件鉤子中。
$(document).on('pageinit',function(){
? flash_set();
});
可是問題還是來了,有的時候即使你在pageinit事件鉤子中使用代碼也無法執行。你是否想起來mobileinit和ready的區別了,前者 在DOM加載完之前,后者在DOM剛剛加載完的時候。我們完全可以形象的把pageinit比作mobileinit,那么誰來頂替ready呢?jqm 提供了一個pageshow事件,pageshow則是發生在一個新的頁面完全展現出來之后,這個時候不要說DOM了,基本上可以說是一個頁面加載的最后 階段,所以這個時候做什么事都可以,包括jqm通過ajax操作新加載進來的DOM。
2.如何放置你的代碼
通過上面的解說你可能會覺得,全部放在pageshow里面不就好了么。但事實是沒有必要每個頁面都執行那么多腳本,而且你還要考慮如何把它們安排 在不同的頁面位置。例如css,如果你打算直接在某一個頁面中使用單獨的css,那么不要用link放在head之間,因為如果它是被新加載進來 的,head之間的任何代碼都不會被加載進來,你只能把這堆css放在頁面的body中間。
如果你的代碼放置的不好,可能導致腳本執行混亂。例如你的HTML元素中在不同的頁面使用相同的id,就可能因為ajax加載導致同一個DOM中出 現兩個一樣的id,導致執行混亂。即使你在新頁面中使用了新的javscript代碼,也有可能無法執行,例如你希望在新的頁面中對提交的表單進行檢查, 于是在新頁面的body中間加入了下面的代碼
$('#form').submit(function(){
? ...
});
結果發現根本不執行,原因很簡單,submit事件只有在ready的時候被加入事件監聽的序列,而新加的js早就過了ready的時間了,因此,上面這段代碼應該換為
$(document).on('pageshow',function(){
$('#form').submit(function(){
? ...
});
});
3.頁面跳轉問題
jqm遇到使用PHP header location做的頁面跳轉時,就傻了,什么也加載不出來。如果遇到你要頁面跳轉,我教幾個辦法,應對你應用中的跳轉問題。
第一種,使用data-ajax=”false”取消Ajax頁面加載。雖然jqm的頁面輪轉看上去確實很酷,但在不得已的情況下,只能舍棄了。這 個時候你必須注意:如果重新執行頁面DOM,你新的頁面中引入的css、js等能否滿足之后打算加載的頁面,因為一旦你取消了Ajax,就相當于換了一個 入口頁面,網頁的標題變了,加載的文件也變了。
第二種,通過PHP判斷,在不同的情況下顯示不同的鏈接。例如需要用戶登錄的頁面,有些頁面必須用戶登錄了才能看,可以用PHP判斷,如果沒喲登 錄,那些內頁的鏈接直接統一換成登錄頁的鏈接,如果已經登錄,則正常顯示。但這個地方要注意,比如首頁,可能也有這樣的鏈接,如果你登錄了,首頁DOM中 的鏈接是不會變的,所以你需要在登錄操作之后刷新URL,或者通過Ajax的success回調函數中,修改這些鏈接。
第三種,使用$.mobile.changePage實現間接跳轉。jqm之所以不能實現跳轉,是因為它的Ajax加載頁面無法繞過header, 所以如果你最好不要有跳轉,比如你需要跳轉的地方,干脆直接引入跳轉到的頁面,把頁面顯示出來。但是這樣明顯是不大好的,所以實在沒有辦法的時候,使用這 里提出來的間接跳轉。比如你打算某一個地方使用header location了,這個時候打住,把這個跳轉代碼換成下面的代碼:
<html>
<head>
<title>跳轉頁面...</title>
<meta charset="utf-8">
</head>
<body>
<script>
$.mobile.changePage('{$url}');
</script>
</body>
</html>
$url就是要跳轉到的目標地址。這個實現的原理很簡單,Ajax加載的代碼就是上面的<script>部分,激活了 changePage,于是開始跳轉。不過這個動作實際上在用戶體驗上并不好,因為這個跳轉會出現一個空白頁,雖然不影響大局,而且還非常流暢的實現了跳 轉,但是如果用戶追求細節,可能就需要你對這個界面進行進一步的美化,例如加入一些跳轉提示圖片等。
jquery mobile動態添加元素之后不能正確渲染
listview: 添加 jq(".detail").listview("refresh");
div或其他:添加.trigger( "create" );
======================================================================
jqm在初始化頁面時會根據data-xxx在各元素中插入jqm的屬性和類等。在頁面初始化結束后,如果動態的插入一個元素,往往顯示很丑陋,因 為沒有插入jqm的樣式。這個可以用瀏覽器里的開發工具來查看,會發現有些元素多了很多類,而動態插入的元素代碼還是你寫的那樣子。
如果要使動態插入的元素具有jqm的樣式,可以對jqm對象觸發create事件:
<span style="font-size:18px;"> $(selector).trigger('create');</span>?
create事件適用范圍廣,甚至可以是 不存在的元素(raw markup?),比如要插入一個按鈕
$('<a data-role="button">dy button</a>').appendTo('#content').trigger('create');
有些對象提供了refresh 方法,如listview、flip toggle。與create的區別是refresh方法需要作用在已存在的對象上,如
$('ul').listview('refresh'),而且refresh只會去更新新加入的元素,如listview里最新append的元 素會更新,原有的保持不變。(不知有沒理解錯,有些沒測試。原文http://stackoverflow.com/questions/7663078 /jquery-mobile-page-refresh-mechanism
不使用jqm樣式:
如果不希望jqm自動初始化你的元素,有兩種方法。加入data-role="none"屬性,或者在mobileinit事件中對keepNative選項進行配置
$(document).bind('mobileinit',function(){
?$.mobile.page.prototype.options.keepNative = "select, input.foo, textarea.bar";
});
?
材料源自:http://www.111cn.net/wy/jquery/71787.htm
轉載于:https://www.cnblogs.com/babysay123/p/4494568.html
總結
以上是生活随笔為你收集整理的【新手向】jQuery Mobile中动态加载或执行脚本的分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ZOJ 3597 Hit the Ta
- 下一篇: CRITICAL_SECTION的详细说