04月25, 2017

通过样例来学NgController(一)

玩过Angular.js的童鞋都知道, Angular.js里面的ngModel.NgModelController真的很强大,但真TM难理解,学习曲线陡峭的不是一丢丢。我问你,$formatters$render是干毛的? $parsers又是什么玩意,我们该怎么去理解和掌握这些东东?

这篇文章就是来协助你了解其内幕的。不过你不要太担心太有压力,你只要懂一点点Angular.js就可以很好的理解这篇文章所讲述的内容。Angular.js是很复杂,学习曲线也陡峭,不过没关系,我们来慢慢各个击破。

什么是ng-model ?

ng-mode 在angular中主要用来进行双向数据绑定,用于将值绑定到控件上。如下面代码所示:

<label>Username
<input ng-model="use.name">
</label>

上面的例子很简单,但如果你想自定义一个控件,并且希望将一个复杂的数据绑在上面,你会怎么做?又或者说,如何用多个值来表示一个值呢(例如R,G,B三个值来生成一个颜色值)? 解决方案就是利用NgModelController

什么是NgModelController?

在Angular中,ng-model就是利用NgModelController来进行数据绑定的,所以它有很多非常有用的功能值得我们去探究一番。

NgModelController有啥优势?

NgModelController有如下优势:

  • 基于ng-model进行数据校验
  • 可以自由的来回转换底层数据值和显示值,这些数据可以绑定在复杂的UI界面上
  • 可以检测数据是否被修改, 是否是脏数据
  • 使得封装的指令(Directive)更为干净

在这些场景下你会考虑使用NgModelController

  • 你有一个复杂的UI界面,你需要用ng-model来进行数据绑定
  • 你想将底层数据以另外一种方式呈现在UI界面,例如显示在日历控件上。(底层数据结构也许是时间戳,但是需要展现成年月日等)
  • 你想做特殊的数据校验。比如校验日期是否在某个区间内

    数据值的生命周期

为了方便在Directive指令中来回转换底层数据值和显示值,NgModelController提供了 $modelValue,$viewValue以及$scope值

  1. 实际值,用户真正需要的数据(比如需要发送到后台的数据)
  2. NgModelController.$modelValue - 通过ng-model来关联并且与实际值实时同步,它是一个内部用到的值
  3. NgModelController.$viewValue - $modelValue转换后或者格式化的值
  4. $scope值 - 在指令中进行绑定的值,通常是NgModelController.$viewValue 的一个副本

上面提到的几种值如下图所示:

4中值类型

同时,NGModelController通过如下的流程步骤来同步操作上文提到的几种值。

数据同步

咋一看,这图还是蛮复杂的,让人摸不着头脑。不过没关系,我们接下来将用一个例子来逐步分析并阐述它是怎么工作的。一旦你掌握了这些内部流程,以后就可以尽情的发挥个人想象力去折腾Angular了。

样例 — 颜色拾取器

这个样例很简单,也没啥新意,但是用它来阐述底层的一些原理还是蛮不这错的,麻雀虽小,但是五脏俱全嘛!简单说下这个样例的功能:通过选择R、G、B这三种值来组成一个颜色。虽然页面展示的的是三种颜色值,但是在底层,我们是用类似于#FA0这样的值来保存颜色的。页面效果如下所示:

样例

猛撮我来看样例

从上面的截图我们可以看到,我们自定义了一个colour-picker指令,然后用它来展现前景色和背景色两种两种情况。虽然页面上用户看到的是R、G、B,但是在底层,我们实际上是用一个单一的值来进行保存的,并且这个值绑和ng-model绑定在一起。接下来我们对代码进行分析。

应用模块

首先,我们定义一个叫做RadifyExample的模块

var app= angular.module('RadifyExample', [])

控制器

在控制器中,我们设置好前景色和背景色

app.controller('ColourPickerController', function($scope) {
    $scope.background = 'F00';
    $scope.foreground = '000';
})

来点HTML代码

<div ng-app="RadifyExample" ng-controller="ColourPickerController">
    <h1>Colours</h1>
    <label>
        Foreground
        <colour-picker ng-model="foreground"></colour-picker>
    </label>
    <label>
        Background
        <colour-picker ng-model="background"></colour-picker>
    </label>

    <div style="background: #{{ background }}; color: #{{foreground}};" class="results">
        Results
    </div>
</div>

代码比较简单,我们有两个值,分别是前景色和背景色,这两个值的展现都是通过一个名为colour-picker的指令来完成的。指令上我们用ng-model进行了双向数据绑定。

同时,我们还有一个展现操作结果的区域,用户选择颜色后,这个区域会发生变化。

指令

首先,我们处理指令的template, 它由select控件来组成的。


app.directive('colourPicker', function() {
  var tpl = "<div> \
     R <select ng-model='red'> \
         <option value='F'>Lots</option> \
         <option value='A'>Some</option> \
         <option value='0'>None</option> \
     </select> \
     G <select ng-model='green'> \
         <option value='F'>Lots</option> \
         <option value='A'>Some</option> \
         <option value='0'>None</option> \
     </select> \
     B <select ng-model='blue'> \
         <option value='F'>Lots</option> \
         <option value='A'>Some</option> \
         <option value='0'>None</option> \
     </select> \
 </div>";

接下来,我们需要做一些初始化工作。我们需要限制指令值可以通过元素来使用,初始化template,创建隔离作用域。同时,我们还需要引用下ngModel,这样在指令中我们才可以使用ngModelController的功能。

  return {
      restrict: 'E',
      template: tpl,
      scope: {},
      require: 'ngModel'
}

本文链接:http://www.asyncoder.com//post/lear-angular-ng-controller-by-example-part1.html

-- EOF --

Comments