前端学习总结(七)Angular.js——以数据交互为核心的前端框架

Angular核心概念

(1)本质:设计动态web应用结构框架。

web应用与传统web系统相区别,web应用能为用户提供丰富的操作,能够随用户操作不断更新视图而不进行url跳转。Angular官方也声明它更适用于开发CRUD应用,即数据操作比较多的应用

(2)核心:对HTML标签的增强

就是使你能够用标签完成一部分页面逻辑,具体方式就是通过自定义标签、自定义属性等,这些HTML原生没有的标签/属性在ng中有一个名字:指令。

(3)是MVC还是MVVM?

官网有提到ng的设计采用了MVC的基本思想,但它并不是MVC,因为在书写代码时确实是在用ng-controller这个指令,但这个controller处理的业务基本上都是与view进行交互,所以angular**更接近MVVM**。

简单介绍一下MVVM:即Model-View-ViewModel,它采用双向绑定(data-binding):View的变动,自动反映在 ViewModel,反之亦然。

具体MVC.MVP,MVVM的比较可以参考这篇博客:
http://www.ruanyifeng.com/blog/2015/02/mvcmvp_mvvm.html

(4)适用于?

AngularJS是一个MV* 框架,最适于开发客户端的单页面应用。如果你要开发的是单页应用,AngularJS就是你的上上之选。Gmail、Google Docs、Twitter和Facebook这样的应用,都很能发挥AngularJS的长处。但是像游戏开发之类对DOM进行大量操纵、又或者单纯需要 极高运行速度的应用,就不适合AngularJS了

(5)工作原理

HTML模板将会被浏览器解析到DOM中, DOM结构成为AngularJS编译器的输入。AngularJS将会遍历DOM模板, 来生成相应的NG指令,所有的指令都负责针对view(即HTML中的ng-model)来设置数据绑定。因此, NG框架是在DOM加载完成之后, 才开始起作用的.

(6)优点

1.引入了依赖注入与双向绑定,不需写大量代码就能实现复杂功能

2.不用像jquery操作复杂的dom代码,只需要改变数据模型就可以

Angular重要特性

(1)数据双向绑定

一个web应用可能包含了80%的代码用来处理,查询和监听DOM。数据绑定使得代码极大的减少,开发者可以更专注于应用的数据交互方面。

在我们使用jQuery的时候,代码中会大量充斥类似这样的语句:var val = (‘#id’).val();(‘#id’).html(str);等等,即频繁的DOM操作(读取和写入),其实我们的最终目的并不是要操作DOM,而是要实现业务逻辑。ng的绑定将让你摆脱DOM操作,只要模板与数据通过声明进行了绑定,两者将随时保持同步,最新的数据会实时显示在页面中,页面中用户修改的数据也会实时被记录在数据模型中。

什么是数据双向绑定?
HTML中呈现的view与AngularJS中的数据是一致的. 修改其一, 则对应的另一端也会相应地发生变化.

下面是一个简单的数据双向绑定的例子(通过ng-app 、 ng-model 和 { {msg } } ):

<body ng-app="app">
<!--绑定下面js定义的controller,MyController的管理边界就是这个div-->
<div ng-controller="MyCtroller">
    <!-- 将变量通过{{}}绑定到html中-->
    <h1>{{msg}}</h1>
    <!-- 通过ng-model也可以绑定模型到html-->
    <input type="text" ng-model="msg"/>
</div>

<script>
angular.module('app',[])//定义module,[]里是它的变量名
            .controller('MyCtroller',function($scope){ //定义控制器,器名,$scope是应用程序所指向的html元素
                  $scope.msg="angular";//6.对scope定义一个变量名
            })
</script>

双向绑定原理:

AngularJS**在$scope变量中使用脏值检查来实现了数据双向绑定。和Ember.js数据双向绑定中动态设施setter和getter不同,脏治检查允许AngularJS监视那些存在或者不存在的变量。**

最简单的说法,50ms为一个心跳,去判断一个controller里所有对象的变化,如果有变化,那么更新相关的元素

详细原理可以参考这篇博客:AngularJS 数据双向绑定揭秘:http://sentsin.com/web/779.html

(2)依赖注入(DI)

什么是依赖注入?

wiki 上的解释是:依赖注入(Dependency Injection,简称DI)是一种软件设计模式,在这种模式下,一个或更多的依赖(或服务)被注入(或者通过引用传递)到一个独立的对象(或客户端)中,然后成为了该客户端状态的一部分

该模式分离了客户端依赖本身行为的创建,这使得程序设计变得松耦合,并遵循了依赖反转和单一职责原则。与服务定位器模式形成直接对比的是,它允许客户端了解客户端如何使用该系统找到依赖

一句话 — 没事你不要来找我,有事我会去找你。

AngularJS 提供很好的依赖注入机制。以下5个核心组件用来作为依赖注入:
value:一个简单的 javascript 对象,用于向控制器传递值(配置阶段)
factory:一个函数用于返回值。在 service 和 controller 需要时创建。通常我们使用 factory 函数来计算或返回值。
service
provider:AngularJS 中通过 provider 创建一个 service、factory等(配置阶段)。Provider 中提供了一个 factory 方法 get(),它用于返回 value/service/factory
constant:constant(常量)用来在配置阶段传递数值,注意这个常量在配置阶段是不可用的。

mainApp.constant("configParam", "constant value");

详细的定义方式可参考:http://www.runoob.com/angularjs/angularjs-dependency-injection.html

AngularJS中service,factory,provider的区别可参考:
http://my.oschina.net/tanweijie/blog/295067

通过依赖注入,ng想要推崇一种声明式的开发方式,即当我们需要使用某一模块或服务时,不需要关心此模块内部如何实现,只需声明一下就可以使用了。在多处使用只需进行多次声明,大大提高可复用性
  比如我们的controller,在定义的时候用到一个$scope参数。

app.controller('testC',function($scope){});

  
如果我们在此处还需操作其他的东西,比如与浏览器地址栏进行交互。我们只需再多添
一个参数$location进去:

app.controller('testC',function($scope,$location){}); 

 
这样便可以通过$location来与地址栏进行交互了,我们仅仅是声明了一下,所需的其他代码,框架已经帮我们注入了。我们很明显的感觉到了这个函数已经不是常规意义上的javascript函数了,在常规的函数中,把形参换一个名字照样可以运行,但在此处若是把$scope换成别的名字,程序便不能运行了。因为这是已经定义好的服务名称。
这便是依赖注入机制。顺理成章的推断,我们可以自己定义模块和服务,然后在需要的地方进行声明,由框架来替我们注入

来看下如何定义一个服务:

app.factory('tpls',function(){
    return ['tpl1','tpl2','tpl3','tpl4'];
}); 

 
看上去相当简单,是因为我在这里仅仅是直接返回一个数组。在实际应用中,这里应该是需要向服务器发起一个请求,来获取到这些模板们。服务的定义方式有好几种,包括使用provider方法、使用factory方法,使用service方法。它们之间的区别暂且不关心。我们现在只要能创建一个服务出来就可以了。我使用了factory方法。一个需要注意的地方是,框架提供的服务名字都是由$开头的,所以我们自己定义的最好不要用$开头,防止发生命名冲突。
定义好一个服务后,我们就可以在控制器中声明使用了,如下:

app.controller('testC',function($scope,tpls){
    $scope.question = questionModel;
    $scope.nowTime = new Date().valueOf();
    $scope.templates = tpls; //赋值到$scope中
    $scope.addOption = function(){
        var o = {content:''};
        $scope.question.options.push(o);
    };
    $scope.delOption = function(index){
        $scope.question.options.splice(index,1);
    };
}); 

此时,若在模板中书写如下代码,我们便可以获取到服务tpls所提供的数据了:
模板:

<a href="javascript:void(0);" target="_blank" rel="nofollow">

AngularJS常用指令整理

1.ng-app: 初始化一个 AngularJS 应用程序。
2.ng-init: 初始化应用程序数据。
3.ng-model: 把数据模型元素值(比如输入域的值)绑定到应用程序。
4.ng-repeat:循环输出指定次数的 HTML 元素,集合必须是数组或对象。
5.ng-controller:绑定控制器。
6.ng-if与ng-show/hide:都是控制dom元素的显示或隐藏,ng-if指令根据表达式的值在DOM中生成或移除一个元素(false为移除,反之生成),ng-show/hide只是隐藏或显示,不移除。
7.ng-submit:在表单提交后执行指定函数。
8.ng-disabled:设置表单输入字段的disabled属性(input, select, 或textarea),ng-disabled中的表达式返回 true 则表单字段被禁用。
9.ng-checked:设置复选框(checkbox)或单选按钮(radio)的 checked 属性, 该属性返回 true,复选框(checkbox)或单选按钮(radio)将被选中。
10.ng-src:绑定文件资源路径
11.ng-href:覆盖原生的 <a> 元素 href 属性。如果在 href 的值中有 AngularJS 代码,则需要使用 ng-href 而非 href。ng-href 指令确保了链接是正常的,即使在 AngularJS 执行代码前点击链接。
12.ng-class:给 HTML 元素动态绑定一个或多个 CSS 类。
13.ng-selected:设置<select>列表中的<option>元素的selected属性,ng-selected属性的表达式返回true则选项被选中
14.ng-change:ng-change 指令用于告诉 AngularJS 在 HTML 元素值改变时需要执行的操作,需要搭配 ng-model 指令使用,不会覆盖原生的 onchange 事件, 如果触发该事件,ng-change 表达式与原生的 onchange 事件都执行。

下面通过一个完整的实例实践一下ng指令:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>AngularJS指令</title>
    <link rel="stylesheet" href="css/foundation.min.css">
    <script src="js/angular.min.js"></script>
    <script src="js/js-AngularJS-04-Instructions.js"></script>
    <style type="text/css">
        .tx {
            width: 100px;
            height: 100px;
        }
    </style>
</head>
<!--1.ng-app 初始化一个 AngularJS 应用程序-->
<body ng-app="myapp">

<!--2.ng-controller 绑定controller-->
<div ng-controller="UserController">
    <!--11.ng-submit 在表单提交后执行指定函数-->
    <form action="#" name="f" ng-submit="register(user)">
        <fieldset>
            <legend>用户信息</legend>
            <!--4.ng-src 绑定文件资源路径,需加{{}}-->
            <!--5.ng-class 给HTML元素动态绑定一个或多个CSS类,前面是样式class名,写在上面的style中,后面的是true就渲染该样式-->
            <!--6. ng-if与ng-show/hide(""里为结果是true或false的值):都是控制dom元素的显示或隐藏(if: false为移除,反之生成显示)而ng-show/hide只是隐藏或显示,不移除-->
            <img ng-src="{{user.img}}"
                 ng-class="{'tx':user.showicon}"
                 ng-if="user.isShow">
            <div>
                姓名
                <!--3.ng-model 绑定数据模型-->
                <input type="text" ng-model="user.uname" required>
                <!--7.ng-checked 设置复选框(checkbox)或单选按钮(radio)的checked属性, 该属性返回 true,复选框(checkbox)或单选按钮(radio)将被选中-->
                性别(单选按钮):
                <input type="radio"
                       ng-checked="user.sex=='1'"
                       name="sex"><input type="radio"
                       ng-checked="user.sex=='0'"
                       name="sex"><br>
                兴趣(复选框):
                <!--9. ng- 的属性值既可以是值,表达式,也可以为函数,通过函数处理的结果的返回值来做属性值,常用的一种技巧-->
                <input type="checkbox" ng-checked="isChecked(1)">音乐
                <input type="checkbox" ng-checked="isChecked(2)">电影
                <input type="checkbox" ng-checked="isChecked(3)">体育
                <input type="checkbox" ng-checked="isChecked(4)">旅游

                <br>
                <!--8.ng-selected 设置<select>列表中的<option>元素的selected属性,ng-selected属性的表达式返回true则选项被选中-->
                职位:
                <select name="" id="">
                    <option value="0" ng-selected="user.job=='0'">--请选择--</option>
                    <option value="1" ng-selected="user.job=='1'">前端</option>
                    <option value="2" ng-selected="user.job=='2'">运维</option>
                </select>
                <!--10.ng-disabled 设置表单输入字段的disabled属性(input, select, 或textarea,button都可以用),ng-disabled中的表达式返回true则表单字段被禁用
                表单里的姓名input里加了required属性,如果不填,按钮会变灰无法提交(这里是用了angular内置的一个属性(元素名.$invalid)得到元素的可用性)-->
                <button type="submit" class="button expand"
                        ng-disabled="f.$invalid">
                    提交
                </button>
            </div>
        </fieldset>
    </form>

    <div>
        <ui class="ul-list ui-list-link ui-list-text ui-list-active ui-border-tb">
            <!--12. ng-repeat 循环输出指定次数的 HTML 元素,集合必须是数组或对象
                              三个内置常用属性:$index(下标从零开始) $first $last-->
            <li ng-repeat="a in list1" class="ui-border-t">
                <h3>{{$index+1+':'+a.title+' '+$first+' '+$last}}</h3>
            </li>
        </ui>
    </div>
</div>

</body>
</html>

所引用的js文件:js-AngularJS-04-Instructions.js

/**
 * Created by chenhaoact on 16/3/14.
 */
angular.module('myapp', []) //1.定义app
    .controller('UserController', function ($scope) { //2.定义controller
        //3.controller中新建对象或变量,常量等
        $scope.user = {
            uname: '  安卓',
            pwd: '',
            sex: '1',
            job: '1',
            hobby: [1, 2, 3],
            img: 'img/android.png',
            showicon: true,
            isShow: true
        };

        //4.定义isChecked函数,结合isChecked属性,通过数组控制多选框的选择情况
        //5.ng- 的属性值既可以是值,表达式,也可以为函数,通过函数处理的结果的返回值来做属性值,常用的一种技巧
        $scope.isChecked = function (n) {  //n是页面传回来的值
            var isok = false;
            for (var i = 0; i < $scope.user.hobby.length; i++) {
                if (n == $scope.user.hobby[i]) {
                    isok = true;
                    break;
                }
            }

            return isok;  //注意函数return的位置
        }

        $scope.register = function (u) {
            console.log(u);  //从页面得到了输入的对象,这样就可以进行各种处理
        }

        //在页面中可通过 ng-repeat 循环输出指定次数的 HTML 元素,集合必须是数组或对象
        $scope.list1 = [
            {title: '标题1',info: 11},
            {title: '标题2',info: 22},
            {title: '标题3',info: 33},
            {title: '标题4',info: 44}
        ];


    });

Angular实现原理

1双向绑定原理

Angular的数据观测采用的是脏检查(dirty checking)机制。每一个指令都会有一个对应的用来观测数据的对象,叫做watcher;一个作用域中会有很多个watcher。每当界面需要更新时,Angular会遍历当前作用域里的所有watcher,对它们一一求值,然后和之前保存的旧值进行比较。如果求值的结果变化了,就触发对应的更新,这个过程叫做digest cycle

脏检查有两个问题

任何数据变动都意味着当前作用域的每一个watcher需要被重新求值,因此当watcher的数量庞大时,应用的性能就不可避免地受到影响,并且很难优化。

当数据变动时,框架并不能主动侦测到变化的发生,需要手动触发digest cycle才能触发相应的DOM 更新。Angular通过在DOM事件处理函数中自动触发digest cycle部分规避了这个问题,但还是有很多情况需要用户手动进行触发。

对于这个问题,Vue.js给出了不一样的解决方法:基于依赖收集的观测机制,有兴趣的话可以研究一下Vue.js。

AngularJS常用插件收集

1 图片视频类
angular-maxonry 图片墙效果插件,可以将图片组织成类似于瀑布流的效果,依赖于jQuery、imageloaded和Masonry
angular-deckgrid 另一个照片瀑布流解决方案
ngImgCrop 图片剪裁工具
ngVideo 播放器,直接播放指定地址的mp4,控制按钮美观度远甩朝内99.99%的视频站
2 输入控件类
ngDraggable 控制元素拖动的控件,Demo
angular-umeditor 百度umeditor的AngularJS扩展,umeditor从界面上讲并不够现代化,但却总有人喜欢它
ngAutocomplete 喜闻乐见的自动补完
textAngular 文本编辑器,更简洁,更漂亮
ngTagsInput 以标签的方式来组织输入
Angular-slider 以拖动方式输入值的控件
Angular Slidezilla 与Angular-slider功能一样,只不过设计风格不一样
3 界面类
ui-bootstrap 官方扩展,在AngularJS中方便的以指令的方式使用Bootstrap
ui-map 用于在页面中集成Google Maps
NG-Grid 官方提供的表格插件,支持表格的主题、排序、直接编辑、多行选择等操作,而且使用非常简单,只需要一行HTML代码,但是,比较难看,适合于不讲究外观但要求功能强大的场合,像后台工具、管理系统之类
angular-table 第三方表格工具,适合于需要对表格进行高度定制的场合
ng-table 在易用性和外观上对上面两个进行折衷的解决方案
AngularUI 上面的ui-bootstrap、ui-map就是它的一部分,官方提供的常用扩展集,除了这两个,还有ui-router、ui-select等,注意,它使用的是Bootstrap 2.x
Adapt-Strap 第三方Bootstrap插件,而且是基于扁平化的Bootstrap 3,更美观
ng-polymer-elements Polymer风格的AngularJS指令,Material Design设计,值得尝试
Angular Loading Bar 可用于在页面顶部增加一个漂亮的进度条
angular-busy 与Angular Loading Bar有点类似,主要用于处理 httpngInfiniteScroll线ngScrollToidngDialogBootstrapAngularTreeview使便jQueryangulargrowl http中收到的警告
angular-truncate 当文字过多过长时,显示部分文字的插件,可以按文字总长度来控制,也可以按单词数量来控制

4 调试工具

Batarang:专门为angular设计的一款调试工具,在chrome插件中心可以进行安装

5 其它工具类
angular-translate AngularJS的i18n扩展
Satellizer 可以方便的在AngularJS中集成第三方账号登陆,支持国际主流社交网站账号,支持协议有OAuth 1.0/2.0
ngStorage 本在存储插件,用于处理localStorage和sessionStorage
ng-csv 导出csv的扩展

三 AngularJS学习资源

(1)AngularJS官网:https://angularjs.org/

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值