信达互联北京网站建设公司全新官网

当前位置:首页 / 新闻中心 / 网络营销

使用 AngularJS 构建 RIA 前端架构实践

文章来源:信达互联 人气:202发表时间:2016-12-20

  首先明确什么是富应用,然后对 Angular 进行简单的了解,然后是我们 Worktile 在这三年里用 AngularJS 的一些经验,包括更好、更快的使用 AngularJS,最后是一些相关资源推荐。

  首先我们明确一下什么是富应用。

  富应用还有一种说法是单页应用,总体来说比普通资讯型网页有更高的交互性,更强大的用户体验。比如下面有一些例子,office360,Worktile,都算是 Web 应用的东西。相比普通网页难在哪儿呢,前端角度来讲,它的界面会非常的复杂。它的复杂就是会有很多区域,很多模块,而且元素之间关联、会有弹窗,还有元素的堆叠。交互会有拖拽、缩放、快捷键……等等。数据展现形式也是多种多样的,对于列表有各种排序规则,对于日期有各种形态,还有复杂 form 表单、元素合规性检查……等。

  在我三年前没有接触 AngularJS 之前也做过一些比较复杂的系统,当时主流是 ExtJS,或者是 Flush 之类的东西。(当然你采用 Flush 已经是另外一个编程模型领域了)无论你怎么做,自己去搭,给我的感觉,最后代码虽然不像面条式的,但很脆弱,就像搭一个纸牌房子的感觉。

  Hello Angular。

  接下来给没有实际使用过 Angular 的同学大概讲一下 Angular 的基础概念,Hello Angular。

  首先引入一个 AngularJS 的脚本,在代码最上面有一个 ng-app,声明,声明这一块开始就由 Angular 托管了。底下这里写双括弧的表达式用来绑定数据层,而且可以在 Input 表单上指定一个 ng-model 做双向绑定,这就是特别简单的 Hello Angular。

  当时选型的时候觉得这个东西酷,很简单,就开始用了。结果用着用着发现产生了这个问题,搞前端的同学学 jQuery 应该知道越了解 jQuery 它的 API,就越觉得学起来很爽。搞后端的 Node.JS 也是这样,但是在学用 Angular 的时候,就感觉学习曲线有些诡异,有时候会有一些曲里拐弯的感觉。

  再讲一下 Angular 的知识点,AngularJS 的构成,数据绑定、Scope、Modules、依赖注入……每个都是一个小概念,看上去挺多的,其实也不用担心,后面会提供一张图给大家分门别类起来,这里就不多赘述了。

  Angular 是 MV* 的框架,有 Model、View 层和 ViewModel。最主要的特点是双向绑定的,双向数据绑定的图是官网的,我做了一下自己理解的注释。大家写自己的 HTML 模板,Angular 进行Complie 编译,编译后 当数据发生变化会动态更新到View层,而当View 层的控件修改了数据,也会同步更新到Model 层,这是Angular 在研发之初最具特色一个特点。

  Angular 的知识点看上去很多,但是每个知识点所要处理的业务还是分得很清晰的。Module 是所有东西的容器,由 Module 管理这些概念。比如在 Module 下可以声明一个 Config 进行模块的预定配置比如路由配置,也可以定义一个数据过滤器 Filter 和自定义组件 Directive。

  使用 AngularJS 的一些经验

  讲完 Angular 概念之后,讲一下用 Angular 怎么用好它。首先要排除 jQuery 的编程方式。因为 Angular 是双向数据绑定的,所以要明白 DOM 结构不是数据结构,数据才是数据结构。最开始的思路转换是最难的,要从数据结构来考虑控件的编写,如果这是一个业务页面的话,它的业务状态有哪些,要基于业务数据模型来编程。如果是交互控件的话,就要基于控件状态有哪些,有多少个交互状态来编程,而不是回到 DOM 的思路去写。

  信达互联

  这张 PPT 是模拟的一个场景,如果要写一个图书馆管理系统,怎么样分解代码。图书馆管理系统肯定有书,书就是一个大的模块,它会有自己的 Template 模板,会有自己的数据展现的转换 Filter。也会有书的读取 DataService,也会有自己的路由。图书馆系统中有用户来借书,那么User 也是一个模块,同样也是这样去分解,每一个大的模块都应该是把的代码组织在自己模块内,用模块去分解,这样的话你的代码会分得比较清晰。

  信达互联

  这是 Book 模块具体的写,Angular.module(Book,[])。它不依赖于任何模块,所以这里就是空的。它可能会有一些静态配置,可能会有一些自己的路由,可能会有自己增删改查的数据请求。会有关于书籍不同的枚举状态,这个书的借还状态,可以写一些 Filter。具体的 Controller,就是页面控制器。

  这里提醒大家一个最开始特别容易忽略的一个地方,Angular.module 如果有中括号的话,它会是声明一个模块。如果这里没有的话,表面是在已有模块上附加上新的代码,这是一个小细节。

  还有一个需要注意的是依赖注入的写法,依赖注入有3种写法,第一种推断式虽然代码写得比较快的时候,但后来如果采用了代码压缩就不能正常工作了。后期把所有代码改写成注解方式,当然也可以写到内联里。不推荐推断式,不能进行代码压缩,压缩之后会报错。

  说完代码分解到模块里之后,那具体文件应该怎么存放呢。我个人的实践经验就是按照模块集中放,但是要把它打水平,水平放置,目录不要太深。

  信达互联

  还是拿 Book 模块来做例子的话,会把它的文件分散到 service、controllers,具体的 detail,详情页面也会分到 html 模板上,不用展开太多目录层级。这样还有一个好处,使用 SublimeText 时摁快捷键 Ctrl+P 敲入名字就可以快速打开文件。

  有了文件存放方式,有了模块,用户输入UI之后,怎么样让它们串联起来呢。这里就要用到路由组件 ui-router,早期 Worktile 是用官方的 ngRouter。后期出现一些业务需求,要分区域。比如一个页面有 main 主区域,sidenav 子区域。我在访问 book 栏目页时,主区域 main 是显示书籍列表,子区域显示书记分类,采用 ui-router 就能很好的处理这种需求,也能将页面 URL 和 html 模板、controller 控制器串联起来。

  这里讲一将编写 Controller 的注意事项,在 Controller 控制器应该只放置场景代码,一个控制器只负责一小块视图,不要写出万能控制器,不要在 Controller 中考虑重用,当有重用可能,应当考虑是否放到 service。也不操应该作 DOM,DOM 应该由 Directive 驱动。不写数据模型格式化逻辑,应该放到 service 和 Filter 里。最后 Controller 不要基于内存数据通信,而应该用 Angular 官方的广播机制 $emit 或 $broadcast 去通信。

  由于 DOM 是有层级的,但是在 controller 中应该避免 $scope 嵌套混乱,现在 Worktile 做法是所有的数据,包括方法,controller 里都应该放入 $scope.vm 视图模型对象里。而且开发的每一个组件都应该是独立的 isolate scope,确保和外部是有一个隔离的关系。所有数据变化都应该由 cache 层触发,当然不是所有的福应用都有这个 cache 层。因为 Worktile 采用了 WebSocket 长连接,所以有 Cache 层,界面显示数据会优先从 coche 里引用读取,如果coche 需要更新的话,WebSocket 会通知浏览器更新的。而对于 WebSocket 通知系统里产生的各种数据变化消息,我们会有一个订阅 list,各个组件根据需要来订阅数据变化。

  Directive 有一个容易让人迷糊的地方,它的绑定方法,有 link,compile,controller 三种;其实 link 和 compile 是冲突的,link 是 compile 函数返回函数的缩写方式。controller 也可以绑定,但 Angular 建议只有在多个 Directive 公用一个 Controoler 时才这么写,大部分都是写 link 绑定。

  Directive 绑定这里有一些与性能相关的地方,在 Directive 中不同的时机分别使用 compile 和 link。Compile 一般在 DOM 渲染前对DOM 进行操作,并且此时不需要用到 scope 参数。如果想在所有相同 Directive 里共享某些方法和数据,这时应该定义在 compile 里,性能会比较好,link 会执行多次。对特定 element 元素的注册绑定事件会写到 link 函数里,在需要用到 scope 参数时也会用到link函数。

  Directive 里的 restrict,支持4种形式的封装 AECM,分别代表属性Attribute、元素Element、样式Class、注释Comment。在实际编写组件 Directive 是,我们会用 restrict=E 来封装元素性的控件,假如封装一个时间选择器的话而如果是个交互性的组件会用 restrict=A 来封装。一般不建议使用另外两种样式和注释性的组件封装。

  大概总结一下 Angular 框架,虽然 Angular 有很多概念,上手比较困难。但是如果我们用好用准它的概念分而治之,用 Angular 的秩序来包容业务系统的变化,最后达到的效果是非常好的。它会对你的代码进行问题领域。路由层可以用官方的 ngRouteProvider 或者 Angular-ui-router 配置;视图层采用表达式绑定数据,filter 格式化数据显示。通讯层有 http,angular-resource 封装Ajax/REST 请求。各种组件就编写 Directive 来达到交互组件和元素控件重用。

  更好、更快的使用 AngularJS

  再接下来讲一下性能方面的知识点,Worktile 是一个看版,它的元素会非常多。如果有 300个任务时,它的元素会达到 3 千个之多。当时我做性能优化的时候,发现动画是一个很大的 CPU 开销。而 Angular 动画默认是开启全部元素的全部动画,所以如果 DOM 元素特别多的时候,所有元素的添加和删除都会触发到动画。虽然这个动画很快,在元素少的时候这都不是问题,但元素多了这就是一个灾难,所以我发现如果开启了动画元素过滤器之后,让只有样式名叫 wt-animate 才会启用动画效果,性能瞬间优化 20%,这是在元素特别多的时候。还有 CSS3 的动画会比位 css position 的移动画效率高很多,因为它调动浏览器的 GPU。

  其次 DOM 操作是昂贵的,ng-repeat 是展现列表时非常常用的东西。因为 Angular 的脏检查也是考虑 DOM 重用的,但是它无法知道 DOM 是不是可以重用,所以所有 ng-repeat 原则上都要指定 track by 主键。还有 ng-if 优于 ng-show,因为 ng-if 能让子元素子组件懒编译。还有一个是以前 jQuery 中的经验如果你有一个很大的表格,给每个表格 td 上绑一个事件,这个事件绑定的数量是非常可观的,这时可以将事件绑定到表格行 tr 上来优化。最后就是上面提到过得跟数据无关的一些 DOM 操作应该放在 compile 阶段,因为它只执行一次。

  信达互联

  Angular 双向绑定也会带来性能的问题,首先我们可以尽量减少绑定范围,这两个写法达到的效果是一样的。但是这个写法会把绑定的元素绑定到“P”标签里,这里内部还有很多表达式的话也是一个性能灾难。还有对一些需要数据更新的东西,尽量用一次性的绑定的语法来绑定,就是两个冒号{{::bind_once}}。特别是对象的主键,主键肯定不会变。主键变了的话,说明这个对象就应该已经删除了。

  然后就是浏览器的颤动问题,这上面两个和 Angular 没有太多的直接关系,在 jQuery 编程中也是可以优化的,但也是使用中的一些心得。在绑定 resize 和 keydown 时都应该加 debounce 防颤器,在绑定 scroll 事件时要用 throttle 节流阀。还有就是当你在用 ng-repeat 重绘重排时,应该防止重绘重排,先将元素 hide,最后一个 repeat 元素 complie 后再展示出来,能尽量减少浏览器的重绘重排,速度会快很多。还有慎用 ng-mouseenter 和 ng-mouseleave 这两个事件会非常频繁的被触发。

  信达互联

  然后及时 $destroy 时记得回收资源。

  还有是关于双向数据 $digest 的一些性能点,双向绑定基于原理没有这么复杂,它会有一个脏检查,每次脏检查都是在 $digest。因为每一次触发的 $digest 时候,也会触发filter 至少两次,会触发 $watch 一到两次。还有就是不要写特别复杂的 filter 和 watch。要保证 watch 和filter 没有阻塞,单次执行应该足够快。DOM 是很昂贵的东西,不要再 watch 中修改 DOM。不要构造一个很深层次的对象然后 $watch。

  通过设定好 directive 的 priority 优先级,将 DOM 生成的 directive 前置。先让 DOM 生成的控件执行完,把优先级调得很高,最后再把绑定事件的行为组件再去执行,这样的话也会让整个应用性能得到提升。还有如果不触发数据变更的 $timeout,函数后来加一个 true 就会跳过 $digest。

  在对于前端团队如何基于Angular 框架来协作开发,我们团队现在的做法首先把所有Angular 的组件、编码规范、视觉规范全部放在一个DemoCode 网站制作中,方便新的同事来学习和上手。我们还会用看板式API 文档,让前端的同事对接口有一个全局的了解。最后就是一些Angular 推崇的一些工作,比如说代码检查、自动化测试,还有代码打包,一系列东西都用自动化配置起来。

  最后这里给大家推荐一些 Angular 的相关的学习资源,官方网站、AngularUI 的、还有ngNice、还有 Angular 编码规范,非常推荐其实里面不光是编码规范,还有一些最佳实践在里面,非常好的文档推荐大家去看。

  相关推荐:北京网站改版