借助AngularJS写优雅的代码

开发 前端
接触AngularJS还真有点碰巧,在用JQuery写数据绑定的时候,我被数据对象和DOM之间的同步整烦了,要写一大堆方法绑定和取值/设值的代码逻辑,丑得要死。

接触AngularJS还真有点碰巧,在用JQuery写数据绑定的时候,我被数据对象和DOM之间的同步整烦了,要写一大堆方法绑定和取值/设值的代码逻辑,丑得要死。简单说来,就是:

  1. 数据对象发生变更以后,要及时更新DOM树;
  2. 用户操作改变DOM树以后,要回头更新数据对象

这个问题还是举例来说清楚一些,比如我定义了这样一个queryObj:

  1. {name: "sally", price: 30} 

现在有这样的DOM对象:

  1. <input type="text" value="sally" /> 
  2. <label>sally</label> 

1、queryObj发生变化的时候,这两个DOM对象要及时更新,一个是value需要更新,一个则是标签里面的文本需要更新。

我就得写这样的JQuery设值语句:

  1. $("input").val(queryObj.name); 
  2.  
  3. $("label").text(queryObj.name); 

2、当用户操作改变input里面的值的时候,我也需要同步更新label里面的值,以及queryObj里面的值:

  1. $("input").keydown(function(){ 
  2.     var data = $(this).val(); 
  3.     $("label").text(data); 
  4.     queryObj.name = data; 
  5. }); 

可以想象在DOM对象很多的时候,这种绑定语句和设值语句恶心得令人发指。

就这个问题,第1条对象的变更需要及时刷新到DOM上,有好多办法,underscore.js、mustache之类的,模板+数据绑定嘛,当 然,需要手动调用来更新;但是反过来的第2条,DOM变更需要及时刷新到其它DOM对象上,也要刷回数据对象,我找了一会儿,也没有看见有什么现成的实 现,正火大地准备自己写一个简单的机制,这时Google到了AngularJS的“two way binding”,哈哈,暗爽,这不正是我想要的东西么?

鉴于这不是AngularJS的教程。在此我假设你有AngularJS的基础知识,否则,建议你先阅读AngularJS简单易懂的教程。

双向绑定

不管是MVC还是MVVM,数据绑定的过程总是惹人厌烦的,这样的事情做得越少越好;如果需要数据绑定的逆过程,这样的问题是现有MVC框架所很少考虑到的。AngularJS不但把双向绑定的事情替我做了,而且也避免了特定视图类的定义,直接使用原始的数据对象就好。

还是就上面这个问题,在写HTML标签的时候,增加ng-app和一个ng-controller的属性,至于占位符,和普通的模板机制没有什么区别:

  1. <div ng-app ng-controller="QueryController"
  2.     <input type="text" value="{{queryObj.name}}" /> 
  3.     <label>{{queryObj.name}}</label> 
  4. </div> 

并且定义一个和ng-controller同名的方法,参数名为$scope:

  1. function QueryController($scope) { 
  2.     $scope.queryObj = {name : "sally", price : 30}; 

完毕了,这以后label、input和$scope.queryObj这三者就同步了,DOM变化的时候,其它二者也会被及时更新。这就是AngularJS的双向绑定。我觉得这大概是AngularJS最精华的部分。

AngularJS官网的教程上,还给了这样的说明:

从上面的例子,控制器、模板、数据模型、视图,这几个概念和之间的关系应该已经明晰了。

AngularJS遵循的设计理念,是构建UI应当用声明式的方式来(什么是声明式编程,请参阅我关于编程范型的文章)。值得一提的是,AngularJS引入的directive确实方便扩展了标签集,可以写出DSL样子的代码,非常非常灵活,比如:

  1. <Alert> 
  2.   <p>Error occurs.</p> 
  3. </Alert> 

这其中的Alert就是通过directive实现的自定义的标签,最终可以被解析成具备“警告”样式的html,但是,在对于directive的定义上面,就连官网的例子都是,生写html片段模板代码字符串的,用起来确实让我不够舒服。

依赖注入

依赖注入(Dependency Injection,DI)对于使用过Spring的程序员来说实在是再熟悉不过了,所谓依赖注入,就是把某个过程中注入值的步骤交给外部框架、容器来完成。举例来说,这样的代码:

  1. function PhoneListCtrl($scope, $http) { 
  2.   $http.get('phones/phones.json').success(function(data) { 
  3.     $scope.phones = data; 
  4.   }); 
  5.  
  6.   $scope.orderProp = 'age'

$scope、$http都是需要AngularJS框架传入的服务变量,在此,参数的名字不可随意修改,因为AngularJS是根据它来判定需要依赖注入的。

服务可以自己定义,再利用依赖注入的方式加进来使用,这对于模块化和重用是很有帮助的。

过滤器

AngularJS的表达式功能比较弱,不支持条件判断和流程控制,不过好在支持过滤器,这就一定程度上弥补了这个缺憾。过滤器是个很有趣的特 性,让人想起了管道编程。到这里,开个玩笑,你大概也发现AngularJS真是一个到处抄袭,哦不,是借鉴各种概念和范型的东西,比如依赖注入抄 Spring,标签定义抄Flex,过滤器抄Linux的管道:

  1. {{ "lower cap string" | uppercase }} 
  2. {{ 1304375948024 | date:"MM/dd/yyyy @ h:mma" }} 

既然是管道编程,那么肯定支持迭代地使用管道:

  1. <li ng-repeat="phone in phones | filter:query | orderBy:orderProp" class="thumbnail"> 

事件处理

解耦一定是相对的,在我们使用各种绑定语句把onClick="javascript:xxx"从DOM上拿掉的时候,我们就已经想到,总有一天,写那些DOM事件绑定的语句写烦了,一定还会拿回来:

  1. <img ng-src="{{img}}" ng-click="setImage(img)"> 

相应地,定义setImage:

  1. $scope.setImage = function(imageUrl) { 
  2.     $scope.mainImageUrl = imageUrl

无论是把这个绑定关系拿走还是拿回来,都是有道理的,选择你最倾心的方式。就我而言,我倾向于把同一模块的代码放置在一起,增加可理解性,而不在乎它的组成是DOM声明还是JavaScript解释。

另外,值得一提的是不同controller之间的通信方式,AngularJS推荐的方式是采用事件,具体说,controller是可以嵌套 的,$broadcast会把事件广播给所有子controller,而$emit则会将事件冒泡传递给父controller,$on则是 AngularJS的事件注册函数:

  1. $scope.$on("DataChange", function (event, msg) { 
  2.     $scope.$broadcast("DataChange", msg); 
  3. }); 

但是,这让我颇为不爽,如果我的两个视图在不同的controller内,我还非得要通过事件机制来保持同步的话,如此啰嗦,我还需要AngularJS干嘛?

吐槽归吐槽,AngularJS还是非常值得学习使用的,尤其是其中的双向绑定,用起来真是太爽了。***附加几个有用的链接:

原文链接:http://www.raychase.net/2270

责任编辑:陈四芳 来源: 四火的唠叨
相关推荐

2020-04-03 14:55:39

Python 代码编程

2017-06-26 09:40:50

Python代码写法

2017-07-07 16:57:35

代码Python

2014-08-08 13:40:53

AngularJS模块

2024-06-24 14:19:48

2022-05-24 06:07:48

JShack用户代码

2022-08-01 23:45:23

代码识别项目

2012-07-03 09:59:03

程序员

2017-09-27 16:09:29

代码

2021-01-04 07:57:07

C++工具代码

2024-02-23 08:57:42

Python设计模式编程语言

2022-05-09 14:33:20

代码设计设计模式

2022-03-11 12:14:43

CSS代码前端

2019-09-20 15:47:24

代码JavaScript副作用

2023-07-30 22:25:00

JavaScrip服务端Web

2021-09-08 08:34:37

Go 文档Goland

2018-07-23 08:19:26

编程语言Python工具

2022-03-08 06:41:35

css代码

2024-06-21 09:19:45

代码接口重复请求开发

2024-06-19 10:04:15

ifC#代码
点赞
收藏

51CTO技术栈公众号