AngularJS基础(一)
1.简介
AngularJS 是一个 JavaScript 框架, 它是一个以 JavaScript 编写的库。
AngularJS 通过指令扩展了HTML,且通过表达式绑定数据到 HTML。
AngularJS 可以构建一个单一页面应用程序(SPAs:Single Page Applications)。
在开始学习 AngularJS 之前,您需要具备以下基础知识
- HTML
- CSS
- JavaScript
2.AngularJS指令
AngularJS 指令是扩展的 HTML 属性,带有前缀 ng-
-
ng-app
指令初始化一个 AngularJS 应用程序 -
ng-init
指令初始化应用程序数据 -
ng-model
指令把元素值绑定到应用程序
2.1 ng-model
-
ng-model
数据双向绑定
以下实例中,两个文本域是通过两个ng-model
指令同步数据的
<div ng-app="" ng-init="num=1;price=5">
<h2>价格计算器</h2>
数量: <input type="number" ng-model="num">
价格: <input type="number" ng-model="price">
<br />
总价:{{num*price}}
</div>
价格计算器效果图
-
ng-model
可以为应用数据提供状态值, 验证用户输入 . 根据表单域的状态我们可以添加/移除以下类
ng-empty
:
ng-not-empty
:
ng-touched
: 表示用户是否和控件进行过交互
ng-untouched
: 表示用户是否和控件未进行过交互
ng-valid
: 表单是否通过验证。如果表单当前通过验证,它将为true.
ng-invalid
: 未通过验证的表单.
ng-valid-[key]
: 由setValidity添加的所有验证通过的值 `ng-invalid-[key]` : 由setValidity添加的所有验证失败的值
ng-dirty
: 表示用户是否修改了表单。如果为 ture,表示有修改过;false 表示修没有修改过
ng-pending
: 任何为满足$asyncValidators的情况
ng-pristine
: 控件为初始状态
<form ng-app="" name="myForm" ng-init="myText='10086@mobie.com'">
Email:<input type="email" name="myEmail" ng-model="myText" required />
<span ng-show="myForm.myEmail.$error.email">不是一个合法的邮箱地址</span>
<p>编辑邮箱地址,注意查看状态的改变。</p>
<h1>状态</h1>
<p>Valid: {{myForm.myEmail.$valid}} (如果输入的值是合法的则为 true)。</p>
<p>Dirty: {{myForm.myEmail.$dirty}} (如果值改变则为 true)。</p>
<p>Touched: {{myForm.myEmail.$touched}} (如果通过触屏点击则为 true)。</p>
</form>
ng-model 验证用户输入
-
ng-model
基于它们的状态为 HTML 元素提供了 CSS 类.
<head>
<style>
input.ng-valid {
background-color: red;
}
input.ng-invalid {
background-color: lightblue;
}
</style>
</head>
<body>
<form ng-app="" name="myForm">
输入你的名字:
<input name="myName" ng-model="myText" required>
</form>
<p>编辑文本域,不同状态背景颜色会发生变化。</p>
<p>文本域添加了 required 属性,该值是必须的,如果为空则是不合法的。</p>
</body>
ng-mode提供的 CSS 类
2.2 ng-repeat
-
ng-repeat
指令会重复一个 HTML 元素
<p>使用 ng-repeat 来循环数组</p>
<div ng-app="" ng-init="names=[{name:'张三',country:'中国'}, {name:'尼古拉斯·赵四',country:'英国'}, {name:'小犬纯三狼',country:'日本'}]">
<ul>
<li ng-repeat="x in names">{{ x.name + ', ' + x.country }}</li>
</ul>
</div>
ng-repeat
-
ng-repeat-start
和ng-repeat-end
指令 (在ng-repeat-end
后循环结束, 所以x.country
无值)
<p>使用 ng-repeat-start 和 ng-repeat-end 来循环数组</p>
<div ng-app="" ng-init="names=[{name:'张三',country:'中国'}, {name:'尼古拉斯·赵四',country:'英国'}, {name:'小犬纯三狼',country:'日本'}]">
<ul>
<li ng-repeat-start="x in names">{{ x.name }}</li>
<li>来自</li>
<li>{{ x.country }}</li>
<br ng-repeat-end>
<li>{{ x.country }}</li>
</ul>
</div>
ng-repeat_start 和 ng-repeat-end
2.3 .directive
使用 .directive
函数可以添加自定义的指令, 如下图所示,使用驼峰法来命名一个指令 testDirective
, 但在使用它时需要以 - 分割 test-directive
要调用自定义指令, HTML 元素上需要添加自定义指令名,你可以通过以下方式来调用指令
- 元素名
<test-directive></test-directive>
- 属性
<div test-directive></div>
- 类名
<div class="test-directive"></div>
- 注释
<❗️-- directive: test-directive -->
<body ng-app="myApp">
<test-directive></test-directive>
<script>
var app = angular.module("myApp", []);
app.directive("testDirective", function() {
return {
template : "<h1>我的自定义指令!</h1><p>使用元素名调用</p>"
};
});
</script>
</body>
directive自定义指令
2.4 restrict
通过使用 restrict
你可以限制你的指令只能通过特定的方式来调用.
restrict
值可以是以下几种:
- E 作为元素名使用
- A 作为属性使用
- C 作为类名使用
- M 作为注释使用
ps:restrict 默认值为 EA, 即可以通过元素名和属性名来调用指令。
<body ng-app="myApp">
<test-directive>01</test-directive>
<div test-directive>02</div>
<div class="test-directive">03</div>
<script>
var app = angular.module("myApp", []);
app.directive("testDirective", function() {
return {
restrict : "CE",
template : "<h1>限制指令CE</h1><p>可以使用元素名和类名调用</p>"
};
});
</script>
</body>
restrict 限制指令CE
directive使用注释调用时与restrict的结合使用(此时template中只能有一对 HTML 标签, 否则不显示)
<body ng-app="myApp">
<!-- directive: test-directive -->
<script>
var app = angular.module("myApp", []);
app.directive("testDirective", function() {
return {
restrict : "M",
replace : true,
template : "<h1>限制指令M, 自定义指令使用注释调用</h1>"
};
});
</script>
<p><strong>注意:</strong> 我们需要在该实例添加 <strong>replace</strong> 属性, 否则评论是不可见的。</p>
<p><strong>注意:</strong> 你必须设置 <b>restrict</b> 的值为 "M" 才能通过注释来调用指令。</p>
</body>
restrict 限制指令M
3.Scope(作用域)
概述
AngularJS 应用组成如下
- View(视图), 即 HTML.
- Model(模型), 当前视图中可用的数据.
- Controller(控制器), 即 JavaScript 函数,可以添加或修改属性.
Scope 是模型, 是应用在 HTML (视图) 和 JavaScript (控制器)之间的纽带。
Scope 是一个 JavaScript 对象, 带有属性和方法, 这些属性和方法可以在视图和控制器中使用。
Scope 可应用在视图和控制器上。
3.1 Scope的使用
当你在 AngularJS
创建控制器时,你可以将 $scope
对象当作一个参数传递.
当在控制器中添加 $scope
对象时,视图 (HTML) 可以获取了这些属性.
视图中,你不需要添加 $scope
前缀, 只需要添加属性名即可, 示例如下.
<div ng-app="myApp" ng-controller="myCtrl">
<h1>{{myname}}</h1>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.myname = "希言";
});
</script>
<p>控制器中创建一个属性名 "myname",对应了视图中使用 {{ }} 中的名称。</p>
Scope使用
进阶用法, 示例如下:
<div ng-app="myApp" ng-controller="myCtrl">
<input ng-model="myname">
<h1>{{greeting}}</h1>
<button ng-click='sayHello()'>点我</button>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.myname = "希言";
$scope.sayHello = function() {
$scope.greeting = 'Hello ' + $scope.myname + '!';
};
});
</script>
<p>当你修改输入框中的值时,会影响到模型(model),当然也会影响到控制器对应的属性值。</p>
Scope进阶使用
3.2 Scope的作用范围
在以上两个实例中,只有一个作用域 scope
,所以处理起来比较简单,但在大型项目中, HTML DOM 中有多个作用域,这时你就需要知道你使用的 scope
对应的作用域是哪一个.
- 所有的应用都有一个根作用域
$rootScope
, 它作用在ng-app
指令包含的所有 HTML 元素中, 是各个 controller 中scope
的桥梁, 用$rootscope
定义的值, 可以在各个 controller 中使用.$rootscope
设置的变量在所有controller里面都是可以直接用{{$root.变量名}}
来显示的,当然也可以赋值给$scope
.$rootScope
全局对象的属性可在所有子作用域中访问,子作用域互相无法访问对方的私有变量,这一点与js的函数作用域完全一致.- 不同的控制器域内可以有同名的变量。但除非必要,否则不建议这么做,自己都会乱掉.
- 后面控制器中定义的
$rootScope
变量,在它前面的控制器中访问不到.
<div ng-app="myApp">
<!--myCtrl1-->
<div ng-controller="myCtrl1">
<h1>姓氏为 {{surname}} 的员工</h1>
<ul>
<li ng-repeat="x in names">{{surname}}{{x}} {{country}}</li>
</ul>
<div>-{{country_2}}-</div>
<div>*{{names_2[1]}}*</div>
</div>
<!--myCtrl2-->
<div ng-controller="myCtrl2">
<div>{{names[1]}}</div>
<div>{{surname}} {{names_2[1]}} </div>
<p>子作用域互相无法访问对方的私有变量</p>
</div>
<!--javascript-->
<script type="text/javascript">
var app = angular.module('myApp', []);
app.controller('myCtrl1', function($scope, $rootScope) {
$rootScope.surname = "李";
$scope.names = ["大嘴", "明", "时珍"];
$scope.country_2 = $rootScope.country; // 访问不到,未定义
});
app.controller('myCtrl2', function($scope, $rootScope) {
$rootScope.country = "中国";
$scope.names_2 = ["四", "已疯", "冰冰"];
$scope.surname_2 = $rootScope.surname;
});
</script>
</div>
Scope作用域
进阶用法
<div ng-controller="myCtrl" id="001">
<h1>{{surname}}姓成员:</h1>
<ul>
<!-- ng-repeat循环对象不能出现重复项, 所以需要添加 track by $index -->
<li ng-repeat="x in names track by $index">
{{surname}}{{x}}
<button ng-click="delPerson($index)">删除</button>
</li>
</ul>
<p>添加成员:<input type="text" ng-model="name" placeholder="请输入要添加的名字" /></p>
<button ng-click="addPerson(name)">确认添加</button>
</div>
<script type="text/javascript">
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $rootScope) {
$scope.name = '';
$rootScope.surname = "李";
$scope.names = ["大嘴", "明", "时珍", "已疯", "冰冰"];
$scope.delPerson = function(index) {
// 将点击删除的对象从数组中移除,angular会自动更新列表
$scope.names.splice(index, 1);
}
$scope.addPerson = function(name) {
// 输入的对象添加到数组,angular会自动更新列表
$scope.names.push(name);
}
});
// 手动初始化
// angular.bootstrap(document.getElementById('001'), ['myApp']);
angular.bootstrap(document, ['myApp']); // 浏览器加载的每个html都会对应一个document对象, 此对象是所有html中dom元素的根节点, 也属于dom元素.
</script>
在传统的angularJS应用中,都是通过 ng-app
把 angular
应用绑定到某个 dom
上,这样做会把js代码入侵到html上,angular
提供了手动启动的API: angular.bootstrap(element, [appName], [config]);
-
element
:绑定ng-app的dom元素 -
modules
:绑定的模块名字 -
config
:附加的配置
注意: angular.bootstrap
只会绑定第一次加载的对象,后面重复的绑定或者其他对象的绑定,都会在控制台输出错误提示
4.ng-controller(控制器)
ng-controller
定义了应用程序控制器, 控制器是 JavaScript 对象, 由标准的 JavaScript 对象的构造函数创建. 控制器也可以有方法(变量和函数), 在大型的应用程序中,通常是把控制器存储在外部文件中, 只需要把 <script> 标签中链接外部文件即可.
在上一部分 Scope
中我们已经多次使用过, 关于 controller 中作用域的问题, 还需要注意情况:
- 如果局部
$scope
和$rootScope
都存在,且有相同名字的变量,{{变量名}}
指局部变量而不是全局变量,作用域只有当前 controller;{{$root.变量名}}
是全局变量,在ng-app=""
下任何一个 controller 中都能使用。 - 如果没有
$scope
, 只有$rootScope
,那么{{变量名}}
和{{$root.变量名}}
就没区别了。
<body ng-app="myApp">
<div ng-controller="myCtrl1">
{{first}}<br>
{{$root.first}}<br>
{{second}}<br>
{{$root.second}}<br>
</div>
<br>
<br>
<div ng-controller="myCtrl2">
{{first}}<br>
{{$root.first}}<br>
{{second}}<br>
{{$root.second}}
</div>
<!-- javascript -->
<script type="text/javascript">
var app = angular.module('myApp', []);
app.controller('myCtrl1', function ($scope,$rootScope) {
$scope.first = 'ctrl局部first';
$rootScope.first = '全局first';
});
app.controller('myCtrl2', function ($scope,$rootScope) {
$scope.second = 'ctrl2局部second';
$rootScope.second = '全局second';
});
</script>
</body>
ng-controller
5 过滤器
AngularJS 过滤器可用于转换数据, 可以通过一个管道字符
|
和一个过滤器
添加到表达式中.
过滤器 | 描述 |
---|---|
uppercase | 格式化字符串为大写 |
lowercase | 格式化字符串为小写 |
currency | 格式化数字为货币格式 (默认是$) |
json | 可以把一个js对象格式化为json字符串 |
date | 根据不同的日期格式可以将时间戳格式化为一个日期字符串 |
number | 可以为一个数字加上千位分割, 比如: 123,456,789。同时接收一个参数, 可以指定float类型保留几位小数. |
limitTo | 用来截取数组或字符串,接收一个参数用来指定截取的长度, 如果参数是负值, 则从数组尾部开始截取. |
filter | 用来处理一个数组, 可以过滤出含有某个子串的元素,作为一个子数组来返回. 可以是字符串数组, 也可以是对象数组. 如果是对象数组, 可以匹配属性的值. 它接收一个参数, 用来定义子串的匹配规则。 |
orderBy | 可以将一个数组中的元素进行排序,接收一个参数来指定排序规则,参数可以是一个字符串,表示以该属性名称进行排序。可以是 一个函数,定义排序属性。还可以是一个数组,表示依次按数组中的属性值进行排序(若按第一项比较的值相等,再按第二项比较) |
<div ng-app="myApp" ng-controller="myContrl">
<p>姓名为 {{ name | uppercase}}</p>
<p>姓名为 {{ name | lowercase}}</p>
<p>默认的货币转换 {{99 | currency}}</p>
<p>自定义货币转换 {{99 | currency:"¥"}}</p>
<p>货币小数点位数 {{99 | currency:'£':4}}</p>
<p>时间戳转换 {{times | date:"yyyy-MM-dd HH:mm:ss"}}</p>
<p>格式化数字: {{times | number:2}}</p>
<p>截取数组或字符串 {{ personArray | limitTo:-1}} </p>
<p>匹配属性值中含有a的: {{personArray | filter:'a'}}</p>
<p>匹配属性值中含有4的: {{personArray | filter:4}}</p>
<p>参数是对象,匹配name属性中含有i的: {{ personArray | filter:{name : 'i'} }}</p>
<p>参数是函数,指定返回age小于34的 {{ personArray | filter:ageFunc }}</p>
数组按age属性值进行排序:
<div ng-repeat= "per in personArray | orderBy: 'age'">{{per.name}} {{per.age}}</div>
<p>数组按照函数的返回值进行排序: {{ personArray | orderBy: orderFunc }} </p>
<p>如果age相同,按照name进行倒序: {{ personArray | orderBy: ['age', '-name'] }} </p>
<p>自定义过滤器 {{name | aa}} </p>
</div>
<script type="text/javascript">
var app = angular.module("myApp", []);
app.controller('myContrl', function ($scope, $rootScope) {
$scope.name = "Jack";
$scope.times = "1517940306000";
$scope.personArray = [{name:'Tom', age:23},
{name:'Cindy', age:34},
{name:'Lucis', age:34},
{name:'Kalon', age:56}];
$scope.ageFunc = function(e) {
return e.age < 34;
}
});
// 自定义过滤器, aa为自定义过滤名称 ,val为穿参.
// split("")将val切割成数组, reverse()将数组反转,join("")将数组变成字符串.
app.filter('aa', function() {
return function(val) {
return val.split("").reverse().join("");
}
})
</script>
AngularJS_过滤器