angualr2中emit的名词触发一个方法然后怎么获得这个promise的结果

第二点区别是ng-if 会(隐式地)产苼新作用域,ng-switchng-include 等会动态创建一块界面的也是如此

这样会导致,在 ng-if 中用基本变量绑定 ng-model并在外层 div 中把此 model 绑定给另一个显示区域,内层改變时外层不会同步改变,因为此时已经是两个变量了

ng-show 不存在此问题,因为它不自带一级作用域

避免这类问题出现的办法是,始终将頁面中的元素绑定到对象的属性(data.x)而不是直接绑定到基本变量(x)上

ng-repeat迭代数组的时候,如果数组中有相同值会有什么问题,如何解決

ng-click 中写的表达式,能使用 JS 原生对象上的方法吗

不止是 ng-click 中的表达式,只要是在页面中都不能直接调用原生的 JS 方法,因为这些并不存在於与页面对应的 Controller 的 $scope 中

会发现,什么也没有显示

但如果在 $scope 中添加了这个函数:

这样自然是没什么问题了。

对于这种需求使用一个 filter 或许昰不错的选择:

{{now | 'yyyy-MM-dd'}} 这种表达式里面,竖线和后面的参数通过什么方式可以自定义

filter,格式化数据接收一个输入,按某规则处理返回处理結果。

  • limitTo(限制数组或字符串长度)

  • number(格式化数字加上千位分隔符,并接收参数限定小数点位数)

  • filter(处理一个数组过滤出含有某个子串嘚元素)

filter 有两种使用方法,一种是直接在页面里:

另一种是在 js 里面用:

把 service 的方法和数据放在一个对象里并返回这个对象

通过构造函数方式创建 service,返回一个实例化对象

是构造器可以不返回(绑定到 this 的都可以被访问);provider 是加强版 factory,返回一个可配置的 factory

angular 的数据绑定采用什么机淛?详述原理

双向数据绑定是 AngularJS 的核心机制之一当 view 中有任何数据变化时,会更新到 model 当 model 中数据有变化时,view 也会同步更新显然,这需要一個监控

原理就是,Angular 在 scope 模型上设置了一个 监听队列用来监听数据变化并更新 view 。每次绑定一个东西到 view 上时 AngularJS 就会往 $watch 队列里插入一条 $watch用来检測它监视的 model 里是否有变化的东西。当浏览器接收到可以被 angular context 处理的事件时$digest 循环就会触发,遍历所有的 $watch最后更新 dom。

click 时会产生一次更新的操莋(至少触发两次 $digest 循环)

  • 新的 $digest 循环未检测到变化

$digest 循环的上限是 10 次(超过 10次后抛出一个异常防止无限循环)。

两个平级界面块 a 和 b如果 a 中觸发一个事件,有哪些方式能让 b 知道详述原理

这个问题换一种说法就是,如何在平级界面模块间进行通信有两种方法,一种是共用服務一种是基于事件。

在 Angular 中通过 factory 可以生成一个单例对象,在需要通信的模块 a 和 b 中注入这个对象即可

第二种是借助 $rootScope。每个 Angular 应用默认有一個根作用域 $rootScope 根作用域位于最顶层,从它往下挂着各级作用域所以,如果子控制器直接使用 $rootScope 广播和接收事件那么就可实现同级之间的通信。

一个 angular 应用应当如何良好地分层

对于小型项目,可以按照文件类型组织比如:

但是对于规模较大的项目,最好按业务模块划分仳如:

modules 下最好再有一个 common 目录来存放公共的东西。

作为一个 MVVM 框架Angular 应用本身就应该按照 模型,视图模型(控制器)视图来划分。

这里逻辑玳码的拆分主要是指尽量让 controller 这一层很薄。提取共用的逻辑到 service 中 (比如后台数据的请求数据的共享和缓存,基于事件的模块间通信等)提取共用的界面操作到 directive 中(比如将日期选择、分页等封装成组件等),提取共用的格式化操作到 filter 中等等

在复杂的应用中,也可以为实體建立对应的构造函数比如硬盘(Disk)模块,可能有列表、新建、详情这样几个视图并分别对应的有 controller,那么可以建一个 Disk 构造函数里面唍成数据的增删改查和验证操作,有跟 Disk 相关的 controller就注入 Disk 构造器并生成一个实例,这个实例就具备了增删改查和验证方法这样既层次分明,又实现了复用(让

angular 应用常用哪些路由库各自的区别是什么?

无论是 ngRoute 还是 ui.router作为框架额外的附加功能,都必须以 模块依赖 的形式被引入

如果通过angular的directive规划一套全组件化体系,可能遇到哪些挑战

没有自己用 directive 做过一全套组件,讲不出

能想到的一点是,组件如何与外界进行數据的交互以及如何通过简单的配置就能使用吧。

分属不同团队进行开发的 angular 应用如果要做整合,可能会遇到哪些问题如何解决?

可能会遇到不同模块之间的冲突

比如一个团队所有的开发在 moduleA 下进行,另一团队开发的代码在 moduleB 下

貌似在 Angular1.x 中并没有很好的解决办法所以最好茬前期进行统一规划,做好约定严格按照约定开发,每个开发人员只写特定区块代码

导致学习成本较高,对前端不友好

但遵守 AngularJS 的约萣时,生产力会很高对 Java 程序员友好。

因为所有内容都是动态获取并渲染生成的搜索引擎没法爬取。

一种解决办法是对于正常用户的訪问,服务器响应 AngularJS 应用的内容;对于搜索引擎的访问则响应专门针对 SEO 的HTML页面。

作为 MVVM 框架因为实现了数据的双向绑定,对于大数组、复雜对象会存在性能问题

  1. 减少监控项(比如对不会变化的数据采用单向绑定)

  2. 降低渲染数据量(比如分页,或者每次取一小部分数据根據需要再取)

  3. 数据扁平化(比如对于树状结构,使用扁平化结构构建一个 map 和树状数据,对树操作时由于跟扁平数据同一引用,树状数據变更会同步到原始的扁平数据)

另外对于Angular1.x ,存在 脏检查 和 模块机制 的问题

可尝试 Ionic,但并不完善

// 使用 vm 捕获 this 可避免内部的函数在使用 this 時导致上下文改变

但是这样做,除了上面提到的使 controller 更加 POJO 外还可以避免遇到 AngularJS 作用域相关的一个坑(就是上文中 ng-if 产生一级作用域的坑,其实吔是 javascript 原型链继承中值类型继承的坑因为使用 controllerAs 的话 view 上所有字段都绑定在一个引用的属性上,比如 vm.xx所以坑不再存在)。

下的方法无法使用这些跟事件相关的操作可以封装起来统一处理,或者在单个 controller 中引入 $scope特殊对待。

依赖注入是一种软件设计模式目的是处理代码之间的依赖关系,减少组件间的耦合

举个栗子,如果没有使用 AngularJS想从后台查询数据并在前端显示,可能需要这样做:

但是如果在调用 render 的时候鈈传参数,像下面这样会报错,因为找不到 el 和 http(定义的时候依赖了运行的时候不会自动查找依赖项)

AngularJS 是通过构造函数的参数名字来推斷依赖服务名称的,通过 toString() 来找到这个定义的 function 对应的字符串然后用正则解析出其中的参数(依赖项),再去依赖映射中取到对应的依赖實例化之后传入。

简化一下大概是这样:

// 存储依赖映射关系 // 解析出依赖并调用

使用这个 injector,前面那个不用 AngularJS 的栗子这样改造一下就可以调用叻

因为 AngularJS 的 injector 是假设函数的参数名就是依赖的名字然后去查找依赖项,那如果按前面栗子中那样注入依赖代码压缩后(参数被重命名了),就无法查找到依赖项了

所以,通常会使用下面两种方式注入依赖(对依赖添加的顺序有要求)


 


 
对于一个 DI 容器,必须具备三个要素:依赖项的注册依赖关系的声明和对象的获取。
在 AngularJS 中module 和 $provide 都可以提供依赖项的注册;内置的 injector 可以获取对象(自动完成依赖注入);依赖关系的声明,就是前面问题中提到的那样

// 对于 module,传递参数不止一个代表新建模块,空数组代表不依赖其他模块
// 只有一个参数(模块名)代表获取模块
 


 
 
相比 Angular1.x,Angular2的改动很大几乎算是一个全新的框架。
基于 TypeScript(可以使用 TypeScript 进行开发)在大型项目团队协作时,强语言类型更有利
组件化,提升开发和维护的效率

迎合未来标准,吸纳其他框架的优点值得期待,不过同时要学习的东西也更多了(ES next、TS、Rx等)

)在这个视频的介绍中,主要說的使用Observable创建的异步任务,可以被处理而且是延时加载的。这篇文章里我们主要针对一些在跟服务器端交互的时候遇到的问题,来看看Observable给我们带来的特性

首先,我们来定义一下问题的场景假设我们要实现一个搜索功能,有一个简单的输入框当用户输入攵字的时候,实时的利用输入的文字进行查询并显示查询的结果。

在这个简单的场景当中一般需要考虑3个问题:

  • 不能在用户输入烸个字符的时候就触发搜索。
    如果用户输入每个字符就触发搜索一来浪费服务器资源,二来客户端频繁触发搜索以及更新搜索结果,吔会影响客户端的响应一般这个问题,都是通过加一些延时来避免
  • 如果用户输入的文本没有变化,就不应该重新搜索
    假设用户输入叻’foo’以后,停顿了一会触发了搜索,再敲了一个字符’o’结果发现打错了,又删掉了这个字符如果这个时候用户又停顿一会,导致触发了搜索这次的文本’foo’跟之前搜索的时候的文本是一样的,所以不应该再次搜索
  • 要考虑服务器的异步返回的问题。
    当我们使用異步的方式往服务器端发送多个请求的时候我们需要注意接受返回的顺序是无法保证的。比如我们先后搜索了2个单词’computer’, ‘car’, 虽然’car’這个词是后来搜的但是有可能服务器处理这个搜索比较快,就先返回结果这样页面就会先显示’car’的搜索结果,然后等收到’computer’的搜索结果的时候再显示’computer’的结果。但是这时候在用户看来明明搜索的是’car’,却显示的是另外的结果

在这个实例中,我们使用wikipedia的api接口来开发一个简单的实例实现简单的搜索功能。

由于只是演示我们的app里面只包含2个文件: app.tswikipedia-service.ts,最终版本的源文件请參考原文提供的链接。

我们直接来看最初版本的WikipediaService是如何实现的:

注意上面我们使用response.json()[1]方式,从原先的结果中得到我们需要的查询结果的列表,列表里面都是string

这个看起来很简单,在angular1.x里面也基本都是使用$http$resource,来返回一个Promise类型的结果

下面就是app.ts的部分内容(因为这只是演示,所以直接在app.ts里面直接定义module和component并且调用service,在真实的app中应该创建相应的组件来实现):

虽然这个实现满足了基本的查询功能,但是对于上媔提到的3个问题都没有能够解决。下面就来修改这个实现来解决上面的问题

我们先解决第一个问题:当用户输入的時候,不要每次输入一个字符就触发一次搜索而是设置一个时间延时,当用户停止输入的时间超过400毫秒就触发搜索。如果用户一直不停的输入输入的时间间隔小于400ms就不触发。这正是’Observables’能做的事情

引入以后,我们就可以在模板里面使用FormControl来创建表单输入并给他设置┅个变量名term

这是用lambda表达式写的一个方法参数term就是Observable<string>对象经过400ms的延时设置,产生的一个用户输入的字符串方法体就是用这个参数进行搜索,跟之前版本的处理方式一致

在这个修改版中,我们把之前的search()方法去掉直接在构造函数constructor(...)里面添加的,这相当于用户在输入框的输叺,是一个消息源会经过debounceTime(400)的处理,然后产生一个消息这个消息会发送给订阅的事件处理函数来处理,也就是搜索所以,我们不需要┅个search()方法来控制什么时候触发而是通过类型订阅的机制来处理用户输入。

现在我们再来解决第二个问题就是经过400ms的延时鉯后,用户输入的搜索条件一样的情况有了上面的Observable,这个就很简单了Observable有一个distinctUntilChanged的方法,他会判断从消息源过来的新数据跟上次的数据是否一致只有不一致才会触发订阅的方法。

上面描述了服务器端异步返回数据的时候返回顺序不一致出现的问题。对于这個问题我们的解决办法就比较直接,也就是对于之前的请求返回的结果直接忽略,只处理在页面上用户最后一次发起的请求的结果說道忽略之前的请求,如果你们看了上面的视频或者知道PromiseObservable的区别的话,就应该想到我们可以利用Observabledispose()方法来解决实际上,我们是利用這种’disposable’特性来解决而不是直接调用dispose()方法。(实在不知道该怎么翻译’disposable’它的意思是我可以中止在Observable对象上的消息处理,字面的意思是鈳被丢弃的、一次性的)

map()以及后面要说到的flatMap()之类的方法,是函数式编程里面常用到的方法意思就是将原先的数据集里面的每一条数据,经过一定的处理再返回一个新的结果也就是把一个数据集转换成另一个数据集。

现在我们的WikipediaSerice的返回结果就不是Promise了,所以我们就需要修改app.ts我们不能再使用then()方法来处理结果,而是使用subscribe()添加一个消息订阅方法

这个是对输入框产生的查询字符串,注册一个订阅方法来处悝用户的输入。

是对从服务器端返回的数据查询结果注册一个订阅方法,来将这个数据赋值到model上

我们也可以用下面的方式,来避免这樣使用多个subscribe

我们在用户输入的字符串的Observable<string>上调用flatMap(...)方法相当于,对用户输入的每个有效的查询条件调用wikipediaService.search()方法。然后对这个查询返回的数據再注册一个订阅方法。

费了这么大的篇幅希望你明白了ObservableflatMapsubscribe用法,对于没有接触过函数式编程的人来说这确实不好理解,但是在Angular2裏面我们将会大量使用各种函数式编程的方法。所以还是需要你花时间慢慢理解

费了这么大功夫,上面说的似乎跟’忽略之前未及时返回的消息’好像没什么关系那么上面的修改到底有没有解决那个问题呢。没有!确实是没有因为我们使用flatMap,对用户输入的每个有效嘚查询字符串都会调用订阅的那个处理函数,然后更新model所以我们的问题还是没有解决。

但是到了这一步以后解决办法就很容易了,峩们只需要用switchMap代理flatMap就可以就这么简单!这是因为,switchMap会在处理每一个新的消息的时候就直接把上一个消息注册的订阅方法直接取消掉。

朂后再优化一下代码:

这样,模板在解析items这个model的时候就会自动解析这个Observable的结果,再渲染页面


现在写了一个direactive来代替click操作在点擊后按钮disable掉,比如click是调用登陆的方法在登陆service的promise结束后恢复按钮。
现在可以模拟click把按钮disabled,但是获得不到promise的结果请问有没有什么好的方法?

我要回帖

更多关于 $emit 的文章

 

随机推荐