Android_UIangular

玩转angularJS框架

2017-10-13  本文已影响111人  我爱开发

AngularJS

AngularJS概述

Angular图标

介绍

AngularJS 诞生于2009年,由 Misko Hevery 等人创建,后为Google所收购。是一款优秀的前端JS框架,已经被用于Google的多款产品当中。
AngularJS有着诸多特性,最为核心的是:

MVC、模块化(编程)、自动化双向数据绑定、语义化标签、指令、依赖注入等等。
1. Model模型 主要是负责业务数据的处理,前端项目中的表现为js变量
2. View视图 主要是业务数据在用户面前显示和数据的收集,前端项目中的表现为html代码
3. Controller控制器 主要负责是业务数据的curd操作【操作模型里面的数据,调用模型来对数据处理】,协调模型和视图之间的关系,前端项目中的表现为function

Angular的核心特性

原则

优势

使用场景

SPA -单页应用程序

单页Web应用(single page application,SPA),就是只有一个Web页面的应用,
是加载单个HTML页面,并在用户与应用程序交互时动态更新该页面的Web应用程序。

优势

1 ajax请求不会留下历史记录
2 用户无法直接通过URL直接进入指定页面
3 ajax对SEO不友好

劣势

主要技术点

实现思路

实例和参考

AngularJS的基本使用

案例

使用步骤

directive -指令

指令是什么

<input type="text" ng-model="userName">

指令的类型

常用指令

ng-app

ng-app 指令指定了应用的根元素,通常放置在页面的根元素,也可以是任意的元素
例如:body或html标签

应用程序运行时,会自动执行边界内部的其他指令。
标记的范围尽可能小,提高性能

注意:每个页面中可以出现多次 `ng-app` 指令(不推荐!)
如果是多个需要手动引导:`angular.bootstrap()`

ng-click

<button ng-click="val + 1"></button>

ng-model

ng-model指令将尝试把属性绑定到当前作用域中。
如果当前作用域中没有该属性,那么AngluarJS会帮我们隐式创建并且添加到当前作用域中。

ng-init (了解)

expression -表达式

从JS角度,使用运算符和数据 连接起来的有 结果 的代码就是:表达式
注意:不带分号

例如:
可以使用 console.log(); 打印出来, 或者
    console.log( expression );
可以用作 赋值运算符 的右值
    var test = expression;
<p>{{user.name}}</p>
<p>{{1 + 8}}</p>
<p>{{"hello" + "world"}}</p>

<div ng-click="sayHi()"></div>

AngularJS的执行过程分析

<body ng-app>
    <input type="text" ng-model="user.name" />
    <p>Hello {{user.name}}</p>
</body>

执行过程说明

案例强化

查看AngularJS的文档

离线文档和在线文档

module -模块

模块是一个容器包含了应用程序的不同组成部分,并且这些内容必须要依附于一个模块
    例如:controllers, services, filters, directives, configs 等

模块是应用程序的组成单元,例如:登录模块、注册模块、商品列表模块 等,这些模块
组合在一起构成了一个完整的应用程序。

创建模块

// 第一个参数:模块名称,字符串
// 第二个参数:数组,用来添加当前模块的依赖项
var app = angular.module("firstApp", ["otherModuleName"]); 

获取模块

controller -控制器

创建控制器

app.controller("DemoController", function($scope) {
    // $scope 相当于当前的数据模型
});

控制器的作用

$scope的说明

1 ng 在使用的时候,页面中只要有 ng-app 就会创建一个 scope,名字是:$rootScope
2 $scope 是 HTML(视图)背后的“男人” ---->
    视图:女人,负责美(展示)
    $scope:男人,负责提供美的资源(数据)
3 所有的控制器都继承自 $rootScope 
4 继承是按照:原型式继承 来实现
5 对于HTML来说,参照原型式继承:子节点继承自父节点

数据绑定方式

简介

双向数据绑定

数据模型的值发生改变,就会导致页面值的改变;页面值的改变,也会导致数据模型中值的改变,
这种相互影响的关系就是双向数据绑定。

单向数据绑定

MVC 与 MVVM

MVC介绍

MVC(Model–view–controller)是一种软件架构模式,
把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。

MVC是一种应用程序的设计思想(不是设计模式)
例如:移动端和PC端两个View,共享同一个Model
在MVC设计模式中, Model 响应用户请求并返回响应数据,
View 负责格式化数据并把它们呈现给用户,业务逻辑和表示层分离,
同一个 Model 可以被不同的 View 重用,所以大大提高了代码的可重用性。

MVVM

M: model 模型,相当于 User(构造函数)
V: view 视图, ng-app 管理的页面
VM: ViewModel 视图模型 在Angular中就是:$scope

ViewModel

案例:用户注册

localStorage 的基本使用

参考

$watch -监听数据

app.controller("demoController", function($scope) {
    $scope.name = "jack";
    
    // 参数一:表示监听的$scope中的属性名称,类型为:字符串
    // 参数二:表示数据变化执行的回调函数,有两个参数分别是:当前值与变化之前的值
    // 参数三:比较方式,false:表示比较引用;true:表示比较值。默认值为false
    $scope.$watch("name", function(curValue, oldValue) {
        // 只要被监听的数据发生变化,就会指定该回调函数中的代码!

        // 略过第一次执行
        if(curValue === oldValue) return;
    });
});

启动NG的方式

// 等待文档加载完成后,启动 angular
angular.element(document).ready(function() {
    angular.bootstrap(document, ['MyModule']);
});

其他

多个app

<div ng-app="FirstApp"></div>
<div ng-app="SecondApp"></div>

框架和库的区别

Library

使用jQuery的思路:
1 想要获取元素,我调用 $(selector)
2 元素绑定事件,我调用 .on()
3 进行什么DOM操作,我调用什么方法完成

总结:你告诉jQuery你要做的操作,jQuery就能帮你做好。
      **在使用库的过程中,开发人员是 控制者**

Framework

Angular提供了一套完整的解决方案,所有的流程都设定好了
我们只需要按照流程规则,把我们的代码进行填坑。

主要区别是:

其他资料

angular代码风格

模块化

参考网站

AngularJS

在Angular中使用"jQuery"

示例

// 获取 jqLite 对象
var $ = angular.element;
$(document).ready(function() { });

注意点

AngularJS的一般开发流程

模块的划分

按照模块划分

按照文件划分

控制器(controller) -创建方式

低版本(1.2.29之前)

推断式

angular
    .module('testApp', [])
    .controller('DemoController', function($scope) {
        
    });

安全方式创建

创建控制器

// 第一个参数:控制器的名称
// 第二个参数:数组,最后一项表示回调函数,除此之外其他的参数表示依赖的参数列表
app.controller("DemoController", ["$scope", "$log", function($scope, $log) {
    $log.log("打印日志了");
}]);

面向对象方式

<div ng-app="testApp" ng-controller="DemoController as demo">
    <p>{{demo.name}}</p>
</div>

<script>
angular.module('testApp', [])
    .controller('DemoController', ['$scope', function($scope) {
        // 添加模型属性
        this.name = 'Jack';
    }]);
</script>

依赖注入(DI -Dependency injection)

原理分析

/**
 * [提取参数]
 * @param  {Function} fn [回调函数]
 * @return {[type]}      [参数列表数组]
 */
function extractArgs(fn) {
    var r = /^[^\(]*\(\s*([^\)]*)\)/;
    var args = r.exec( fn.toString() );
    return args[1].split(',');
}

extractArgs(function($scope, $log) {});
// 方法的返回值:["$scope", "$log"]

解决页面闪烁问题

ng-bind 指令

<p ng-bind="name"></p>

ng-cloak 指令

<style>
    .ng-cloak {
        display: none;
    }
</style>

<p class="ng-clock">{{name}}</p>

常用指令介绍

ngSanitize 模块

<div ng-bind-html="name"></div>
<script src="angular-sanitize.js"></script>
<script>
    // 引入 ngSanitize 模块
    var app = angular.module("testApp", ["ngSanitize"]);
    app.controller("testController", ["$scope", function($scope) {
        $scope.name = "<h1>雨啊雨</h1>";
    }]);
</script>

ng-repeat 指令

<ul>
    <li ng-repeat="item in datas"></li>
</ul>

<script>
app.controller('TestController', ['$scope', function($scope) {
    $scope.datas = [
        {name: 'jack', age: 19},
        {name: 'tom', age: 21},
        {name: 'rose', age: 22}
    ];
}]);
</script>
<ul>
    <li ng-repeat="item in datas track by $index"></li>
</ul>

ng-repeat 的循环项属性

<ul>
    <!-- 隔行变色效果的实现 -->
    <li ng-repeat="item in datas" class="{{$odd?'red':'green'}}"></li>
</ul>

ng-class指令

对象值

模型中的变量

<div ng-class="type"></div>
<script>
    app.controller("demoController", ["$scope", function($scope) {
        $scope.type = "red";
    }]);
</script>

其他指令

ng-hide/ng-show 显示和隐藏(知道)

<div ng-show="isShow"></div>

ng-if

<div ng-hide="false"></div>

ng-switch (了解)

<div ng-switch="name">
    <div ng-switch-when="jack">我是jack</div>
    <div ng-switch-when="tom">我是tom</div>
    <div ng-switch-when="rose">我是rose</div>
</div>
<script>
    $scope.name = "jack";
</script>

表单元素的指令

ng-checked / ng-selected 可以使用 ng-model 代替, 但是要注意ng-model是双向绑定

事件指令

ng-click / ng-submit / ng-dblclick / ng-blur / ng-focus / ng-change

兼容HTML5标准的指令

AngularJS

TodoMVC案例

功能划分

1 展示任务列表
2 添加任务
3 删除一条任务
4 修改任务
5 切换任务选中状态(单个或批量)
6 清除已完成任务
7 显示未完成任务数
8 显示不同状态的任务
    以及当前任务高亮处理
9 根据URL变化显示相应任务
11 使用服务抽象数据模型管理
12 使用路由完成不同任务的切换

$location.url()

URL是: file:///F:/Angular_File/todomvc/index.html#/completed

通过调用 $location.url() 方法获取的是:'/completed'

过滤器

格式化数据过滤器

filter过滤器 -过滤数据

<!-- 取出 completed 属性为:true 的数据 -->
<p ng-repeat="item in data | filter:{completed: true} track by $index"></p>

<script>
app.controller('FilterController', ['$scope', '$filter', 
    function($scope, $filter) {
        $scope.data = [
            {name: '吃饭', completed: true },
            {name: '睡觉', completed: false },
            {name: '豆豆', completed: true }
        ];
    }]);
</script>

currency 过滤器

<p>{{12345678.333 | currency: "¥"}}</p>

date 过滤器

<p>{{1412345678901 | date: "yyyy-MM-dd hh:mm:ss"}}</p>

limitTo 过滤器

<p>{{'是谁在唱歌,温暖了寂寞' | limitTo:5:2}}</p>

orderBy 过滤器

<p ng-repeat="item in data | orderBy: 'age'"></p>

在JavaScript中使用过滤器

var time = $filter("date")($scope.curDate, "yyyy-MM-dd hh:mm:ss");

service 服务

创建服务

app.service('TestService', [function() {
    // this.get = function() {};
    // this.set = function() {};
    // this.update = function() {};
    // this.delete = function() {};
}]);

// 在控制器中使用自定义服务
app.controller('DemoController', ['$scope', 'TestService', 
    function($scope, TestService) {
    console.log(TestService);
}]);

模块之间的依赖关系

有三个模块:
1 app.js:主模块,应用程序的入口,实现统一调用所有其他模块
2 controller.js:控制器模块,处理视图中与用户交互的功能,即:处理业务逻辑
3 service.js:服务模块,抽象数据操作,提供数据的增删改查

每个模块都会放在一个独立的js文件中,因此,每个文件都会有一个模块,
    即:angular.module("模块名", []);
建立模块之间的联系:
    在 app.js 主模块中,引入:controller 和 service这两个模块

ngRoute -路由

使用步骤

<div ng-app="routeApp">
    <a href="#/stu/li"></a>
    <p>a</p>
    <p>b</p>
    <div ng-view></div>
    <p>c</p>
    <p>d</p>
</div>

<script>
    var app = angular.module('routeApp', ['ngRoute']);
    app.config(['$routeProvider', function($routeProvider) {
        $routeProvider.when('/stu/li', {
            template: '<p>李四</p>'
        });
    }]);
</script>

when() 方法

app.config(['$routeProvider', function($routeProvider) {
    $routeProvider.when('/stu/li', {
        template: '<p>你好,我是{{name}}</p>',
        controller: 'stuController'
    });
}]);

app.controller('stuController', ['$scope', function($scope) {
    $scope.name = '小明';
}]);

otherwise() 方法

$routeProvider
    .otherwise({
        redirectTo: '/stu/'
    });

$routeParams -路由的服务

app.config(['$routeProvider', function($routeProvider) {
    // '/stu/:name?' 用来匹配:/stu/ 或 /stu 或 /stu/xxx 的任意一种
    $routeProvider.when('/stu/:name?', {
        template: '<p>你好,我是{{name}}</p>',
        controller: 'stuController'
    });
}]);

app.controller('stuController', ['$scope', '$routeParams', function($scope, $routeParams) {
    // $routeParams 是一个对象,对象中包含了一个 name 属性。
    // name属性,是路由的 when 方法的第一个参数
    console.log($routeParams.name);
}]);

$route -路由的服务

app.controller('stuController', ['$scope', '$routeProvider', '$route', function($scope, $routeProvider, $route) {
    console.log($routeProvider.name);
    
    // 参数是一个对象,具有路由参数属性的对象
    $route.updateParams({name: 'lisi'});
}]);

hashPrefix

<a href="#!/users"></a>

<script>
$routeProvider
    .when('/users', {
        templateUrl: 'view.html',
        controller: 'TestController'
    })

// 1.6以上,默认值为:'!'
// $locationProvider.hashPrefix('!');
</script>

AngularJS

WebAPI

API 应用程序编程接口,简单来说,就是:方法
依赖于Web而提供的API称为: WebAPI ,通过URL实现。

可以把 WebAPI 看作是有 输入和输出(I/O) 的方法
    根据输入的参数,接口会返回不同的数据

webapi就相当于函数
webapi的参数(?username=小明&pwd=123465) 相当于 函数参数
    function fn(username, pwd) {}  fn('小明', 123456)
webapi接口返回的数据,就相当于函数的返回值

豆瓣电影项目

豆瓣电影API

1 输入上述网址
2 点击最上部的开发文档,进入 豆瓣API快速入门
3 从该页面中找到 'https://api.douban.com/v2/' 这是所有API的URL地址的前半部分
4 点击左侧菜单中的 '豆瓣Api V2(测试版)',进入 豆瓣Api V2(测试版)
5 将页面滑动到底部,找到 '电影Api V2',点击,然后会进入到 Movie API Doc 页面
6 在该页面中即可找到:"正在热映"、"即将上映"、"Top250"

模块的划分

首页模块、电影详情页模块
有三个模块: "正在热映"、"即将上映"、"Top250"

各个模块之间相互独立, 主模块中引入单个模块即可!

电影案例思路

ng-src

![]({{item.iamges.large}})

$http服务

$http.get

app.controller('DemoController', ['$scope', '$http', function($scope, $http) {
    // 路径最好使用绝对路径
    $http.get('url').then(function(response) {
        // 成功的回调函数
    }, function() {
        // 失败的回调函数
    });
}]);

JSONP -实现跨域

JSONP跨域原理分析

其他跨域方式

2 $http.jsonp -实现跨域

$http.jsonp("url地址?callback=JSON_CALLBACK").then();
// 获取手机号码归属地
// http://v.showji.com/Locating/showji.com2016234999234.aspx?m=13333333333&output=json&callback=JSON_CALLBACK&timestamp=' + (new Date()-0)

$scope.$apply()

1 angular代码执行会触发 Dirty Check 机制,进行数据的双向绑定
2 异步操作是在angular代码执行完毕之后才执行的
3 也就是说,angular代码执行完了,脏检查已经执行完毕,才执行的异步回调
4 此时,可以在异步操作中手动调用 $scope.$apply() 方法告诉angular让其立即执行一次 Dirty Check
5 执行完毕,angular知道了数据变化,就会展示出我们想要的数据

如果没有调用 $scope.$apply,数据已经改变了,但是双向绑定没有触发。

自定义指令

1 自定义指令用于扩展和增强HTML
2 用于封装一些常用而且共用的功能
3 AngularJS仍然有DOM操作,所有的DOM操作都应该集中在自定义指令中
4 内部指令基本满足我们平时开发的需求, 少数情况的一些特殊需求,会用到自定义指令

创建指令

// 第一个参数:表示指令的名称,使用驼峰命名法,在视图中使用时修改为`-`分割的形式
// 第二个参数:是一个回调函数,让用户设置该指令的行为
angular.module('testApp', [])
    .directive('myBtn', [function() {
        return {};
    }]);

指令常用属性说明

<!-- 标签 -->
<my-btn></my-btn>
<!-- 类名 -->
<div class="my-btn"></div>
<!-- 注释 -->
<!-- directive:my-btn -->
<!-- 属性 -->
<div my-btn></div>

参考文章

面试题 angularJS最大的不足是什么呢?

    angularJs内部的双向数据的绑定是通过脏检测来实现的,在angularJS的内部维持一个 $digest队列,每当在view视图里面使用 插值表达式 或者 指令 的时候,则会向该队列里面创建一个对应的回调函数fn来和对应的插值表达式或者指令相对应;最后当$scope模型对象里面的数据发生变化后,则会立马循环遍历当前的$digest队列,查看每个fn回调函数里面对应的模型数据是否发生变化,如果发生变化,则立马影响视图上面的变化。但是需要注意的是angularJS的脏检测的循环次数最大为10次,如果超过10次,则不再检测,防止无限循环。
    
    解决方法: 最好将页面划分多个区域,每个区域单独创建属于自己的控制器,然后在控制器里面创建属于自己的$scope模型对象。
上一篇 下一篇

猜你喜欢

热点阅读