AngularJS移動開發中的各種坑

来源:http://www.cnblogs.com/heroine/archive/2016/11/17/6075443.html
-Advertisement-
Play Games

捂臉,辛酸淚ing...... 本文主要涉及部分在移動設備上特有的問題。 相對來說,Jquery側重DOM操作,AngularJS是以視圖模型和雙向綁定為核心的。 ...


捂臉,辛酸淚ing......

本文主要涉及部分在移動設備上特有的問題。

相對來說,Jquery側重DOM操作,AngularJS是以視圖模型和雙向綁定為核心的。

DOM操作的問題

        避免使用 jQuery 來操作 DOM,包括增加元素節點,移除元素節點,獲取元素內容,隱藏或顯示元素。你應該使用 directives 來實現這些動作,有必要的話你還要編寫自己的 directives。

       在網站Web前端開發中,如果你感到很難改變習慣,那麼考慮從你的網頁中移除 jQuery 吧。真的,AngularJS 中的 $http 服務非常強大,基本可以替代 jQuery 的 ajax 函數,而且 AngularJS 內嵌了 jQLite ?? 它內部實現的一個 jQuery 子集,包含了常用的 jQuery DOM 操作方法,事件綁定等等。但這並不是說用了AngularJS 就不能用 jQuery 了。如果你的網頁有載入 jQuery 那麼 AngularJS 會優先採用你的 jQuery,否則它會 fall back 到 jQLite。

       如果是移動App或移動Web開發,建議不要引入Jquery了,如果實在需要jquery的某些功能,引入Zepto.js吧。不過請相信我,用了AngularJS,你不會需要Jquery的!

       需要自己編寫 directives 的情況通常是當你使用了第三方的 jQuery 插件。因為插件在 AngularJS 之外對錶單值進行更改,並不能即時反應到 Model 中。例如我們用得比較多的 jQueryUI datepicker 插件,當你選中一個日期後,插件會將日期字元串填到 input 輸入框中。View 改變了,卻並沒有更新 Model,因為$('.datepicker').datepicker(); 這段代碼不屬於 AngularJS 的管理範圍。我們需要編寫一個directive 來讓 DOM 的改變即時更新到 Model 里。

var directives = angular.module('directives', []);
 
directives.directive('datepicker', function() {
   return function(scope, element, attrs) {
       element.datepicker({
           inline: true,
           dateFormat: 'dd.mm.yy',
           onSelect: function(dateText) {
               var modelPath = $(this).attr('ng-model');
               putObject(modelPath, scope, dateText);
               scope.$apply();
           }
       });
   }
});

然後在 HTML 中引入這個 directive

<input type="text" datepicker ng-model="myObject.myDateValue" />

        Directive 就是在 HTML 里寫自定義的標簽屬性,達到插件的作用,有效補充了HTML的功能。這種聲明式的語法擴展了 HTML。建議項目中通用的功能和頁面組件,都封裝成Directive,方便使用和代碼維護。

      需要說明的是,有一個 AngularUI 項目提供了大量的 directive 給我們使用,包括 Bootstrap 框架中的插件以及基於 jQuery 的其他很熱門的 UI 組件。 AngularJS 的社區現在很活躍,生態系統健全。

ngOption 中的 value

       這是個大坑。如果你去查看 ngOption 生成的 <select> 中的 <option> 的選項值(每個 <option value="xxx"> 的 value 部分),那絕對是枉費心機。因為這裡的值永遠都會 是 AngularJS 內部元素的索引,並不是你所指定的表單選項值。

   還是要轉變觀念,AngularJS 已經不再用表單進行數據交互了,而是用 Model。使用 $http 來提交 Model,在 php 中則使用 file_get_contents('php://input') 來獲取前端提交的數據。

Input type='number'的問題

AngularJS有些版本,當輸入框設為 Input type='number'時,在移動設備上ng-change方法會失效。

{{ }} 的問題

在頁面初始化的時候,用戶可能會看到 {{ }},然後閃爍一下才出現真正的內容。
解決辦法:

使用 ng-cloak directive 來隱藏它
使用 ng-bind 替代 {{ }}

將界面與業務邏輯分離

Controller 不應該直接引用 DOM,而應該控制 view 的行為。例如“如果用戶操作了 X,應該發生什麼事情”,“我從哪裡可以獲得 X?”

Service 在大部分情況下也不應該直接引用 DOM,它應該是一個單例(singletons),獨立於界面,與 view 的邏輯無關。它的角色只是“做 X 操作”。

DOM 操作應該放在 directives 裡面。

儘量復用已有功能

你所寫的功能很可能 AngularJS 已經實現了,有一些代碼是可以抽象出來複用的,使用更 Angular 的方式。總之就是很多 jQuery 的繁瑣代碼可以被替代。

1. ng-repeat

ng-repeat 很有用。當 Ajax 從伺服器獲得數據後,我們經常使用 jQuery (比如上面講過的例子) 向某些 HTML 容器節點中添加更多的元素,這在 AngularJS 里是不好的做法。有了 ng-repeat 一切就變得非常簡單了。在你的 $scope 中定義一個數組 (model) 來保存從伺服器拉取的數據,然後使用 ng-repeat 將它與 DOM 綁定即可。下麵的例子初始化定義了 friends 這個 model

<div ng-init="friends = [{name:'John', age:25}, {name:'Mary', age:28}]">
    I have {{friends.length}} friends. They are:
    <ul>
        <li ng-repeat="friend in friends">
            [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.
        </li>
    </ul>
</div>

2. ng-show

 

ng-show 也很有用。使用 jQuery 來根據條件控制界面元素的顯示隱藏,這很常見。但是 Angular 有更好的方式來做到這一點。ng-show (以及 ng-hide) 可以根據布爾表達式來決定隱藏和顯示。

對於數組或字元串,可以用strXXXX.length控制顯示,否則在移動設備上會不正常。

類似的內置 directives 還有 ng-disabled, ng-switch 等等,用於條件控制,語法簡潔,都很強大。

3. ng-class

ng-class 用於條件性地給元素添加 class,以前我們也經常用 jQuery 來實現。Angular 中的 ng-class 當然更好用了,例子:

<div ng-class="{ errorClass: isError, warningClass: isWarning, okClass: !isError && !isWarning }">...</div>

在這裡 ng-class 接受一個 object 對象,key 為 CSS class 名,值為 $scope 變數控制的條件表達式,其他類似的內置 directives 還有 ng-class-even 和 ng-class-odd,很實用。

ng-show和ng-if的使用場景問題

使用ng-show和ng-if都實現控制頁面元素顯示的功能,但2者是不同的,ng-if會動態創建DOM,ng-show只是切換已有DOM的顯示,相當於設置style="display:none",如果使用before和after等css偽類控制顯示效果,可能會出現問題,需要根據情況合理使用ng-show和ng-if。

$watch 和 $apply

AngularJS 的雙向數據綁定是最令人興奮的特性了,然而它也不是全能的魔法,在某些情況下你需要做一些小小的修正。

當你使用 ng-model, ng-repeat 等等來綁定一個元素的值時, AngularJS 為那個值創建了一個 $watch,只要這個值在 AngularJS 的範圍內有任何改變,所有的地方都會同步更新。而你在寫自定義的 directive 時,你需要定義你自己的 $watch 來實現這種自動同步。

有時候你在代碼中改變了 model 的值,view 卻沒有更新,這在自定義事件綁定中經常遇到。這時你就需要手動調用 scope.$apply() 來觸發界面更新。上面 datepicker 的例子已經說明瞭這一點。第三方插件可能會有 call back,我們也可以把回調函數寫成匿名函數作為參數傳入$apply()中。

將 ng-repeat 和其他 directives 結合起來

ng-repeat 很有用,不過它和 DOM 綁定了,很難在同一個元素上使用其他 directives (比如 ng-show, ng-controller 等等)。

如果你想對整個迴圈使用某個 directive,你可以在 repeat 外再包一層父元素把 directive 寫在那兒;如果你想對迴圈內部的每一個元素使用某個 directive,那麼把它放到 ng-repeat 的一個子節點上即可。

Scope的問題

Scope 在 templates 模板中應該是 read-only 的,而在 controller 里應該是 write-only 的。Scope 的目的是引用 model,而不是成為 model。model 就是我們定義的 JavaScript 對象。

$rootScope 是可以用的,不過很可能被濫用

Scopes 在 AngularJS 中形成一定的層級關係,樹狀結構必然有一個根節點。通常我們用不到它,因為幾乎每個 view 都有一個 controller 以及相對應的自己的 scope。

但偶爾有一些數據我們希望全局應用在整個 app 中,這時我們可以將數據註入 $rootScope。因為其他 scope 都會繼承 root scope,所以那些註入的數據對於 ng-show 這類 directive 都是可用的,就像是在本地 $scope 中的變數一樣。

當然,全局變數是邪惡的,你必須很小心地使用 $rootScope。特別是不要用於代碼,而僅僅用於註入數據。如果你非常希望在 $rootScope 寫一個函數,那最好把它寫到 service 里,這樣只有用到的時候它才會被註入,測試起來也方便些。

相反,如果一個函數的功能僅僅是存儲和返回一些數據,就不要把它創建成一個 service。

子作用域的原型繼承問題

       辛酸淚,這個也是個大坑。作用域變數的繼承是基於javascript原型繼承機制的,在使用涉及到作用域的指令如ng-template,ion-modal等時需要特別註意,相關的查找順序這裡就不細說了。

PS:如果有寫錯的地方,歡迎指出,謝謝。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • jquery.validation.js 表單驗證 官網地址:http://bassistance.de/jquery-plugins/jquery-plugin-validation jQuery plugin: Validation 使用說明 一導入js庫<script src="../js/j ...
  • https://developer.mozilla.org/en US/docs/Web/JavaScript/Reference/Global_Objects/JSON js數據類型: js Object JSON.stringify(); JSON.parse(); ...
  • Kendo UI是一個強大的框架用於快速HTML5 UI開發。基於最新的HTML5、CSS3和JavaScript標準。 Kendo UI包含了開發現代JavaScript開發所需要的所有一切,包括:強大的數據源,通用的拖拉(Drag-and-Drop)功能,模板,和UI控制項。 今天開始就對項目里使 ...
  • 簡單的來說,就是給每個需要綁定的元素加上$watcher,緩存下oldValue,然後定時遍歷所有的$watcher,比較newValue和oldValue,如果變化了就做更新的操作。 ...
  • HTML5表單在原有表單特性的基礎上增加了一些比較便捷的特性,使得我們實現一些常用的表單的小部件、輸入類型、輸入驗證不再那麼大費周章。上一篇文章提到了HTML5實現的幾種新的輸入類型,現在我們更加詳盡的瞭解HTML5的表單產生的新特性和功能。 1. 輸入類型和輸入屬性 菜鳥教程上給出了HTML5新增 ...
  • 採用CSS的flex佈局可以很容易的實現特殊佈局,比如垂直居中,div底部對齊等。我遇到了一個交叉佈局的需求,然後用flex佈局很愉快的把它給解決了。 ...
  • 這一節針對attr()與prop()之間的區別進行學習。先看看官方文檔是如何解釋兩者之間功能差異的: attr() Get the value of an attribute for the first element in the set of matched elements or set on ...
  • 這一節詳細的總結jQuery選擇器。 一、基礎選擇器 二、基本過濾器 基本選擇器獲取的元素集合,通過過濾器的篩選,使選擇更加精確。 三、內容過濾器 jQery準備了內容過濾器用於對選擇的元素集合內容進行過濾。 統一名稱: 空元素:不包含任何後代元素或文本內容的元素,如<div></div> 非空元素 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...