zoukankan      html  css  js  c++  java
  • angularjs学习总结(快速预览版)

    对html标签的增强 -> 指令

    指令的本质是什么 声明的方式调用相应的脚本,实现一些操作,声明的所在的dom就是脚本的执行上下文?

    自定义标签 -- 标签指令
    自定义属性 -- 属性指令
    特定格式注释 -- 注释指令

    概念
    模板 视图 模型 模块 指令 依赖注入 路由

    > MVVM
    其他MVC框架 backbone emberjs
    Angular不依赖其他任何框架
    AngularJs重新定义了前端应用的开发方式,AngularJs特别适合开发单页面应用(SPA)

    > AngularJs的特性
    1. 双向数据绑定

    2. dom模板
    简单的来说,模板是包含angular指令和表达式的html文件
    html模板---浏览器解析--->dom模板---Angular编译器编译--->动态dom(双向数据绑定)
    因为是dom模板,所以angular可以自定义具有特定行为的标签或属性(指令)


    3. mvc
    model:
    数据,一般是简单的js对象

    viewModel:
    是一个提供特别数据和方法从而维护指定view的对象。viewmodel是$scope的对象,只存在于AnguarJS的应用中。$scope只是一个简单的js对象,这个对象使用简单的API来侦测和广播状态变化。

    controller:
    controller负责设置初始状态和参数化$scope方法用以控制行为。需要指出的controller并不保存状态也不和远程服务互动。

    view:
    view是AngularJS解析渲染和绑定后生成的HTML

    4. 服务和依赖注入
    服务就是对外提供某种功能
    内置DI(依赖注入)系统,自动查找和注入依赖,有利于开发,理解和测试

    //例子1:创建自定义服务,并注入到控制器中
    html template:
    <div ng-controller="myctrl">
    <p ng-click="hi('long time no see, how are you today?');">点击我打个招呼吧</p>
    </div>
    js:
    angular.module('myapp',[]).factory('sayhi',[$window, function(win){
    return function(msg){
    win.alert('hi, sindy!' + msg );
    }
    }]);

    function myctrl(scope,sayhiService){
    scope.hi = function(msg){
    sayhiService.hi(msg);
    };
    }

    myctrl.$inject = ['$scope', 'sayhi'];


    //例子2:视图-控制器-模型的交互
    <html ng-app="myapp">
    ...
    <div ng-controller="demoCtrl">
    <input type="text" ng-model="user.name" disabled="disabled" />
    <a href="#" ng-click="getAjaxUser();">Ajax获取用户名</a>
    </div>
    ...
    js:
    mymodule = angular.module('myapp',[]);
    mymodule.controller('demoCtrl',function($http, $scope){
    $scope. getAjaxUser = function(){
    // $http.get('user.php').success(function(data){ //ok too
    $http.get('user.json').success(function(data){
    $scope.user = data;
    });
    };
    });

    5. scope, module, controller
    scope:
    view和controller都可以访问$scope中保存的数据和方法,所以$scope是view和controller通信的桥梁。
    在mvc结构里,$scope扮演者model的角色,负责提供数据和方法,这些数据和方法是在某个Dom元素范围内可用的。

    每个angular应用都会有一个$rootScope,即可顶级的scope,对应的包含ng-app指令属性的dom元素

    模板表达式 {{}}

    module:
    <html ng-app="myapp">
    var mymodule = angular.module('myapp',[]);

    controller:
    <div ng-controller="myCtrl">{{person.name}}</div>
    ng-controller 指令属性给所在dom元素创建了一个$scope对象,外层元素也有$scope对象,所有的$scope形成作用域链,
    子$scope对象是以原型继承的方式继承自父$scope的,任何属性和方法的访问都是从当前$scope查找--没找到,则在父$scope查找,层层向上遍历的(和js作用域链的查找机制一样)。

    注意:有些指令属性(如:ng-repeat)可以选择性地创建一个独立的scope,让这个scope不继承它的父scope们。

    6. ajax 和 jsonp
    通过注入$http服务来使用ajax的相关方法,如:$http.get(url).success(fn).error(fn);

    7. expression 表达式 ~~模板表达式?
    表达式可以作为指令的值 如:ng-model="person.name" ng-click="showme()"
    标记中使用表达式: {{2+3}} {{2+3|currency}}
    ng的表达式不能使用循环,判断语句,不推荐使用复杂的表达式,表达式中尽量不包含逻辑

    --所有表达式都是在当前scope这个上下文执行,因此可以访问$scope中的变量
    --表达式的执行出现类型错误或引用错误,错误不会被抛出
    --表达式里不允许流程控制语句(if/else)
    --表达式可接受1个或多个串联的过滤器

    8. filter
    filter的作用对数据进行格式化
    {{expresion | filter1 | filter2... }} 前1个filter的输出作为下一个filter的输入

    {{expression | filter:arg1:arg2 }} filter接受参数

    <div ng-repeat=" img in images | filter"></div>
    在js中使用filter,以依赖注入的方式使用。
    mymodule.controller('myCtrl', function($scope, currencyFilter){
    $scope.num = currencyFilter(12345);
    });

    注入多个过滤器
    mymodule.controller('myctrl',function($scope, $filter){
    //...
    })

    ng的内置过滤器:
    number, currency, date
    filter, limitTo, lowercase, uppercse, number
    json, orderBy

    9. 指令
    模板中可以使用的东西包括4种:
    --指令(directive):ng提供的或自定义的标签和属性,用来增强html的表现力(~~个人理解是以声明的方式绑定某种行为)
    --标记(markup): {{}} 可将数据单向绑定到视图
    --过滤器(filter): 用来格式化数据的输出
    --表单控制:用来增强表单验证功能

    ng中指令的使用量是最大的,ng内置了很多指令用来控制模板,如ng-repeat,ng-class,也有很多指令来帮你完成业务逻辑,如ng-controller,ng-model。
    指令的几种使用方式如下:

    --作为标签:<my-dir></my-dir> ~~~注意指令名在js中是 myDir 则在html中是my-dir
    --作为属性:<span my-dir="exp"></span>
    --作为注释:<!-- directive: my-dir exp -->
    --作为类名:<span class="my-dir: exp;"></span>

    其实常用的就是作为标签和属性。

    9.1 样式相关的指令
    ng-class:
    ng-class用来给元素绑定类名,其表达式的返回值可以是以下三种:

    --类名字符串,可以用空格分割多个类名,如’redtext boldtext’;
    --类名数组,数组中的每一项都会层叠起来生效;
    --一个名值对应的map,其键值为类名,值为boolean类型,当值为true时,该类会被加在元素上。

    ng-style:

    ng-show , ng-hide:

    9.2 表单控制相关的指令
    ng-checked 控制radio和checkbox的选中状态
    ng-selected 控制select的选项选中状态
    ng-multiple 控制select多选
    ng-disabled
    ng-readonly
    值都为boolean类型,为true时生效;从数据到模板的单向绑定

    9.2 事件绑定相关的指令
    事件是js中比较重要的一部分内容。
    ng-click
    ng-dblclick
    ng-change

    ng-mousedown
    ng-mouseup
    ng-mouseenter
    ng-mouseover
    ng-mousemove
    ng-mouseleave

    ng-submit


    10. 特殊的ng-src ng-href
    angularjs是在DOMContentLoaded之后才开始解析dom文档的,所以在DOMConetentLoaded之前 src={{url}} href="{{url}}" <p>{{user.name}}</p> 都会明文显示出来,导致链接无效,模板表达式没被内容替换,避免这种情况的方法就是用 ng-src, ng-href, ng-bind

    <img ng-src="url" />
    <a ng-href="url" />

    11. 自定义指令 mymodule.directrive('userInfo', function(){..})

    12. 服务 service
    服务是一个单例对象或函数,对外提供某种功能,服务是模块内可用的,不污染全局环境
    系统内置服务以$开头


    13. 路由
    angular的路由机制是靠ngRoute模块提供的,通过hash和history两种方式实现路由,特性检测后决定采用哪种方式路由
    ngRoute模块包括以下内容:
    --$routeProvider服务用来定义一个路由表,即地址栏与视图模板的映射
    --$routeParams服务保存了地址栏的参数 如:{id:1,name:'tom'}
    --$route服务完成路由匹配,并提供路由相关的服务和事件
    --ngView指令用来在主视图中指定加载子视图的区域

    以上+$location服务就可以完成一个单页面应用了(SPA)


    --引入js文件 angular-route.js
    --注入到根作用域对应的控制器中 var mymodule = angular.module('myapp',['ngRoute']); //node的模块定义 加载其他依赖模块

    --定义路由表 $routeProvider
    when(path, route) otherwise(params)

    核心方法 when(path, route)
    * (string)path 将与 $location.path进行匹配 如需匹配参数冒号+名称 ,如:"/show/:name" 将匹配地址栏的 /show/tom {name:'tome'}被保存到$routeParams中, *进行模糊匹配 如: /show*/:name 将匹配地址栏的 /showinfo/tom

    * (object)route 用于指定path获得匹配后所需的一些配置项 包括
    .. (fn|string)controller 在当前模板上执行的controller函数, 生成新的scope
    .. (string)controllerAs 设置controller的别名
    .. (string|fn)template 视图所用的模板 这部分内容将被ngView引用
    .. (string|fn)templateUrl 当视图模板为单独的html文件或是使用了<script type="text/ng-template">定义模板时使用;
    .. resolve 指定当前controller所以来的模块
    .. redirectTo 重定向的地址

    14. angular动画
    通过css3或js实现,js的实现底层是通过其他js库来实现的

    ng动画效果包括:
    --enter 元素添加到dom中时执行动画
    --leave 元素从dom中删除时执行动画
    --move 移动元素时执行动画
    --beforeAddClass
    --addClass
    --beforeRemoveClass
    --removeClass

    类似加入路由功能
    先引入angular-animate.js
    注入动画模块 var mymodule = angular.module('myapp',['ngAnimate']);
    引入实现js动画效果的js库 如jq

    mymodule.animation('.border-animation', function(){
    return {
    beforeAddClass: function(element, className, done){
    //...
    },
    removeClass: function(element, className, done){
    //...
    }
    }
    });

    -----------------------------------
    Angularjs进阶
    $watch, $apply, $digest, dirty-checking

    > $watch
    <input name="txtUser" type="text" ng-model="user" />
    <input name="txtPass" type="text" ng-model="pass" />
    绑定数据模型$scope.user到dom txtUser, $scope.pass绑定到dom txtPass
    每绑定一些东西到dom中时,就会在$watch队里中增加一条$watch, $watch监视被绑定的2个东西的变化

    每一个绑定到了DOM上的数据都会生成一个$watch,当我们的模版加载完毕时,也就是在linking阶段(Angular分为compile阶段和linking阶段),Angular解释器会寻找每个directive,然后生成每个需要的$watch。

    > $digest
    浏览器收到可以被angular context处理的事件, $digest就会被触发, evalAsync队列 $watch队列
    遍历每条$watch 进行dirty-checking.

    如果当事件触发时,你调用$apply,它会进入angular context,如果没有调用就不会进入

    $apply是我们的$scope(或者是direcvie里的link函数中的scope)的一个函数,调用它会强制一次$digest循环(除非当前正在执行循环,这种情况下会抛出一个异常,这是我们不需要在那里执行$apply的标志)。

    执行$apply:
    element.bind('click', function() {
    scope.foo++;
    scope.bar++;
    scope.$apply();
    });

    更好的使用$apply的方法:
    element.bind('click', function() {
    scope.$apply(function() {
    scope.foo++;
    scope.bar++;
    });
    })

    > 自定义$watch
    ~~~$watch的作用就是监视一个数据模型(如:$scope.name) 当它改变了的话,默认会同步更新跟它($scope.name)绑定的dom, 这里我们可以自定义检测到数据模型更新时 要执行的回调函数。
    /*Controller app.js */
    app.controller('MainCtrl', function($scope) {
    $scope.name = "Angular";
    $scope.updated = -1;
    $scope.$watch('name', function() {
    $scope.updated++;
    });
    });

    /*View index.html*/
    <body ng-controller="MainCtrl">
    <input ng-model="name" />
    Name updated: {{updated}} times.
    </body>


    dirty-checking的执行是很快的

    > 自定义指令详解
    angular通过指令的方式实现了HTML的扩展,增强后的HTML不仅长相焕然一新,同时也获得了很多强大的技能。
    angular的启动过程:
    浏览器解析html=>dom --> angular $compile(查找模板表达式和指令--把指令关联到dom--多个指令按权重排列--执行指令中的complie函数 返回link函数) =>所有指令返回的link函数队列-->执行link函数 连接到scope

    这里注意区别一下$compile和compile,前者是ng内部的编译服务,后者是指令中的编译函数,两者发挥作用的范围不同。

    指令的使用方式和命名:
    --作为标签:<my-dir></my-dir>
    --作为属性:<span my-dir="exp"></span>
    --作为注释:<!-- directive: my-dir exp -->
    --作为类名:<span class="my-dir: exp;"></span>

    关于自定义指令的命名,你可以随便怎么起名字都行,官方是推荐用[命名空间-指令名称]这样的方式,像ng-controller。
    指令命名时用驼峰规则,使用时用-分割各单词。如:定义myDirective,使用时像这样:<my-directive>


    自定义指令的配置参数:
    myModule.directive('namespaceDirectiveName', function(injectables) {

    var directiveDefinitionObject = {

    restrict: string,//指令的使用方式,包括标签,属性,类,注释

    priority: number,//指令执行的优先级

    template: string,//指令使用的模板,用HTML字符串的形式表示

    templateUrl: string,//从指定的url地址加载模板

    replace: bool,//是否用模板替换当前元素,若为false,则append在当前元素上

    transclude: bool,//是否将当前元素的内容转移到模板中

    scope: bool or object,//指定指令的作用域

    controller: function controllerConstructor($scope, $element, $attrs, $transclude){...},//定义与其他指令进行交互的接口函数

    require: string,//指定需要依赖的其他指令

    link: function (scope, iElement, iAttrs) {...},//以编程的方式操作DOM,包

    括添加监听器等

    compile: function(tElement, tAttrs, transclude){

    return: {

    pre: function preLink(scope, iElement, iAttrs, controller){...},

    post: function postLink(scope, iElement, iAttrs, controller){...}

    }

    }//编程的方式修改DOM模板的副本,可以返回链接函数

    };

    return directiveDefinitionObject;

    });

    --指令的表现配置参数:restrict、template、templateUrl、replace、transclude;

    --指令的行为配置参数:compile和link;

    --指令划分作用域配置参数:scope;

    --指令间通信配置参数:controller和require。


    > 指令的解析流程:
    DOMContentLoaded -> ng查找ng-app ->扫描指令(指令属性 指令元素 插值指令{{}} ) -->(根据指令的配置参数)解析指令为dom(或者说转换为dom)[~~生成html] -->顺序执行各指令的complie函数(指令定义时配置的的complie函数) 访问dom并操作dom 返回link函数[~~绑定监听]--> link函数队列,进入link阶段 把view和scope连接起来 [~~关联数据]

    如果指令只进行DOM的修改,不进行数据绑定,那么配置在compile函数中,如果指令要进行数据绑定,那么配置在link函数中。


    > 使用scope为指令划分作用域

      顾名思义,scope肯定是跟作用域有关的一个参数,它的作用是描述指令与父作用域的关系,这个父作用域是指什么呢?想象一下我们使用指令的场景,页面结构应该是这个样子:
    <div ng-controller="testC">
    <say-hello speak="content">美女</say-hello>
    </div>  
    外层肯定会有一个controller,而在controller的定义中大体是这个样子:
    var app = angular.module('MyApp', [], function(){console.log('here')});
    app.controller('testC',function($scope){
    $scope.content = '今天天气真好!';
    }); 

    所谓sayHello的父作用域就是这个名叫testC的控制器所管辖的范围,指令与父作用域的关系可以有如下取值:

    false 默认值。使用父作用域作为自己的作用域
    true 新建一个作用域,该作用域继承父作用域
    javascript对象 与父作用域隔离,并指定可以从父作用域访问的变量

    scope: {
    attributeName1: 'BINDING_STRATEGY',
    attributeName2: 'BINDING_STRATEGY',...
    }  
    键为属性名称,值为绑定策略。等等!啥叫绑定策略?最讨厌冒新名词却不解释的行为!别急,听我慢慢道来。
      先说属性名称吧,你是不是认为这个attributeName1就是父作用域中的某个变量名称?错!其实这个属性名称是指令自己的模板中要使用的一个名称,并不对应父作用域中的变量,稍后的例子中我们来说明。再来看绑定策略,它的取值按照如下的规则:

    @ 传递一个字符串作为属性的值 str : ‘@string’

    = 使用父作用域中的一个属性,绑定数据到指令的属性中 name : ‘=username’

    & 使用父作用域中的一个函数,可以在指令中调用 getName : ‘&getUserName’


    > 指令间的通信参数 controller和require

    使用指令来定义一个ui组件是个不错的想法,首先使用起来方便,只需要一个标签或者属性就可以了,其次是可复用性高,通过controller可以动态控制ui组件的内容,而且拥有双向绑定的能力。当我们想做的组件稍微复杂一点,就不是一个指令可以搞定的了,就需要指令与指令的协作才可以完成,这就需要进行指令间通信。

    想一下我们进行模块化开发的时候的原理,一个模块暴露(exports)对外的接口,另外一个模块引用(require)它,便可以使用它所提供的服务了。ng的指令间协作也是这个原理,这也正是自定义指令时controller参数和require参数的作用。

    controller参数用于定义指令对外提供的接口:
    controller: function controllerConstructor($scope, $element, $attrs, $transclude)
    它是一个构造器函数,将来可以构造出一个实例传给引用它的指令。
    先看controller可以使用的参数,作用域、节点、节点的属性、节点内容的迁移,这些都可以通过依赖注入被传进来,所以你可以根据需要只写要用的参数。

    表示从父节点上寻找,使用起来像这样:require : ‘^directiveName’,如果不加,$compile服务只会从节点本身寻找。另外还可以使用前缀:?,此前缀将告诉$compile服务,如果所需的controller没找到,不要抛出异常。

    > 性能及调优
    AnglarJS很棒,但当处理包含复杂数据结构的大型列表时,其运行速度就会非常慢
    一个与“ng-repeat ”指令有关,另一个与过滤器有关

    AngularJS中的ng-repeat在处理2500个以上的双向数据绑定时速度会变慢。这是由于AngularJS通过“dirty checking”函数来检测变化。每次检测都会花费时间,所以包含复杂数据结构的大型列表将降低你应用的运行速度。

    > 7个调优规则:
    1.渲染没有数据绑定的列表
    数据绑定是性能问题最可能的根源,如果你只想显示一次列表,并不需要更新、改变数据,放弃数据绑定是绝佳的办法。

    2.不要使用内联方法计算数据
    <li ng-repeat="item in filteredItems()"> //这并不是一个好方法,因为要频繁地评估。
    <li ng-repeat="item in items"> //这是要采用的方法

    3.使用两个列表(一个用来进行视图显示,一个作为数据源)

    4.在其他模板中使用ng-if来代替ng-show
    <div ng-if="item.showDetails">
    {{item.details}}
    </div>


    5.不要使用ng-mouseenter、ng-mouseleave等指令
    使用内部指令,像ng-mouseenter,AngularJS会使你的页面闪烁。浏览器的帧速率通常低于每秒30帧。使用jQuery创建动画、鼠标悬浮效果可以解决该问题。确保将鼠标事件放入jQuery的.live()函数中。

  • 相关阅读:
    MongoDB的C#驱动
    在C#使用MongoDB
    MongoDB 主从复制
    MongoDB 索引操作
    MongoDB 分片技术
    Mongodb 与sql 语句对照
    MongoDB命令使用示例
    MongoDB 高级操作
    MongoDB 细说增删查改
    MongoDB 运维技术
  • 原文地址:https://www.cnblogs.com/stephenykk/p/3924096.html
Copyright © 2011-2022 走看看