小丸子总结angularjs的一些问题

在公司回来,明天就要开启奔波模式啦。

借此缓和的机会,总结一下在公司自学angular之后,可能会面临的一些问题。
加深一下印象。

1.angularjs中的作用域

例子:

<div ng-controller="TestCtrl"> <p>{{name}}</p> <div ng-if="show"> <input type="text" ng-model="name"> </div> </div> <script> function TestCtrl($scope){ $scope.show = true; $scope.name = 'htf'; } </script>

在这段代码中,不管input标签内的值怎么变,p标签的内容始终不会变化。这是因为angular的ng-if,ng-switch,ng-include都会隐式的创建一个新的作用域。

我们知道,js有基本数据类型引用数据类型之分。

当我们传递一个基本类型时,js采用的是值传递,b=a,就是把栈里存放的a数值复制到b里。
当我们传递一个引用类型时,js采用的是引用传递。因为引用类型(相当于c中的结构体)是把所有的属性存放到堆中(因为我们是不能预测它的大小的),把堆的地址存放到栈中。执行b=a的时候,我们把栈中的a的地址赋值给b,这样b和a引用的都是同一块地址,同一批数据,b修改自己的属性的时候,通过a也可以访问到数据的改变。

所以,我们在angular中不通的作用域之间传递时,尽量使用引用类型来传递。
即:

<div ng-controller="OuterCtrl"> <p>{{x}}</p> <div ng-controller="InnerCtrl"> <input type="text" ng-model="x"> </div> </div> <script> function OuterCtrl($scope){ $scope.data = {}; $scope.data.x = 'hello'; } function InnerCtrl($scope){ } </script>

注:ng-ifng-switch,ng-include会产生新的作用域,但是ng-showng-hide就并不会产生新的作用域。不过保险起见,都是用引用类型传值吧。

看到别的大大这么说:(可能是假的,回公司证实一下)
这里还有一个区别,开发者在使用ng-if的时候,angular是不去创建内部的dom结构的。也就是说连dom树终都没有唉~~~
但是ng-switchng-hide是加载了内部html结构,知识在display:none和display:block之间切换而已。

关于javascript作用域,变量类型以及内存的问题

2.angularjs页面中不可以调用其他控制器的方法甚至js原生方法

<p>{{parseInt(55.66)}}<p>

会发现,什么也没有显示。

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

$scope.parseInt = function(x){
    return parseInt(x);
}

就可以显示了。

angularjs是MVC架构的。题目的想法完全与MVC相违背。我们需要的方法我们可以创建服务和指令,注入到我们这个controller里,在这个controller中与页面交互。
这样可以降低耦合,而不是乱作一团。

(ps:事实上我怎么感觉vue.js的代码结构更加清晰更加简单,MVVM的强大。。。)

3.angularjs中的过滤器

http://www.tuicool.com/articles/vmmeQvj

4.factory、service 和 provider 是什么关系?

service调用的factory,factory调用的provider。

factory

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

app.factory('FooService',function(){
    return {
        target: 'factory',sayHello: function(){
            return 'hello ' + this.target;
        }
    }
});

service

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

app.service('FooService',function(){
    var self = this;
    this.target = 'service';
    this.sayHello = function(){
        return 'hello ' + self.target;
    }
});

provider

创建一个可通过 config 配置的 service,$get 中返回的,就是用 factory 创建 service 的内容

app.provider('FooService',function(){
    this.configData = 'init data';
    this.setConfigData = function(data){
        if(data){
            this.configData = data;
        }
    }
    this.$get = function(){
        var self = this;
        return {
            target: 'provider',sayHello: function(){
                return self.configData + ' hello ' + this.target;
            }
        }
    }
});

// 此处注入的是 FooService 的 provider
app.config(function(FooServiceProvider){
    FooServiceProvider.setConfigData('config data');
});

provider创建的服务可以配置.

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

脏检查机制。

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

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

6. AngularJS 中 Controller 之间的通信

在平时的业务实现中,发现有时候后台接受的User数据会在不太能够的controller中用到。

然而我再去发送一次AJAX请求?明明数据我之前已经收到了呀。

这时候我就要通过controller之间数据通信来解决。

  • 1.通过service(因为service都是单例模式的)。
    • 我们对后台的交互都通过service来接收,我们只需要在不通的controller中注入同一个service即可传递数据了。
  • 2.通过父controller。我们知道父controller中的引用类型传递到子controller中还是可以使用不会出错。如果父controller中数据是基本类型呢?子controller使用$scope.$parent.data即可。
  • 3.通过事件传播 。子controller通过$emit向父controller传播,父controller通过$on接收,使用$broadcast来广播。子controller使用$on来接收。
  • 4.传递到rootscope。(没试过)

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

我感觉我们的项目分层就不是太好,有些混乱。
这样怎么样呀~

  • directives //指令们
  • services //公共服务们
  • filters //过滤器们
  • common //公共组件们
    • aModal
      - aModal.html
      - aModalCtr.js
  • tpl
    • login,html
    • loginCtr.js

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

8. 依赖注入服务,原理

服务是单例模式的。

注入在任何controller里可以实现通信。

原理

angularjs通过传入参数的参数名,把它tostring,来获得对应的字符串,然后使用正则表达式,解析出其中的依赖项,再去以来映射中获取那个依赖,实例化,传入。

问题

使用的代码压缩会出现问题怎么解决呢?变成字符串传输。

myApp.controller('myCtrl',['$scope','$http',function($scope,$http){
    ...
}])

或显式inject

myApp.controller('myCtrl',myCtrl);
function myCtrl = ($scope,$http){
    ...
}
myCtrl.$inject = ['$scope','$http'];

9.angular 路由

了解 angular内置的 ngRoute 和插件 ui.router。

项目使用到的是ui.router。

ngRoute是基于url的,ui-router是基于state的(大大说的,具体实现的区别是什么呢??没有研究过)

ui.router更加强大,可以多级路由嵌套。这个在前面的博文中总结过。

使用 ui.router 能够定义有明确父子关系的路由,并通过 ui-view 指令将子路由模版插入到父路由模板的 <div ui-view></div> 中去,从而实现视图嵌套。而在 ngRoute 中不能这样定义,如果同时在父子视图中 使用了 <div ng-view></div> 会陷入死循环。

ngRoute

var app = angular.module('ngRouteApp',['ngRoute']);
app.config(function($routeProvider){
    $routeProvider
        .when('/main',{
            templateUrl: "main.html",controller: 'MainCtrl'
        })
        .otherwise({ redirectTo: '/tabs' });

ui.router

var app = angular.module("uiRouteApp",["ui.router"]);
app.config(function($urlRouterProvider,$stateProvider){
    $urlRouterProvider.otherwise("/index");
    $stateProvider
        .state("Main",{
            url: "/main",templateUrl: "main.html",controller: 'MainCtrl'
        })

10.angular 的缺点有哪些?

  1. 前面的博文有提到说,angular使用脏检查机制,遇到数据量大的情况下,会影响性能。
  2. html是在不停动态渲染生成的。不利于SEO。肯定更不利于移动端了。现在有一种趋势,叫做前端页面静态化。
  3. 前面发现,MVC限制了不同controller之间的通信是那么的困难,九曲十八弯。不过这也是MVC的特点。(我们前端,有必要把页面做得那么笨重,那么复杂吗?有时候简单清晰,没有那么多框架依赖,小而美才是我们前端工程师最应该追求的吧。)

11.如何看待 angular 1.2 中引入的 controller as 语法?

我想说我接触的项目,很多controller都是用了这种语法,我们在controller中把变量给this赋值,我们在视图中就可以访问。再也不需要绑定到$scope上了。

这是什么原理呢?

从源码实现上来看,controllerAs 语法只是把 controller 这个对象的实例用 as 别名在 $scope 上创建了一个属性。

if (directive.controllerAs) {
    locals.$scope[directive.controllerAs] = controllerInstance;
}

原来是这样!这不还是使用了$scope么。

只是这样就避免了ng-if等坑。

使用 controllerAs 会遇到的一个问题是,因为没有注入 $scope,导致 $emit$broadcast$on$watch$scope 下的方法无法使用。这些跟事件相关的操作可以封装起来统一处理,或者在单个 controller 中引入 $scope,特殊对待。

解决了一个坑又出来了一堆新坑。掀桌。

12.angularjs中$apply和$digest区别

  1. $apply接受一个函数,这个函数会被包装到try…catch….块中,所以有异常处理。apply会触发$rootScope实现全范围的digest circle
  2. $digest只能实现自身scope和子scope的 digest circle。

所以ajax请求或者timeout之后当然选择调用$apply了。

相关文章

ANGULAR.JS:NG-SELECTANDNG-OPTIONSPS:其实看英文文档比看中...
AngularJS中使用Chart.js制折线图与饼图实例  Chart.js 是...
IE浏览器兼容性后续前言 继续尝试解决IE浏览器兼容性问题,...
Angular实现下拉菜单多选写这篇文章时,引用文章地址如下:h...
在AngularJS应用中集成科大讯飞语音输入功能前言 根据项目...
Angular数据更新不及时问题探讨前言 在修复控制角标正确变...