前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >借助 AngularJS 写优雅的代码

借助 AngularJS 写优雅的代码

作者头像
四火
发布2022-07-18 13:55:11
2.8K0
发布2022-07-18 13:55:11
举报
文章被收录于专栏:四火的唠叨

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

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

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

代码语言:javascript
复制
{name: "sally", price: 30}

现在有这样的 DOM 对象:

代码语言:javascript
复制
<input type="text" value="sally" />
<label>sally</label>

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

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

代码语言:javascript
复制
$("input").val(queryObj.name);

$("label").text(queryObj.name);

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

代码语言:javascript
复制
$("input").keydown(function(){
	var data = $(this).val();
	$("label").text(data);
	queryObj.name = data;
});

可以想象在 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 的属性,至于占位符,和普通的模板机制没有什么区别:

代码语言:javascript
复制
<div ng-app ng-controller="QueryController">
    <input type="text" value="{{queryObj.name}}" />
    <label>{{queryObj.name}}</label>
</div>

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

代码语言:javascript
复制
function QueryController($scope) {
    $scope.queryObj = {name : "sally", price : 30};
}

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

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

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

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

代码语言:javascript
复制
<Alert>
  <p>Error occurs.</p>
</Alert>

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

依赖注入

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

代码语言:javascript
复制
function PhoneListCtrl($scope, $http) {
  $http.get('phones/phones.json').success(function(data) {
    $scope.phones = data;
  });

  $scope.orderProp = 'age';
}

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

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

过滤器

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

代码语言:javascript
复制
{{ "lower cap string" | uppercase }}
{{ 1304375948024 | date:"MM/dd/yyyy @ h:mma" }}

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

代码语言:javascript
复制
<li ng-repeat="phone in phones | filter:query | orderBy:orderProp" class="thumbnail">

事件处理

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

代码语言:javascript
复制
<img ng-src="{{img}}" ng-click="setImage(img)">

相应地,定义 setImage:

代码语言:javascript
复制
$scope.setImage = function(imageUrl) {
    $scope.mainImageUrl = imageUrl;
}

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

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

代码语言:javascript
复制
$scope.$on("DataChange", function (event, msg) {
    $scope.$broadcast("DataChange", msg);
});

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

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

文章未经特殊标明皆为本人原创,未经许可不得用于任何商业用途,转载请保持完整性并注明来源链接 《四火的唠叨》

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档