angular指令心得(ng-model)

前端之家收集整理的这篇文章主要介绍了angular指令心得(ng-model)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

angular指令心得(ng-model)

在项目中编写指令,常常会依赖其他的指令来实现想要达到的功能,其中最常用到的便是ng-model,它为我们明确了需要绑定的属性,虽然在指令中可以通过通过使用独立作用域的”=”来进行双向绑定,但使用ng-model更能简化指令的传值,符合angular的使用习惯。


指令依赖

angular中编写自定义指令是通过require属性来指定查找依赖指令的controller,并传入link函数中进行调用.

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
.directive("..."@H_403_55@,function@H_403_55@(){ return@H_403_55@ { ...@H_403_55@ require@H_403_55@:'ngModel'@H_403_55@,link:function@H_403_55@(scope,elem,attr,ngModelCtr){ ...@H_403_55@ } ...@H_403_55@ } })

所依赖指令的控制器被传入link的第四个参数中,可以依赖多个指令,此时第四个参数则是个数组。

require@H_403_55@:['^?form'@H_403_55@,136); Box-sizing: border-Box;">...@H_403_55@],ctrls){
             在查找指令的过程中,如果未找到指令,则会抛出一个编译错误
可以通过加前缀来控制其查找的操作。

前缀 作用
^ 向上查找指令,未找到则报错。
? 未找到,取消报错,将null传到link的第四个参数。

ng-model

使用ng-model前,让我们先简单了解一下ng-model的工作原理。

angular是一个mvvm的框架,其主要就体现在ng-model身上

angular将model和view之间的联系切断,自己内部通过ng-model去实现viewmodel层,具体的细节不表,我们就看下我们要用的部分。

在每个使用ng-model的地方,都会创建一个ngModelController实例,这个实例负责管理存储在模型(由model指定)中的值与元素显示值之间的数据绑定。

ngModelController包含有$@H_403_55@formatters和$@H_403_55@parsers数组,会在每次更新数据绑定是调用

当我们从页面或通过$@H_403_55@setViewValue改变绑定的属性时,会遍历执行$@H_403_55@parsers数组里面的方法,而当我们直接在js里面通过赋值语句修改时,则会调用$@H_403_55@formatters数组。

  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    // line number:25332@H_403_55@ // model -> value@H_403_55@ // Note: we cannot use a normal scope.$watch as we want to detect the following:@H_403_55@ // 1. scope value is 'a'@H_403_55@ // 2. user enters 'b'@H_403_55@ // 3. ng-change kicks in and reverts scope value to 'a'@H_403_55@ // -> scope value did not change since the last digest as@H_403_55@ // ng-change executes in apply phase@H_403_55@ // 4. view should be changed back to 'a'@H_403_55@ $scope@H_403_55@.$watch@H_403_55@(function@H_403_55@ ngModelWatch@H_403_55@()@H_403_55@ {@H_403_55@ var@H_403_55@ modelValue = ngModelGet($scope@H_403_55@); // if scope model value and ngModel value are out of sync@H_403_55@ // TODO(perf): why not move this to the action fn?@H_403_55@ if@H_403_55@ (modelValue !== ctrl.$modelValue@H_403_55@ && // checks for NaN is needed to allow setting the model to NaN when there's an asyncValidator@H_403_55@ (ctrl.$modelValue@H_403_55@ === ctrl.$modelValue@H_403_55@ || modelValue === modelValue) ) { ctrl.$modelValue@H_403_55@ = ctrl.$$rawModelValue@H_403_55@ = modelValue; parserValid = undefined; var@H_403_55@ formatters = ctrl.$formatters@H_403_55@,idx = formatters.length; var@H_403_55@ viewValue = modelValue; while@H_403_55@ (idx--) { viewValue = formatters[idx](viewValue); } if@H_403_55@ (ctrl.$viewValue@H_403_55@ !== viewValue) { ctrl.$viewValue@H_403_55@ = ctrl.$$lastCommittedViewValue@H_403_55@ = viewValue; ctrl.$render@H_403_55@(); ctrl.$$runValidators@H_403_55@(modelValue,viewValue,noop); } } return@H_403_55@ modelValue; }); }];

    上面是angular调用$formatters的地方,它监控了model值的变化,负责model->view。


    实践

      
      
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    <html@H_403_55@ lang@H_403_55@="en"@H_403_55@ >@H_403_55@ head@H_403_55@>@H_403_55@ Meta@H_403_55@ charset@H_403_55@="utf-8"@H_403_55@>@H_403_55@ http-equiv@H_403_55@="X-UA-Compatible"@H_403_55@ content@H_403_55@="IE=edge"@H_403_55@>@H_403_55@ title@H_403_55@>@H_403_55@angular-ngModel-test</title@H_403_55@>@H_403_55@ script@H_403_55@ type@H_403_55@="text/javascript"@H_403_55@ src@H_403_55@="http://cdn.bootcss.com/angular.js/1.5.0-beta.1/angular.js"@H_403_55@>@H_403_55@@H_403_55@script@H_403_55@>@H_403_55@ "text/javascript"@H_403_55@>@H_403_55@ angular.module("testModule"@H_403_55@,[]) .controller("testCtr"@H_403_55@,function@H_403_55@($scope)@H_403_55@{@H_403_55@ }) .directive("testDire"@H_403_55@,102); Box-sizing: border-Box;">()@H_403_55@{@H_403_55@ return@H_403_55@ { restrict:"A"@H_403_55@,require@H_403_55@:"ngModel"@H_403_55@,link:(scope,ngModelCtr)@H_403_55@{@H_403_55@ } } }) @H_403_55@body@H_403_55@ ng-app@H_403_55@="testModule"@H_403_55@ ng-controller@H_403_55@="testCtr"@H_403_55@>@H_403_55@ input@H_403_55@ "text"@H_403_55@ test-dire@H_403_55@ ng-model@H_403_55@="say"@H_403_55@/>@H_403_55@ h1@H_403_55@>@H_403_55@ @H_403_55@{{say@H_403_55@}}@H_403_55@ h1@H_403_55@>@H_403_55@ body@H_403_55@>@H_403_55@ html@H_403_55@>@H_403_55@@H_403_55@

    $@H_403_55@formatters &$@H_403_55@parsers


    $@H_403_55@formatters@H_403_55@

    上面搭建了一个基本的架子,现在我们通过来通过js改变模型值,在$@H_403_55@formatters里面加入一个格式化方法显示页面上。

    改动:@H_403_55@

      
      
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • <!-- html -->@H_403_55@ button@H_403_55@ ng-click@H_403_55@="joke()"@H_403_55@>@H_403_55@窗前明月光button@H_403_55@>@H_403_55@ h1 @H_403_55@</body@H_403_55@>@H_403_55@@H_403_55@
      
      
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    //js@H_403_55@ .directive(()@H_403_55@{@H_403_55@ return@H_403_55@ { restrict:403_55@{@H_403_55@ ngModelCtr.$formatters.push((modelValue)@H_403_55@{@H_403_55@ if@H_403_55@(typeof@H_403_55@ modelValue != "undefined"@H_403_55@){ //返回字符串给view,不改变模型值@H_403_55@ return@H_403_55@ "李白睡的香"@H_403_55@; } }) } } })

    效果图:@H_403_55@

    这里有个很奇怪的现象,两个绑定model的地方显示的值不一样,这是因为input是从ngModelController中获得的返回值显示出来的,这个值在通过$formatters数组时被我拦截下来,返回了另外一个字符串。


    $@H_403_55@parsers@H_403_55@

    我们还可以对界面(view)输入后的值进行处理。

    改动:@H_403_55@

      
      
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • //js .directive(...@H_403_55@ ngModelCtr.$parsers.push(function@H_403_55@(viewValue){ if@H_403_55@(typeof viewValue != "undefined"@H_403_55@){ "我说:"@H_403_55@+viewValue; } }) } } })

    效果图:@H_403_55@


    $@H_403_55@render &$@H_403_55@setViewValue


    $render@H_403_55@

    有的时候,$@H_403_55@formatters数组里面也许会有不止一个方法,这时候为了保证一个最终的显示效果,就应该用到$@H_403_55@render方法
    TIP:$@H_403_55@render总会在$@H_403_55@formatters完成之后调用。@H_403_55@

    重新赋值$render方法,在改变模型值后修改字体颜色。

    改动:@H_403_55@

      
      
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    //js .directive(...@H_403_55@ var h1Elem = document.getElementsByTagName("h1"@H_403_55@)[0@H_403_55@]; ngModelCtr.$render = function@H_403_55@(){ if@H_403_55@(typeof scope.say != "undefined"@H_403_55@){ h1Elem.style.color = "red"@H_403_55@; } } } } })

    结果可以看到,颜色成功改变了,但是输入框没有变化。
    造成这个的原因是因为我们重写了$render方法相当于改写了ng-model从model到view的dom操作,用自己的方式去实现@H_403_55@。


    $@H_403_55@setViewValue@H_403_55@

    的作用是为了在指令中改变ng-model绑定的值,适用于使用了独立作用域的指令(在没有双向绑定属性的情况下,无法通过scope进行赋值@H_403_55@)。

    下面在加载自执行的时候通过指令改变模型值。

    改动:@H_403_55@

      
      
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    //js .directive(...@H_403_55@ ngModelCtr.$setViewValue("hello"@H_403_55@); } } })

    总结

    在指令中,我们可以用通过简单的依赖ng-model去实现angular各种其他插件的兼容(如一些日期控件,富文本编辑器等),更能简化我们的指令代码,避免很多复杂的绑定逻辑,特别要注意的是$@H_403_55@formatters,$@H_403_55@passers,$@H_403_55@render这些都会在初始化时去执行一遍,因此应该根据需要做好判断操@H_403_55@

    转@H_403_55@http://blog.csdn.net/qq_17371033/article/details/49248791

    猜你在找的Angularjs相关文章