angular-1.3 之ng-model-options指令
ng-model-options是angular-1.3新出的一个指令,这篇文章就来介绍这个指令的用法.
ng-model-options允许我们控制ng-model何时进行同步. 比如:1.当某个确定的事件被触发的时候 2.在指定的防抖动延迟时间之后,这样视图值就会在指定的时间之后被同步到模型.
为了了解它到底是什么意思,我们从一个最简单的ng-model指令创建的input元素双向数据绑定的栗子开始看起:
eg-0.0
核心代码:
<input type="text" ng-model="name">
<p>Hello {{name}}!</p>
点击查看效果: http://jsfiddle.net/gdjwk5u7/
这是我们都很熟悉的,在angular-1.2版本就可以实现的ng-model双向绑定.
可以看到,它是实时同步更新的,input中每输入一个字,它就立刻同步到数据模型,这是因为,每次输入input,都会触发一个input的事件,然后angular就会执行的$digest循环,直到模型稳定下来.我们不用手动设置任何事件监听来同步更新视图和模型,这样很赞,这就是angular的目的.
然而,由于每次键盘按下,都会触发$digest循环,所以当你在输入input内容的时候,angular不得不处理所有绑定在scope上的watch监听,所以,它执行的效率就取决于你在scope上绑定了多少watch监听,以及这些监听的回调函数是怎样的,这个代价是十分昂贵的.
所以,如果我们能够自己控制$digest的触发,比如当用户停止输入300毫秒后触发,又或者是当input元素失去焦点的时候再触发,那不是更好么? 于是,angular-1.3的ng-model-options就为我们做了这件事.
一. 通过 updataOn 指定同步ng-model的时间
ng-model-options 提供了一系列的选项去控制ng-model的更新.
通过updateOn参数,我们可以定义input触发$digest的事件.举个栗子,我们希望当input失去焦点的时候更新模型,我们只需要按照如下的配置来实现:
eg-1.0
核心代码:
<input
type="text"
ng-model="name"
ng-model-options="{ updateOn: 'blur' }"/>
<p>Hello {{name}}!</p>
在eg-0.0的基础上,我们添加了 ng-model-options="{ updateOn: 'blur' }" 这样一个指令.它告诉angular, 它应该在input触发了onblur事件的时候再更新ng-model,而不是每次按下键盘就立即更新model. 点击查看效果:(maybe需要墙~~~)
http://plnkr.co/edit/URMCoON9qDFnxdlyiDSS?p=preview
如果我们想要保留默认的更新模型事件,另外再给它添加其它触发$digest的事件,我们可以使用一个特殊的事件:default. 可以通过空格分隔的字符串来给它添加多个事件. 下面这段代码能够在输入的时候同步更新模型,并且当input失去焦点的时候,也更新模型.
eg-1.1
核心代码:
<input
type="text"
ng-model="name"
ng-model-options="{ updateOn: 'default blur' }"/>
<p>Hello {{name}}!</p>
点击查看效果:(maybe需要墙~~~)
http://plnkr.co/edit/6VtaJrCIuO5ePfoz8UXA?p=preview
(效果其实不太看不出来的...因为虽然blur的时候它在同步,但是其实输入的时候已经同步完了)
好了,现在我们知道指定更新model的事件是怎么做的了. 接下来让我们看看怎么指定更新的延迟时间.
二. 通过 debounce 延迟模型更新
我们可以通过ng-model-options来延迟模型的更新,以此来降低当用户和模型交互时触发的$digest循环的次数. 这不仅减少了$digest循环的次数,同时也是处理异步数据模型时提升用户体验度的一个好方法.
想象有这样一个元素: input[type="search"] ,每当用户正在输入的时候,数据模型就会更新,并且用最新的字段向后台提交请求.这样是没错的.然而,我们很可能并不想让用户每次按键的时候就立刻更新模型,而是希望当用户输入完了一段有意义的搜索字段以后才更新模型. 在这种情况下,我们正适合使用ng-model-options的 debounce参数. debounce定义了模型更新的延迟毫秒数(需要是整数). 比如刚才提到的这种情况,我们希望当用户停止输入1000毫秒以后再更新模型,(停止输入1000毫秒差不多应该就是输入完了一段有意义的内容了吧).我们可以像下面这样,定义debounce参数的值为1000:
eg-2.0:
核心代码:
<input type="search" ng-model="searchQuery" ng-model-options="{debounce:1000}">
<p>Search results for: {{searchQuery}}</p>
现在,当输入搜索内容的时候,会有1秒的延迟. 点击查看效果:(maybe需要墙~~~)
http://plnkr.co/edit/lpFwWsTvZxMGfHFe38Bk?p=preview
我们还可以做更多的配置: 为指定的事件指定延迟时间. 为不同的事件指定不同的延时,可以通过给debounce属性定义一个json对象来实现: 属性名代表事件名,属性值代表延迟时间.如果某个事件不需要延迟,那么它的属性值就是0.
下面这个栗子实现了这样的模型: 当用户在input里输入的时候,延迟1000毫秒更新模型,但是当input元素失去焦点的时候,立刻更新模型:
eg-2.1:
核心代码:
<input type="search" ng-model="searchQuery" ng-model-options="{updateOn:'default blur',debounce:{default:1000,blur:0}}">
<p>Search results for: {{searchQuery}}</p>
点击查看效果:(maybe需要墙~~~)
http://plnkr.co/edit/yYsfcjW8KVt9ZESQUSB2?p=preview
三. 通过 $rollbackViewValue方法 同步模型和视图
由于我们通过ng-model-options来控制了模型的更新时间,所有,在很多时候,模型和视图就会出现不同步的情况. 举个栗子,我们配置ng-model-options,让input在失去焦点的时候同步数据模型,当用户正在输入内容时,数据模型没有发生更新,所以input的value指向的是模型里真实的值(但是视图上看到的是用户输入的值)
假设在这种情境下,你希望在数据模型更新前把视图上的值回滚到它真实的值.这时,angular提供了一个叫做$rollbackViewValue的方法来为我们同步数据模型到视图. 这个方法会把数据模型的值返回给视图,同时取消所有的将要发生的延迟同步更新事件.
为了解释这个方法,我写了两个demo来感受一下:
eg-3.0
核心代码:
<div class="container" ng-controller="Rollback">
<form role="form" name="myForm2" ng-model-options="{ updateOn: 'blur' }">
<div class="form-group">
<label>执行了 $rollbackViewValue() 方法</label>
<input name="myInput1" ng-model="myValue1" class="form-control" ng-keydown="resetWithRollback($event)">
<blockquote>
<footer>myValue1: "{{ myValue1 }}"</footer>
</blockquote>
<p></p>
</div>
<div class="form-group">
<label>没有执行了 $rollbackViewValue() 方法</label>
<input name="myInput2" ng-model="myValue2" class="form-control" ng-keydown="resetWithoutRollback($event)">
<blockquote>
<footer>myValue2: "{{ myValue2 }}"</footer>
</blockquote>
</div>
</form>
</div>
app.controller('Rollback',function($scope){
$scope.resetWithRollback = function(e){
if(e.keyCode == 27) {
$scope.myForm2.myInput1.$rollbackViewValue();
}
};
$scope.resetWithoutRollback = function(e){
if(e.keyCode == 27){
angular.noop()
}
}
});
点击查看效果:(maybe需要墙~~~) http://plnkr.co/edit/iMY8IqH5f8NLuIAxY8zN?p=preview
按照下图所示的顺序操作:

myValue1使用了$rollbackViewValue()方法,可以回滚文本域里的值和数据模型同步,但是myValue2是不能的.
看一遍这个demo,也就知道了$rollbackViewValue()方法的意思和作用了.
*需要特别注意的一点是,在使用了ng-model-options这种情况下,如果直接修改模型值,有时可能让视图同步,有时却不能,什么意思,看这个栗子:
eg-3.1:
html部分同eg-3.0.
app.controller('Rollback',function($scope){
$scope.resetWithRollback = function(e){
if(e.keyCode == 27) {
$scope.myValue1 = '';
//使用了$rollbackViewValue,总是可以同步视图,清空myValue1值
$scope.myForm2.myInput1.$rollbackViewValue();
}
};
$scope.resetWithoutRollback = function(e){
if(e.keyCode == 27){
//并不是每次都可以成功的同步的,有时可以,有时不可以.
$scope.myValue2 = ''
}
}
});
点击查看运行效果:(maybe需要墙~~~) http://plnkr.co/edit/vve2Xh7LROQLQFa6FFrn?p=preview
在eg-3.0的基础上,我们做了一个小修改,就是按Esc的时候,不是直接回滚视图值到当前的数据模型,而是先设置数据模型为空,然后再回滚视图值.而myValue2,直接设置数据模型为空,不使用回滚.
在demo里多试几次就会发现,在这种情况下,在myValue2的input里按Esc,有时可以同步视图值为空,有时则不能.
所以,在用了ng-model-opitons的时候,如果在模型没有被视图同步之前需要让视图被模型同步,不能简单通过设置模型,必须使用$rollbackViewValue()方法.
翻译参考:EXPLORING ANGULAR 1.3 - NG-MODEL-OPTIONS 以及 https://docs.angularjs.org/api/ng/directive/ngModelOptions (要墙哦~~~)
angular-1.3 之ng-model-options指令的更多相关文章
- ng之自定义指令
最近开始研究并使用angular,今天就来简单讲讲对于ng中自定义指令的一下使用心得吧! 相信用过ng的人都对ng中的指令有所了解,指令,我将其理解为AngularJS操作HTML element的一 ...
- **Apache Options指令详解
http://www.365mini.com/page/apache-options-directive.htm Options指令是Apache配置文件中一个比较常见也比较重要的指令,Options ...
- angular源码分析:$compile服务——指令的编写
这一期中,我不会分析源码,只是翻译一下"https://docs.angularjs.org/api/ng/service/$compile",当然不是逐字逐句翻译,讲解指令应该如 ...
- angular上传获取图片的directive指令
在AngularJS中,操作DOM一般在指令中完成,那么指令是如何实现的呢?指令的作用是把我们自定义的语义化标签替换成浏览器能够认识的HTML标签 一般的事件监听是在对静态的dom绑定事件,而如果在指 ...
- angular报错:angular.min.js:118Error: [ng:areq] http://errors.angularjs.org/1.5.8/ng/areq
报错代码如下: <div ng-controller="HelloAngular"> <p>{{greeting.text}},angular</p& ...
- angular 中 directive中的多个指令
<div ng-controller="ctrl1"> <superman weight length speed>superman</superma ...
- Angular.js实现折叠按钮的经典指令.
var expanderModule=angular.module('expanderModule',[]) expanderModule.directive('expander',function( ...
- [Angular 2] Adding a data model
Instead of add todo as a string, we create a data model: export class TodoModel{ constructor( public ...
- angular.js封装的文件上传指令
今天把最近用到的东西整理一下,直接上代码,需要申请犀牛存储图片,文件 1.html div div img.img-thumbnail.center-block(ng-src="{{ltUp ...
- Angular 2 前端 http 传输 model 对象及其外键的问题
个人随笔,记录问题及思路草稿,非文章性质. 对于设备编辑场景,需要显示设备类型(外键), 前端有如下 TypeScript model(此 model 和后端实体 model 通常相对应) ...
随机推荐
- 转:Ogre的八叉树场景管理器OctreeSceneManager
上面是我绘制的一张图. 关于八叉树场景管理器主要需要关注两个类,其一是松散八叉树的数据结构Ogre::Octree,其二是八叉树场景管理器Ogre::OctreeSceneManager. 下面摘录图 ...
- Uploadify in ASP.Net
和分页类似,文件上传是web开发标配的技能之一.下面介绍Uploadify的配置和使用. 一.配置 首先到Uploadify官网下载,然后在项目中添加相应引用.前台代码如下: 1.jquery.js2 ...
- xml中“ < > ”转义为“ < > ”问题处理
曾经也碰到过类似问题,解决方法是在发送或者解析报文前执行上面的方法将内容转义一下,现在我用dom4j组装如下的报文(报文体中内容传输时加密处理),大致介绍一下上面方法的使用,具体看代码. import ...
- hibernate的批量删除
转自:hibernate的批量删除一般而言,hibernate的批量删除的写法有两种,一种是hibernate内置的批量删除,不过他的批量删除是将每条记录逐一生成删除语句,其效率极低,当然我们可以使用 ...
- Less入门与安装(转)
快速入门 Less 是一门 CSS 预处理语言,它扩充了 CSS 语言,增加了诸如变量.混合(mixin).函数等功能,让 CSS 更易维护.方便制作主题.扩充. Less 可以运行在 Node.浏览 ...
- 【Android】播放音频的几种方式介绍
接下来笔者介绍一下Android中播放音频的几种方式,android.media包下面包含了Android开发中媒体类,当然笔者不会依次去介绍,下面介绍几个音频播放中常用的类: 1.使用MediaPl ...
- 【struts2】拦截器基础
1)拦截器是什么? 拦截器(Interceptor)是Struts2最强大的特性之一,它是一种可以让你在Action执行之前和Result执行之后进行一些功能处理的机制.来回顾一下官方给出的Strut ...
- 下载远程(第三方服务器)文件、图片,保存到本地(服务器)的方法、保存抓取远程文件、图片 将图片的二进制字节字符串在HTML页面以图片形式输出 asp.net 文件 操作方法
下载远程(第三方服务器)文件.图片,保存到本地(服务器)的方法.保存抓取远程文件.图片 将一台服务器的文件.图片,保存(下载)到另外一台服务器进行保存的方法: 1 #region 图片下载 2 3 ...
- 你真的了解字典(Dictionary)吗? C# Memory Cache 踩坑记录 .net 泛型 结构化CSS设计思维 WinForm POST上传与后台接收 高效实用的.NET开源项目 .net 笔试面试总结(3) .net 笔试面试总结(2) 依赖注入 C# RSA 加密 C#与Java AES 加密解密
你真的了解字典(Dictionary)吗? 从一道亲身经历的面试题说起 半年前,我参加我现在所在公司的面试,面试官给了一道题,说有一个Y形的链表,知道起始节点,找出交叉节点.为了便于描述,我把上面 ...
- git经常使用命令和问题
和远程仓库相关的命令: 下载仓库代码:git clone 远程仓库地址 查看远程仓库:git remote -v 加入远程仓库:git remote add origin [url], 当中origi ...