angular 零碎
阅读原文时间:2023年07月14日阅读:2

相关链接

作用域

  angular 中作用域的概念是一个亮点,由不同的指令、controller等作用域组成的作用域树就是一个app。简单理解一个controller的作用域就是一个$scope,在此controller下的所有指令的操作都是在此作用域下,ng-click,ng-show/hide/if 等指令的表达式计算就是在此作用域下进行的。作用域的层级结构使其具有了继承的特性,形成了作用域链,子作用域可以访问父作用域中的内容。

双向绑定原理

  angular的双向数据绑定是其核心功能。angular 通过监控能事件改变进行绑定;DOM事件(input改变,点击等),XHR的响应触发回调;浏览器地址变化,计时器触发回调等;如果以上情况没有发生,MV改变的可能性不大;当发生了能引起view或model改变的事件时angular就会从根作用域执行脏循环$digest检查,判断是否有需要改变的地方。脏循环会不止一次的执行,以便将所有的model改变集中在一起去改变view,为的是提高性能。

服务

  所谓服务就是一些可以共用的方法、常量等,注册之后可以在需要使用的地方通过名称进行依赖注入.在运行之前可以通过module进行注册服务

apm = angular.module('apm', ['ngExtend', 'ui.router', 'highcharts-ng']);
//常量 基本页面路径
apm.constant('BASE_PATH', '/asset/views/')
.constant('SUB_ROUTES', 'subroutes/');

  在运行阶段可以通过$provide进行注册,$provide只能在配置阶段注入,所以要在配置阶段保存其引用

apm.config(function ($stateProvider, BASE_PATH, SUB_ROUTES, $controllerProvider, $filterProvider, $requireProvider, $urlRouterProvider, $provide) {
apm.register = {
controller: $controllerProvider.register,
filter: $filterProvider.register,
factory: $provide.factory
};
//具体使用
apm.register.factory('overview_queryTransactions', function (MyChart, $myhttp, CHART_CONSTANT, $rootScope)

  注册服务的方法比较

 

对象种类

可以在配置阶段注入

可以在运行阶段注入

constant

常量值

Y

value

变量值

N

Y

service

构造函数创建新对象

N

Y

factory

工厂函数返回新对象

N

Y

provider

$get工厂函数返回新对象

Y

N

依赖注入

  angular会将依赖的所有模块上的所有服务混入应用级别的单一命名空间内。所以,模块间可以相互依赖,不同模块间的服务可以相互依赖。这有一个问题就是会存在冲突的可能性。在需要使用的地方根据名称注入。对应的每个名字只存在唯一的服务。我们利用这点可以在依赖某模块的同时去覆盖此模块提供的服务。

  注入服务

var c = $injector.get(cfg.chartId, cfg.header);

事件传播机制

  angular的事件传播机制类似DOM中的冒泡与捕获的情形。在子级可以通过$scope.$emit 进行事件冒泡,父级可以收到此事件,父级通过$scope.$broadcast进行广播,所有子级可以收到此事件.

        //监听事件  
        $rootScope.$on(EVENT.MODULE.emit, function (event, data) {  
            $rootScope.$broadcast(EVENT.MODULE.broadcast, data);  
        });  
       //触发事件  
        $scope.$emit(EVENT.CHANGE\_CONDITION.emit, null);        

路由

  angular用于开发单页面应用,路由是必不可少的。angular自带路由模块,比较简单的路由需求是可以满足了。存在一些局限。不支持嵌套路由,一个路由只能对应页面中一个区域。当你遇到这些问题的时候,已经有人帮你解决了,ui-router,目前还没遇到过他不支持的功能;

$urlRouterProvider.when(/^\/?$/, '/app/application/application/application');

    $stateProvider  
        //固定路径配置示例  
        //.state('accountsettings', {//账号设置  
        //    url: '/accountsettings',  
        //    templateUrl: BASE\_PATH + 'account\_settings.html',  
        //    resolve: {  
        //        require: $requireProvider.require('account\_settings'),  
        //    }  
        //})  
        //默认规则配置  
        .state('def', {  
            url: '{url:\[^@\]\*}',//'/{one\_code:\\\\w+}/{two\_code:\\\\w+}/{three\_code:\\\\w+}/{url:\[^@\]\*}',  
            templateUrl: function ($stateParams) {  
                var menu = apm.parseURL($stateParams.url), url = BASE\_PATH + menu.path;  
                return addSuffix(url);  
            },  
            resolve: {  
                require: function ($q, $stateParams) {  
                    return resolve($q, $stateParams.url, \[getDeps($stateParams.url)\]);  
                }  
            }  
        })  
        //子路由  
        .state('def.child', {  
            url: '@/{path:\[^/\]+}{a1:/?}{p1:\[^/\]\*}{a2:/?}{p2:\[^/\]\*}{a3:/?}{p3:\[^/\]\*}{a4:/?}{p4:\[^/\]\*}{a5:/?}{p5:\[^/\]\*}',  
            templateUrl: function ($stateParams) {  
                var url = BASE\_PATH + SUB\_ROUTES + $stateParams.path;  
                return addSuffix(url);  
            },  
            resolve: {  
                require: function ($q, $stateParams) {  
                    return resolve($q, $stateParams.path, \[SUB\_ROUTES + $stateParams.path.split(/\[.\\?\]/)\[0\]\]);  
                }  
            }  
        });  
})

  ui-router 跳转带参数的url api

.state('/search', { //搜索
url: '/search?query',
。。。
$state.go('/search',{query:$scope.searchfield});

异步加载

  angular开发单页面应用的时候不可能一次将所有资源全部加载,通常会整合requirejs;

//配置路由
$stateProvider.state('index', { //首页
url: '/index',
templateUrl: '/index',
resolve: {
require: $requireProvider.require('index')
}
})

angular.module('ngExtend', ['ng', 'ngCookies']).
provider('$require', function rq() {
/**
* 异步加载配置
* @param deps 如果是单个依赖可以直接写名字,多个依赖使用数组,路径根据require配置
* @returns {*}
*/
this.require = function (deps) {
if (angular.isString(deps)) {
deps = [deps];
}
return ['$rootScope', '$q', function ($rootScope, $q) {
var def = $q.defer();
require(deps, function () {
$rootScope.$apply(function () {
def.resolve();
});
});
return def.promise;
}];
};

        this.$get = function () {  
            return this;  
        };  
    }).

  需要手动启动angular

angular.element(document).ready(function () {
//阻止 # 导航
$(document).delegate('a', 'click', function (event) {
var href = $(this).attr('href');
if (href === '#') {
event.preventDefault();
}
});
angular.bootstrap(document, ['apm']);
});

controller之间相互通信

  • 通过上面的事件传播机制

  • 父作用域数据共享

  • url参数传递

      推荐事件传播以及url传递,url传递参数可以刷新

Form验证

   任意元素上(form元素好像不好使)通过ng-form="formname" 指定一个form, 在此元素内的input元素通过指定name属性就可以在绑定到form作用域上

    表单验证,最常使用 ng-minlength,mg-maxlength,ng-pattern="/^\d?$/",表单及单个验证元素上都有 $valid,$invalid,$pristine,$dirty ,select标签 pattern无效,只要选择了option就是验证通过的

更改插值表达式

myMod.config(function($interpolateProvider){
$interpolateProvider.startSymbol(‘[[’);
$interpolateProvider.endSymbol(‘]]’);
})

表达式

// 取值 var modelGetter = $parse($ipt.attr('ng-model'));
// 设值 var modelSetter = modelGetter.assign;
//执行 $scope.$eval

动态编译指令

参考

element.append($compile(html.join(' '))(scope));

测试

测试环境 karma+jasmine 依赖node.js

参考 网页:

    karma+jasmine 配置

       http://blog.jobbole.com/54936/ 

       http://blog.fens.me/nodejs-karma-jasmine/

    karma 插件

        https://www.npmjs.com/browse/keyword/karma-launcher

        http://karma-runner.github.io/0.10/index.html

        https://github.com/karma-runner/grunt-karma

    jasmine

        http://jasmine.github.io/2.3/node.html#section-Configuration

        https://github.com/jasmine/jasmine/wiki

  1、全局安装karma

       npm install -g karma (有可能提示net framework 没有安装,不用管,安装之后验证一下是否成功karma start)

       npm install -g karma-jasmine 

       npm install -g karma-chrome-launcher

   2.jasmine 测试nodejs