在Angular指令中使用NgModelController做数据绑定
前言
AngularJS 中的指令是其尤为复杂的一个部分,但是这也是其比较好玩的地方。今天我们就来说一说 AngularJS 中的**NgModelController
**。
在 AngularJS 的内置指令中,有一个 directive
叫做 ngModel
,我们可以用它来沟通控制器和视图层的数据交换。说的简单点,就是我们可以用它来做双方数据绑定。
这篇文章我们就来说一说如何在我们自定义的指令中,利用 ngModel
的 controller
来做双向数据绑定。
注意,本篇文章不是对 NgModelController
文档的说明,而是更偏向实践。下面我将全程带领大家去实现一个自定义指令,并且利用 ng-model
属性来做双方的数据绑定。
示例
我们的app中使用了一个自定义的指令,名字叫做 timeDruation ,如下:
我们的示例指令可以做这样一件事,可以指定几个常见的时间单位,并且能够输入数据。最终我们将得到对应的秒数。其功能的截图如下: 这里我们特意将 test 变量分别绑定到我们的自定义指令和默认指令中,以观察其效果。
自定义指令
闲话少叙,show my code. 先上指令的模板。从上图中可以看出,指令包含一个输入框一个下拉选择框。
模板其实很简单,这里就不多说了。下面我们来看看这个指令的逻辑部分。
指令的 link
方法我们暂时TODO了它。后面会逐步完善。
我先来看看这个指令的定义,其中用到了 require
声明。简单来说,require 的作用就是为这个 directive 声明一个依赖关系,表明此 directive 依赖另一个指令的 controller 属性。
这里稍微说明一下 require
的衍生用法。我们可以在 require 前加上修辞量词,比如:
^
前缀修饰表示允许查找当前指令的父级指令,如果找不到对应指令的 controller 则抛出一个错误。?
则表示将这个 require 动作变成一个可选项,意思就是找不到对应指令的 controller 就算了,不会抛出错误。?^
当然,我们也可以联合使用这两个前缀修饰。
相对 ?ngModel
,^ngModel
我们使用的频率要更加高一点。比如:
这时,我们在 other-directive 中使用 require: ^ngModel
,它将会自动查找 my-directive 指令声明中的 controller 属性。
使用NgModelController
当我们声明了 require: 'ngModel'
之后,在 link
方法中会注入第四个参数,这个参数就是我们 require 的那个指令对应的 controller。这里就是内置指令 ngModel
的指控器 ngModeController
了。
$viewValue
和 $modelValue
在 ngModelController 中有两个很重要的属性,一个叫做 $viewValue
,一个叫做 $modeValue
。这两者的含义官方的解释如下:
$viewValue
: Actual string value in the view.$modelValue
: The value in the model, that the control is bound to.
我们的这个 time-duration 示例中,$viewValue
其实指的是指令模板中 num和unit 组合出来的值,而 $modelValue
是 HelloAppController 中 test 变量对应的值。
$formatters
和 $parses
除了 $viewValue
和 $modelValue
这两个属性之外,还有两个用来处理他们的方法。分别是 $parses
和 $formatters
。
前者的是作用是将 $viewValue
-> $modelValue
,后者的作用恰好相反,是将 $modelValue
-> $viewValue
。
time-duration 指令与外部控制器以及其内部的运作如下图:
在外部控制器中(即这里的 HelloApp 的 controller),我们通过
ng-model="test"
将 test 变量传入指令 time-duration 中,并建立绑定关系。 2. 在指令内部,$modelValue
其实就是 test 值的一份拷贝。 3. 我们通过$formatters()
方法将$modelValue
转变成$viewValue
。 4. 然后调用$render()
方法将$viewValue
渲染到directive template中。 5. 当我们通过某种途径监控到指令模板中的变量发生变化之后,我们调用$setViewValue()
来更新$viewValue
。 6. 与**(4)**相对应,我们通过$parsers
方法将$viewValue
转化成$modelValue
。 7. 当$modelValue
发生变化后,则会去更新 HelloApp 的 UI。
完善指令逻辑
按照上面的流程,我们先来将 $modelValue
转化成 $viewValue
,然后在指令模板中进行渲染。
最后返回的对象就是 $viewValue
的 value。(当然 $viewValue
还会有其他的一些属性。)
第二步,我们调用 $render
方法将 $viewValue
渲染到指令模板中去。
第三步,我们通过 $watch
来监控指令模板中 num和unit 变量。当其发生变化时,我们需要更新 $viewValue
。
第四步,我们通过 $parsers
将 $viewValue
-> $modelValue
。
All rights reserved @gejiawen.
Last updated
Was this helpful?