內部Hybrid App經驗解讀
鄭昀編纂 關鍵詞:Hybrid,Zepto,Fastclick,Backbone,sui,SPA,pushState,跨域,CORS
- click 事件還是 tap 事件?
- Zepto 的 show/hide 有時不靠譜
- Android 下的跨域問題
- pushState 調用失敗也屬于跨域問題 </ol>
- 對于無需縮放的頁面,禁用雙擊縮放功能,
- 引入 Zepto 框架的 tap 事件 ,
- Zepto 趁著 JQuery 在移動互聯網市場歷史包袱重的機會,搞了一套輕量級類 JQuery 框架的代碼,核心代碼千行,從而迅速成為移動端 DOM 操作庫的首選。
- Zepto 提供了一個 touch 庫,在載入 Zepto 后為 document 綁定 touchstart、touchmove、touchend 事件,根據手指 x、y 值的位置,判斷方向從而觸發 tap、doubleTap、swipeLeft 等事件。
- 原本沒有 tap 事件,Zepto tap 是用 touchstart 和 touchend 模擬出來的。 </ul>
- 引入 Fastclick 的 click 事件 ,
- FastClick 是 FT Labs 專門為解決移動端瀏覽器 300 毫秒點擊延遲問題所開發的一個輕量級的庫。簡而言之,FastClick 在檢測到 touchend 事件的時候,會通過 DOM 自定義事件 立即觸發一個模擬 click 事件,并把瀏覽器在 300 毫秒之后真正觸發的 click 事件阻止掉。 </ul> </ol>
- 繼續引入 Zepto 的 fx_methods,但按 madrobby 所說,沒有定義 speed 時,僅調用原生的 show;
- 從 Zepto 官方的
改為
</ul>
- 如 0x00 和本小節所描述的問題, 不要引入 Zepto 的 touch 和 fx_methods 模塊 。
- 只引入 zepto+event+ajax+form+ie 基本模塊 </ul> </ol>
- Android 的 WebView 通過 file:// 協議加載本地的 HTML5 模板文件。本地文件的 JS 向遠端發送 AJAX 請求,受到 同源策略 的限制,譬如你可能會看到“XMLHttpRequest cannot load file://…… Origin null is not allowed by Access-Control-Allow-Origin.”的錯誤提示,即當你的 URI 是 file:// 時,源域名(origin)為空。
- 借用 difcareer 的評論 :Web 應用程序能且只能使用 XMLHttpRequest 對象向其加載的源域名發起請求,而不能向任何其他域名發起請求,但 HTML5 允許 AJAX 跨域向其他域名發起請求,但是不能獲取服務器端響應 。 </ul>
- iOS 下無此跨域問題。 </ul> </div>
- 如果是 GET 請求:
- 可以通過 JSONP 來解決跨域問題; </ol>
- 如果是 POST 請求: </ul>
- 由 App 原生代碼發起網絡操作,成功后回調 JS。
- 利用 HTML5 的“ Cross-Origin Resource Sharing(CORS,跨域資源共享) ”新特性,在服務器端響應頭里設置: Access-Control-Allow-Origin 頭域;
- 不限制來源,Access-Control-Allow-Origin: *
- 限制來源域,Access-Control-Allow-Origin: http://xxx.com
- 具體設置參考 http://enable-cors.org/ ;
- 這需要瀏覽器支持;
- SmdCn 提及,『在某些版本的 Android 瀏覽器中,因為緩存的原因,第一次 CORS 正常,但第二次會失效。對此,可以通過在響應頭中增加 Cache-Control: no-cache 來解決』。 </ul>
-
設置 Android 的 WebView 如下 settings 參數為 True:
if( Build . VERSION . SDK_INT >= Build . VERSION_CODES . JELLY_BEAN ){
webView . getSettings (). setAllowUniversalAccessFromFileURLs (true);
}
由此允許通過
file url 加載的 Javascript 可以訪問其他的源,包括其他的文件和 http/https 等源。這個設置在 JELLY_BEAN 以前的版本默認是允許,在 JELLY_BEAN 及以后的版本中默認是禁止的。
</div>According to the documentation for setAllowFileAccessFromFileURLs and setAllowUniversalAccessFromFileURLs, they used to be set to true for ICS and older. Starting in JellyBean they turned it off. If you are trying to load a local JS file from a local HTML page, then you'll need to enable these. – Steven
</li> </ol> </div> </div>我們是既會在 Native API 里封裝了一個接口 sendpostmsg,讓 JS 調用(但也因此導致『 除了 POST 請求,其他都可以在 PC 瀏覽器調試』),也會使用 setAllowUniversalAccessFromFileURLs 方法。
0x03,pushState 調用失敗也屬于跨域問題
我們需要使用 HTML5 的特性 history.pushState,手動插入歷史記錄和修改地址欄,這樣雖然地址欄被修改了,但并不觸發網頁跳轉。
同上節,本地文件的 JS 調用 history.pushState 也會遇到跨域問題,報錯如下圖所示:
</div>由于我們使用了 SUI ,繞不開這個問題。所以,最終還是得調用 webView.getSettings().setAllowUniversalAccessFromFileURLs(true);
徹底解決各種跨域問題。
參考資源:
1,2014, 300 毫秒點擊延遲的來龍去脈 ;
2,2015,freebuf,鳶尾, 同源策略詳解及繞過(Part1) ;
3,2015,知乎, 純數據 API 服務,設置 Access-Control-Allow-Origin: * 是否會有安全性隱患?
4,2012,csdn, CORS(跨域資源共享)簡介 ;
5,2014,smdcn, 使用HTML5 CORS特性進行Ajax跨域POST請求 ;
6,2011,sof, WebView Javascript cross domain from a local HTML file ;
7,2014,龔廣, WebView跨源攻擊分析 ;
歡迎訂閱我的微信訂閱號『老兵筆記』,請掃描二維碼關注:
轉載時請注明“轉載自旁觀者-博客園”或者給出本文的原始鏈接。
</div>-EOF-
</div> </span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span>本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!相關經驗
相關資訊
內部做 Hybrid App 開發歷程也不短了,楊海波、潘軍和劉勤紅與前端組、App 組一起總結了不少寶貴的經驗教訓,逐步形成我們自己的標準打法。下面選了幾個經驗點(坑)做進一步解讀。
</div>0x00,click 事件還是 tap 事件?
如 300 毫秒點擊延遲的來龍去脈 一文所言『盡管蘋果公司創造的雙擊縮放行為,是一種在移動設備上訪問桌面端站點的不錯的解決方案,但隨之引入的 300 毫秒點擊延遲也成為了移動端網站讓用戶感覺卡頓的罪魁禍首之一』,此文把原因和對策講得清楚透徹,此處鄭昀不再贅述,感興趣的同學自習一下。
那么,我們看到,時至今日,有三種應對措施:
但我們在實踐過程中,也領教了著名的 Zepto tap 『點透』坑 。
對此,yexiaochai 分析道:
『
1,一旦引入 touch 庫便會在全局綁定事件,每次點擊皆會觸發無意義的 tap 事件 ;
2,zepto 為了實現 doubleTap 等功能,2B 地在 touchend 上設置了一個 setTimeout,然后整個世界都充滿了翔了。
由于 setTimeout 的拋出主干流程,導致其 event 參數失效,這個時候就算在 tap 事件函數中執行 e.preventDefault() 或者什么都是無效的,這是導致 zepto tap“點透”的罪魁禍首。
』
點透的效果可以看 http://www.cnblogs.com/lilyimage/p/3740668.html 所述。總之,有人 建議 , 如果你還打算繼續用 Zepto,那么它的 tap 事件已經沒用了,那你可以自己 build 一個無 touch 模塊的 Zepto ,以便減小文件大小并提高運行效率。
</div>Fastclick 是怎么做的呢?
Fastclick 將事件綁定到你傳入的元素 上,在 touchstart 和 touchend 后(會手動獲取當前點擊 el),如果是類 click 事件便手動觸發 dom 元素的 click 事件。所以 click 事件在 touchend 便被觸發,于是整個響應速度就起來了。這里雖然使用了 touch 事件,但 touch 事件是綁定到了具體 dom 而不是 document 上 ,所以 e.preventDefault 是有效的,我們可以阻止冒泡,也可以阻止瀏覽器默認事件。
最終我們采用 Fastclick 的 click 事件來規避點擊延遲響應。
0x01,Zepto 的 show/hide 有時不靠譜
在 Hybrid App 開發初期,我們引入了 Zepto 的 fx_methods 模塊,來控制元素的顯示與隱藏:
fx_methods | Animated show , hide , toggle , and fade*() methods. | </tr> </tbody> </table>
---|
fx_methods show() and hide() add unnecessary CSS properties on non-animated DOM nodes </td> </tr> | |||||||
When you add fx_methods to your Zepto, the show() and hide() methods are overriden with methods that also call animate. Even in the case of undefined speed (normal show), animate still adds many CSS properties to the shown/hidden nodes. These unexpected CSS rules can interfere with the page CSS (in my case, it has changed the positioning of my child fixed DIVs). </td> </tr> </tbody> </table>即,她認為,即使是簡單的顯示,fx_methods.js 的 show/hide 也會加入一些額外的 CSS,以至于影響整個頁面樣式,而且還會亂彈琴地改變透明度,重置為 1.0。samwu 在 2013 年也講過類似問題。 所以,我們有兩種選擇: 0x02,Android 下的跨域問題 在 Hyrbid App 里,鄭昀要求采用 Template+Data=HTML 模式在手機客戶端本地渲染出所需的頁面。 Template(HTML5 模板文件+JS+CSS+Images)既可以提前打包到 App 安裝包里,也可以從 CDN(如無,則溯源到靜態文件服務器)拉到客戶端里并存儲在本地。 Data 則是通過模板文件里的 JavaScript 腳本,從遠端拉取 JSON 格式的數據包。 那么,這里存在一個跨域問題: 對此,大致有四種應對措施: |