简述AngularJS相关的一些编程思想

 

  这篇文章主要介绍了AngularJS相关的一些编程思想,AngularJS是一款热门的JavaScript库,推荐!需要的朋友可以参考下

  在过去的几个月里,我一直遨游于Angular的世界。如今回想起来,很难想象在没有类似于Angular.js, Backbone.js以及其伙伴Underscore.js这些数据绑定框架下我每天如何去编写一个大型前端应用。我不敢相信我已经用它们完成了那件工作。

  可能我有点小偏见,但考虑到我一直在做的应用是在浏览器中实现Photoshop类型的编辑器,它呈现相同的数据有几种完全不一样的方式。

  图层以图形化的形式呈现,占据了屏幕的大部份。它们列于一个面板内,你可以删除它们。

  当你选中一个图层时,它的边缘会被虚线包围,同时会高亮显示于列表中。

  类似地,图层在面板中的尺寸和它们的大小这些属性取决于画布。

  我上面提到过的面板是可以拖拽,折叠,关闭的。

  如果不是一个像Augular的框架,这一种类的互动、数据连接和视图同步很容易变成一个持续的噩梦。有能力修正一个地方的模型和用Augular修正所有相关的视图听起来几乎像在骗人。添加、消除或者改动一个层次只是一个改变对象的问题。层次,x+=10,完成。并没有地方需要手动作废视图、手工地修改在DOM的层次中的每一个实例,甚至是因为这个问题而去与DOM互动。

  Augular使我们可以去到我们从未想过的地方,像设置一串使我们能够在现有的环境下做出申请的键盘捷径。举个例子,文件编辑捷径(像?B:用于切换黑体文本)只是使我们能够编辑一个文件层面。


  同样地,我们为这些快捷键附加了一个描述(通过一个我们创建的服务进行注册),然后我们可以显示一个快捷键的列表,同时还有它们的描述,在一个便利条上。此外,我们写了一个指令使得我们可以将单独的DOM元素与它们的快捷键绑定在一起,当你的鼠标在元素上停留一会,会出现一个提示,让你知道此时可用的快捷键。

  Angular可以使我们做到我们做梦也想不到的事情。

  老实说,这就好像我们已经不是在编写一个web应用。web只是媒介。当我们增进了我们对Angular的理解后,代码变得更加模块化,更加独立,并且更加连接交互。它很自然地变得更加Angular了。

  然后通过Augular,我的意思是在Augular背后的那些高度互动的丰富的应用开发哲学。javascript,一个让我们能够开发那些一段时间前我们还觉得不可能的一部分软件的相似的东西。


  我们甚至有能力去开发一个成熟的用于修改DOM变成历史中现在选中的点的历史控制板,并让它工作得很好。至少可以这么说,当你兴奋的返回历史控制板查看那些与Augular能力相关的数据在你的视图工作中完美的更新每一个微小的细节。

  那并不总是容易的,基本代码总是变成一场无可控制的混乱。

  的确,在过去几周里我们一直在更新并且将我们的前端整个架构重写。在我们开始重新编写以前,看一下自从0.10.6以来,将Angular更新得有优势的过程。如果看了变更日志,你就知道这是一个相当长的过程。

  在这个重构的过程里,我们从以错误的方法对待Angular,转变为以Angular的方式对待Angular。

  在我们的案例中,错误的方法包含了许多的问题,我们不得不在此时,在使我们的代码基础到达可爱状态之前,解决它们。

  在全局作用域声明控制器(Controllers)

 

  这是一个 Angular 初学者容易做的例子。如果你熟悉 Angular,你也会熟悉这种模式。

?

1
2
3
4
5
6
7
8
9
10
11

// winds up on window.LoginCtrl ...
var LoginCtrl = function ($scope, dep1, dep2) {
// scope defaults
};
 
LoginCtrl.prototype.resetPassword = function () {
// reset password button click handler
};
 
// more on this one later
LoginCtrl.$inject = ['$scope', dep1', 'dep2'];

        这段代码没有包含在闭包中,或者说,所有的声明都在根作用域,全局的 window 对象上,混蛋啊。用正宗的 Angular 方式来写的话是使用它提供的模块 api ( module API)。但是如你所见,即使是文档和建议步骤任然过时地建议你使用全局作用域:

        这样做,极棒的事情将出现。

?

1
2
3
4

// A Controller for your app
var XmplController = function($scope, greeter, user) {
$scope.greeting = greeter.greet(user.name);
}

       -- Angular.js文档

         使用模块(modules)允许我们以下面的方式重写控制器(controllers):

?

1
2
3
4
5
6
7
8
9
10
11
12

angular.module('myApp').controller('loginCtrl', [
'$scope', 'dep1', 'dep2',
function ($scope, dep1, dep2) {
'use strict';
 
// scope defaults
 
$scope.resetPassword = function () {
// reset password button click handler
};
}
]);

 

  我发现使用 Angular 控制器的漂亮做法是你必须在所有地方使用控制器方法(controller function),因为你需要控器的依赖注入,而且控制器提供了新的作用域,绑定我们从需求到封装我们所有的脚本文件成为自调用函数表达式( self-invoking function expressions),像这样 (function(){})()。

  依赖$injection

  在最早的例子中你可能已经注意到了, 依赖是使用$inject注入的. 另一方面,大部份的模块API, 允许你传入一个函数作为参数, 或者一个包含了依赖的数组作为参数, 其后面跟着一个依赖于这些依赖的函数. 这是在Angular中我不喜欢的一点 , 但这应该是它文档的过错. 在文档中的大部份例子认为你并不需要一个数组形式的参数; 但现实是,你是需要的。 如果你在使用一个压缩器压缩你的代码之前, 没有运行ngmin , 事情将会变得糟糕.

  由于你没有使用数组格式['$scope',...]明确声明你的依赖包,你看上去简洁的方法参数将会被缩略成类似于b,c,d,e的样子,有效地扼杀了Angular的依赖注入能力。我认为他们构建框架的思路存在了重大的失误,这与我在非常不喜欢 Require.js 和他们麻烦的 AMD 模块最后的推论是相似的。

  如果他不能在产品中使用,它还有什么用?

  我的这种态度是因为你在产品中所使用的框架里,有一部分代码是已经写死了的。这对于开发中经常用到、产品中偶尔用到的实用工具,诸如控制台和错误报告,是很好的。如果语法上的甜头(可读性)只用在开发中,就会变得没有任何意义。

  这些破事让我很愤怒, 现在发泄完了. 谈谈$符吧...

  减少 jQuery扩散

  深入的讲, 这个应用是 "类Angular程序", 也就是说它只是包裹于Angular之中, 大多数DOM 交互是经由jQuery处理的, 这给Angular带来相当多的争论。

  如果今天我要从头开始写一款Angular.js应用,我不会立即包含进jQuery。我会强迫自己使用 angular.element 来代替。

  如果jQuery存在的话,angular.element这个API将包装它,同时它给Angular团队实现 jQuery的API提供了可以替代的选择,名为jqLite。这并不是说 jQuery不好,或者说我们需要另一个某种实现,来映射它们的API。只是因为使用jQuery显得不是那么有Angular的思想。

 

  让我们来看一个具体的,愚蠢的,例子。在controller被声明的地方,它使用jQuery来做元素之上的类操作。

?

1
2
3
4
5
6
7
8
9

div.foo(ng-controller='fooCtrl')
 
angular.module('foo').controller('fooCtrl', function ($scope) {
$('.foo').addClass('foo-init');
 
$scope.$watch('something', function () {
$('.foo').toggleClass('foo-something-else');
});
});

然而,我们可以用我们期望的方法来使用Angular,替代之。

?

1
2
3
4
5
6
7

angular.module('foo').controller('fooCtrl', function ($scope, $element) {
$element.addClass('foo-init');
 
$scope.$watch('something', function () {
$element.toggleClass('foo-something-else');
});
});

  最后一行你不能直接,或者通过jQuery来操作DOM(改变属性,增添事件监听器)。你应该使用指令来替代。那篇文章很棒,去读读看。

  如果你仍然jQuery化了,有许多文章可以一读,例如这篇迁移指南,还有我的关于怎样使用jQuery的批判性思考 这篇文章。

  我不是要声明我们准备完全移除 jQuery 。我们有其他更重要的目标,例如,发布我们的产品。这个时候,删除 jQuery 的依赖还是很有意义的。这样做能够使我们的控制器得到简化,我们创建处理 DOM 的指令,使用 angular.element 即使它实际上映射着 jQuery 。

  我们依赖着有点恶心的 jQuery UI,我们当然不只是为了它的对话框而使用它,它还有很多用途。例如,拖动一个列表项然后把它放到一个已排序的列表中,如果不使用 jQuery UI,这将牵涉到一大堆代码。因此,实际上,对于 jQuery UI 来说,并没有真正很好的替代品。拖拽的功能可以通过一个轻量级的拖拽库 angular-dragon-drop 来替代,但是,对于元素排序插件,还是得依赖 jQuery UI 。

  管理代码库

  还有一个我们在迁移中需要解决的问题是整个代码库都挤在一个单一的大文件中。这个文件包含了所有控制器、所有服务、所有指令以及每个控制器的特定代码。我指出一点使得我们可以准确地把每个文件只包含一个组件。目前,我们有很少的文件,却包含了不知一个组件。大多数是因为一个指令使用一个服务来与外界共享数据。

  尽管和 Angular 无关,我们还是把我们的 CSS 样式表(stylesheet)模块化。我们为每个组件中使用的 CSS 类名前面都加上了两个字的前缀。例如, .pn- 作为前缀,代表面板(panel); .ly- 前缀,代表着图层(layer)等等。这样做的直接好处就是,你不需要再费劲地想哪个组件的 CSS 类是怎样的了。因为你已经为它们设置了命名空间,你就很少会重复用到某一个 CSS 类名了。另一个好处就是减少了嵌套,我们以前曾经用 #layoutEditor div.layer .handle div 这样复杂的选择器表达式,而现在,我们只需要 .ly-handle-content 就可以了。深度的嵌套现在只发生在额外的选择器覆盖上,例如 .foobar[disabled]:hover,或者,最坏的情况下,像 .foo-bar .br-baz 。

  下面是一些我们定下的 CSS 类命名规则:

  用两个字符来描述组件名:.ly-、.dd-、.dg-等等

  采用 .ly-foo-barname 来代替嵌套命名 .ly-foo .bar

  避免内联样式,总是使用 CSS 类名。这能够减少不界面的一致性,提高语义解释能力

  不要在 CSS 中使用 ID 来赋值

  在实现了这套面向组件的 CSS 声明方法后,我又想了很久“the class soup way”。

  Angular 强制你写好的代码,但是更深一层说,它强制你去思考。一会儿后,它就像一个服务器端的实现,或者成为一个不堪忍受的“黑客大会”。这些都取决于你这么选择。

  接近完美

 

  让我们来解析一下我们应用程序的各部件的其中之一,层。

?

1
2
3
4
5
6
7
8

div.cv-layer(
ng-repeat="layer in page.layers | reverse",
ap-layer,
ng-mousedown="selectLayer(layer.id)",
ng-mouseup="selectLayer(layer.id)",
ng-dblclick="doubleClickLayer(layer)",
ng-hide="layer.invisible"
)

  这里,我们使用了cv-layer类,也就是说这个元素是canvas组件的一部分(canvas指的使我们绘制层的地方,不要和HTML5canvas混淆)。然后,我们 在foreach类似的循环里面 使用ngRepeat标签来为每一个层的建立一个相似的元素。并且通过一个我们所写的反向的filter来传递,所以,最后一个层位于最上部,而且对用户可见。apLayer标签,其实是为了绘制层的任务所采用的,不论是一个图片,或者是某些文字,HTML,或别的东西。event标签(ng-mousedown, ng-mouseup, ng-dblclick) 仅仅是简单的为事件做代理而用,这些事件将被我们的层选择服务来处理。最后,ngHide这个标签,我想就不必多言了吧。

  这么一大堆功能(译者注:有点夸张了),而Angular成功的使它看上去如此简单,用可读的HTML,从某种程度上就告诉了你它们是怎么回事。更多的是,它使得你可以分解开不同的需要考虑的问题,从而你能够写出来简洁的代码,不需要一次把所有的事情都考虑在内。简而言之,它降低了复杂度(译者注:其实Angular本身就很复杂,呵呵),让复杂变的简单。而让“难以简单度量的问题”,变的可能。

 

  我期待不久会有更多关于Angular代码的文章。特别是,我乐于探讨一些在升级我的代码的时候,所遇到的一些边缘的案例,如何解决其中的问题,同时让其余的部分同样工作。

时间: 2024-12-30 20:05:46

简述AngularJS相关的一些编程思想的相关文章

浅析PHP程序设计中的MVC编程思想_php技巧

PHP的MVC编程思想目前已经被广泛使用于各种大型项目的开发,很多成熟的MVC框架也逐渐被大家所熟知并被广泛应用于各类项目中,比较常见的如ThinkPHP.codeigniter.Symfony.yii.cakePHP等等.本文就来简述一下php的MVC程序设计思想. 一.什么是MVC 简单的说就是将网站源码分类.分层. MVC三个字母的含义:M:Model 模型,负责数据库操作.V:View 视图,负责调用Model调取数据,再调用模板,展示出最终效果.C:Controller 控制器,程序的

Java编程——Java开发必看的编程思想

Java编程思想,Java学习必读经典,不管是初学者还是大牛都值得一读,这里总结书中的重点知识,这些知识不仅经常出现在各大知名公司的笔试面试过程中,而且在大型项目开发中也是常用的知识,既有简单的概念理解题(比如is-a关系和has-a关系的区别),也有深入的涉及RTTI和JVM底层反编译知识.   1. Java中的多态性理解(注意与C++区分) Java中除了static方法和final方法(private方法本质上属于final方法,因为不能被子类访问)之外,其它所有的方法都是动态绑定,这意

C++编程思想1

学了好久的 C++了 发现自己对于C/C++还是没有深入的了解 于是 咬咬牙啃起了 C++编程思想 希望能有所感悟 .. 我以前是直接学C++的对于C不是很了解,然而又是在VC下 学习 所以 没有好好的 去学习 标准C++,直到我 看起C++编程思想  我发现真应该从头再学一遍了  ...   1.定义的声明的区别  : 声明是 声明了标示符的存在 并没有为 其分配空间   ,而定义 是为其分配的一定的存储空间 int * p ;//这是对指针的声明 并且定义 int p;//这是对整形变量的声

学点Java里的编程思想(r12笔记第65天)

   按照自己之前的计划,我觉得得看看关于开发的东西了,因为我对于并发,锁的认知总是有一个局限性,自己也在地铁上做了些功课.有了这个想法,再有拿起书的勇气,那就是一个开始了.    每个圈子都有自己喜爱的图书,就如同Oracle圈子对于Tom的<Oracle编程艺术>,MySQL圈子对于<高性能MySQL>,Java圈子也有自己的,在我的印象中,应该就是<Java编程思想>了.    程序员其实还是容易偏执,在我们的生活中这种例子屡见不鲜,比如php是世界上最好的语言,

Java编程思想重点笔记(Java开发必看)

Java编程思想,Java学习必读经典,不管是初学者还是大牛都值得一读,这里总结书中的重点知识,这些知识不仅经常出现在各大知名公司的笔试面试过程中,而且在大型项目开发中也是常用的知识,既有简单的概念理解题(比如is-a关系和has-a关系的区别),也有深入的涉及RTTI和JVM底层反编译知识.   1. Java中的多态性理解(注意与C++区分) Java中除了static方法和final方法(private方法本质上属于final方法,因为不能被子类访问)之外,其它所有的方法都是动态绑定,这意

算法设计-猜猜我是谁游戏设计编程思想

问题描述 猜猜我是谁游戏设计编程思想 像微软小冰的读心术类似通过程序给出的几个问题选择是否来推出所猜的人,这要用什么数据结构 解决方案 这个是根据语义匹配等算法实现的.

基于PHP的聊天室编程思想

编程|聊天室 1 页面登陆的基本要素你可以在我的竹叶看到登陆 的表单,这里提供了最基本的登陆表单项(1)登陆表单<form method=POST name=chatform action=chat/login.php?action=enter onSubmit="b1_submit();return true;" target="howtodo">(a)聊天表单的名字为chatform,我使用action=enter作为进入聊天室的入口,如果没有这个参

关于继承内部类——java编程思想示例程序分析

编程|程序|继承|示例 关于继承内部类--java编程思想示例程序分析:class Egg2 { protected class Yolk { public Yolk() { System.out.println("Egg2.Yolk()"); } public void f() { System.out.println("Egg2.Yolk.f()"); } } private Yolk y = new Yolk(); public Egg2() { System

在ASP.NET中面向对象的编程思想

asp.net|编程|对象 首先,我们还是来谈一下面向对象的编程思想吧.我想现在的主流编程思想无非两种:结构与面向对象.以前,在ASP中我们完全采用的是结构化思想.现在,asp.net可以完全支持面向对象的编程思想,这不得不说是一个质上的飞跃. 记得我在大约半年前给大家写过一篇<<面向对象从人造地球谈起>>,当时是由于看到一本小说的启发,发现任何东西都可以用面向对象的思想来看.我现在还是简单谈一下吧,面向对象无非就是把世间万物当做一个类,要想使用类做事,就必须创建类的实例.这很好理