搜索
首页web前端js教程AngularJS实践之使用NgModelController进行数据绑定

前言

在Angular应用中,ng-model指令时不可缺少的一个部分,它用来将视图绑定到数据,是双向绑定魔法中重要的一环。ngModelController则是ng-model指令中所定义的controller。这个controller包含了一些用于数据绑定,验证,CSS更新,以及数值格式化和解析的服务。它不用来进行DOM渲染或者监听DOM事件。与DOM相关的逻辑都应该包含在其他的指令中,然后让这些指令来试用ngModelController中的数据绑定功能。

注意:本篇文章不是对NgModelController文档的说明,而是更偏向实践。下面我将全程带领大家去实现一个自定义指令,并且利用ng-model属性来做双方的数据绑定。

示例

我们的app中使用了一个自定义的指令,名字叫做timeDruation

如下

<div ng-app="HelloApp" ng-controller="HelloController">
 <h1>自定义指令</h1>
 <time-duration ng-model="test"></time-duration>
 <h1>默认指令</h1>
 <input ng-model="test">second
</div>

   


JS代码如下,

angular.module(&#39;HelloApp&#39;, [])
 .directive(&#39;timeDuration&#39;, TimeDurationDirective);
 .controller(&#39;HelloController&#39;, function($scope) {
 $scope.test = 1;
 });

   


我们的示例指令可以做这样一件事,可以指定几个常见的时间单位,并且能够输入数据。最终我们将得到对应的秒数。其功能的截图如下,

AngularJS实践之使用NgModelController进行数据绑定

这里我们特意将test变量分别绑定到我们的自定义指令和默认指令中,以观察其效果。

自定义指令

闲话少叙,下面来看代码

先上指令的模板。从上图中可以看出,指令包含一个输入框一个下拉选择框。

<div class="time-duration">
 <input ng-model=&#39;num&#39;>
 <select ng-model=&#39;unit&#39;>
 <option value="seconds">Seconds</option>
 <option value="minutes">Minutes</option>
 <option value="hours">Hours</option>
 <option value="days">Days</option>
 </select>
</div>

   


模板其实很简单,这里就不多说了。下面我们来看看这个指令的逻辑部分。

function TimeDurationDirective() {
 var tpl = &#39;....&#39;; // 指令模板代码就是上面的内容,这里就不复制了。
  
 return {
 restrict: &#39;E&#39;,
 replace: true,
 template: tpl,
 require: &#39;ngModel&#39;,
 scope: {},
 link: function(scope, element, attrs, ngModelController) {
  var multiplierMap = {
  seconds: 1,
  minutes: 60,
  hours: 3600,
  days: 86400
  };
  var multiplierTypes = [&#39;seconds&#39;, &#39;minutes&#39;, &#39;hours&#39;, &#39;days&#39;];
 
  // TODO
 }
 };
}

   


指令的link方法我们暂时TODO了它。后面会逐步完善。

我先来看看这个指令的定义,其中用到了require声明。简单来说,require的作用就是为这个directive声明一个依赖关系,表明此directive依赖另一个指令的controller属性。

这里稍微说明一下require的衍生用法。

我们可以在require前加上修辞量词,比如,

return {
 require: &#39;^ngModel&#39;
}
 
return {
 require: &#39;?ngModel&#39;
}
 
return {
 require: &#39;?^ngModel&#39;
}

   


     1、^前缀修饰表示允许查找当前指令的父级指令,如果找不到对应指令的controller则抛出一个错误。

     2、?则表示将这个require动作变成一个可选项,意思就是找不到对应指令的controller就算了,不会抛出错误。

     3、当然,我们也可以联合使用这两个前缀修饰。

相对?ngModel,^ngModel我们使用的频率要更加高一点。

比如

<my-directive ng-model="my-model">
 <other-directive></other-directive>
</my-directive>

   


这时,我们在other-directive中使用require: ^ngModel,它将会自动查找my-directive指令声明中的controller属性。

使用NgModelController

当我们声明了require: 'ngModel'之后,在link方法中会注入第四个参数,这个参数就是我们require的那个指令对应的controller。这里就是内置指令ngModel的指控器ngModeController了。

link: function (scope, element, attrs, ngModelCtrl) {
 // TODO
}

   


$viewValue和$modelValue

在ngModelController中有两个很重要的属性,一个叫做$viewValue,一个叫做$modeValue。

这两者的含义官方的解释如下

     $viewValue: Actual string value in the view.

     $modelValue: The value in the model, that the control is bound to.

如果你对上面的官方解释有疑惑的话,我这里给出一种我个人的解释。

$viewView就是指令渲染模板所用的值,而$modelView是在控制器中流通的值。很多时候,这两个值可能是不一样的。

比如你在页面上展示了一个日期,它显示的可能是“Oct. 20 2015”这样的字符串,但是呢,这个字符串在控制器中对应的值可能是一个Javascript的Date对象的实例。

再比如,我们的这个time-duration示例中,$viewValue其实指的是指令模板中num和unit组合出来的值,而$modelValue是HelloAppController中test变量对应的值。

$formatters和$parses

除了$viewValue和$modelValue这两个属性之外,还有两个用来处理他们的方法。分别是$parses和$formatters。

前者的是作用是将$viewValue->$modelValue,后者的作用恰好相反,是将$modelValue->$viewValue。

time-duration指令与外部控制器以及其内部的运作如下图,

AngularJS实践之使用NgModelController进行数据绑定

     1、在外部控制器中(即这里的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,然后在指令模板中进行渲染。

// $formatters接受一个数组
// 数组是一系列方法,用于将modelValue转化成viewValue
ngModelController.$formatters.push(function(modelValue) {
 var unit = &#39;minutes&#39;, num = 0, i, unitName;
 modelValue = parseInt(modelValue || 0);
  
 for (i = multiplierTypes.length-1; i >= 0; i--) {
 unitName = multiplierTypes[i];
 
 if (modelValue % multiplierMap[unitName] === 0) {
  unit = unitName;
  break;
 }
 }
  
 if (modelValue) {
 num = modelValue / multiplierMap[unit];
 }
 
 return {
 unit: unit,
 num: num
 };
});

   


最后返回的对象就是$viewValue的value。(当然$viewValue还会有其他的一些属性。)

第二步,我们调用$render方法将$viewValue渲染到指令模板中去。

// $render用于将viewValue渲染到指令的模板中
ngModelController.$render = function() {
 scope.unit = ngModelCtrl.$viewValue.unit;
 scope.num = ngModelCtrl.$viewValue.num;
};

   


第三步,我们通过$watch来监控指令模板中num和unit变量。当其发生变化时,我们需要更新$viewValue。

scope.$watch(&#39;unit + num&#39;, function() {
// $setViewValue用于更新viewValue
 ngModelController.$setViewValue({
 unit: scope.unit,
 num: scope.num
 });
});

   


第四步,我们通过$parsers将$viewValue->$modelValue。

// $parsers接受一个数组
// 数组是一系列方法,用于将viewValue转化成modelValue
ngModelController.$parsers.push(function(viewValue) {
 var unit = viewValue.unit;
 var num = viewValue.num;
 var multiplier;
 
 multiplier = multiplierMap[unit];
 
 return num * multiplier;
});

   

更多AngularJS实践之使用NgModelController进行数据绑定相关文章请关注PHP中文网!


声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
超越浏览器:现实世界中的JavaScript超越浏览器:现实世界中的JavaScriptApr 12, 2025 am 12:06 AM

JavaScript在现实世界中的应用包括服务器端编程、移动应用开发和物联网控制:1.通过Node.js实现服务器端编程,适用于高并发请求处理。2.通过ReactNative进行移动应用开发,支持跨平台部署。3.通过Johnny-Five库用于物联网设备控制,适用于硬件交互。

使用Next.js(后端集成)构建多租户SaaS应用程序使用Next.js(后端集成)构建多租户SaaS应用程序Apr 11, 2025 am 08:23 AM

我使用您的日常技术工具构建了功能性的多租户SaaS应用程序(一个Edtech应用程序),您可以做同样的事情。 首先,什么是多租户SaaS应用程序? 多租户SaaS应用程序可让您从唱歌中为多个客户提供服务

如何使用Next.js(前端集成)构建多租户SaaS应用程序如何使用Next.js(前端集成)构建多租户SaaS应用程序Apr 11, 2025 am 08:22 AM

本文展示了与许可证确保的后端的前端集成,并使用Next.js构建功能性Edtech SaaS应用程序。 前端获取用户权限以控制UI的可见性并确保API要求遵守角色库

JavaScript:探索网络语言的多功能性JavaScript:探索网络语言的多功能性Apr 11, 2025 am 12:01 AM

JavaScript是现代Web开发的核心语言,因其多样性和灵活性而广泛应用。1)前端开发:通过DOM操作和现代框架(如React、Vue.js、Angular)构建动态网页和单页面应用。2)服务器端开发:Node.js利用非阻塞I/O模型处理高并发和实时应用。3)移动和桌面应用开发:通过ReactNative和Electron实现跨平台开发,提高开发效率。

JavaScript的演变:当前的趋势和未来前景JavaScript的演变:当前的趋势和未来前景Apr 10, 2025 am 09:33 AM

JavaScript的最新趋势包括TypeScript的崛起、现代框架和库的流行以及WebAssembly的应用。未来前景涵盖更强大的类型系统、服务器端JavaScript的发展、人工智能和机器学习的扩展以及物联网和边缘计算的潜力。

神秘的JavaScript:它的作用以及为什么重要神秘的JavaScript:它的作用以及为什么重要Apr 09, 2025 am 12:07 AM

JavaScript是现代Web开发的基石,它的主要功能包括事件驱动编程、动态内容生成和异步编程。1)事件驱动编程允许网页根据用户操作动态变化。2)动态内容生成使得页面内容可以根据条件调整。3)异步编程确保用户界面不被阻塞。JavaScript广泛应用于网页交互、单页面应用和服务器端开发,极大地提升了用户体验和跨平台开发的灵活性。

Python还是JavaScript更好?Python还是JavaScript更好?Apr 06, 2025 am 12:14 AM

Python更适合数据科学和机器学习,JavaScript更适合前端和全栈开发。 1.Python以简洁语法和丰富库生态着称,适用于数据分析和Web开发。 2.JavaScript是前端开发核心,Node.js支持服务器端编程,适用于全栈开发。

如何安装JavaScript?如何安装JavaScript?Apr 05, 2025 am 12:16 AM

JavaScript不需要安装,因为它已内置于现代浏览器中。你只需文本编辑器和浏览器即可开始使用。1)在浏览器环境中,通过标签嵌入HTML文件中运行。2)在Node.js环境中,下载并安装Node.js后,通过命令行运行JavaScript文件。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
4 周前By尊渡假赌尊渡假赌尊渡假赌

热工具

MinGW - 适用于 Windows 的极简 GNU

MinGW - 适用于 Windows 的极简 GNU

这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

将Eclipse与SAP NetWeaver应用服务器集成。

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

Dreamweaver Mac版

Dreamweaver Mac版

视觉化网页开发工具

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版