随着互联网时代的不断发展,各大前端框架的产生,前端人员的工作不再仅仅是制作一个个简单的静态页面,而是一个应用程序。如今,已有许多的后台人员转到前端。说到前端流行框架,手机有三大巨头,前端框架也有三大巨头——Vue、React、Angular。首先,先和大家来聊一聊Angular。
一、Angular简介
(1)提供一种规范或者模式
(2)按照它提供的这种规则去写代码
(3)框架会自动帮助我们去执行相应的代码
(4)本质上是js文件
二、Angular含义
(1)一款非常优秀的前端高级 JS 框架
(2)最早由 Misko Hevery 等人创建
(3)2009 年被 Google 公式收购,用于其多款产品
(4)目前有一个全职的开发团队继续开发和维护这个库
(5)其核心就是通过指令扩展了 HTML,通过表达式绑定数据到 HTML
(6)不推崇DOM操作,也就是说在NG中几乎找不到任何的DOM操作
(7)万一需要操作dom,也不要使用jquery,或者原生的dom方法
(8)oangular提供了一个类似于jquery的东西,jqLite,通过angular.element方法来进行dom操作,可以类比成jquery中的$
(9)jqLite是一个轻量级的jquery,封装了一些常用的jquery方法
(10)主要用来帮助我们方便的去写spa应用程序[span(single page application):1、单页应用程序;2、通过监听hashchange事件,根据不同的url中的锚点值,去动态的发送ajax请求去请求数据]
三、Angular安装
(1)通过工具安装:
npm : npm install angular
(2)自动手动的去下载安装
四、Angular 的核心特性
(1)指令化
(2)双向数据绑定
(3)模块化
(4)MVC思想
1、指令
① ng-app: 告诉angular来管理页面的代码(ng-app所在元素及其子元素)
② ng-click : 类比成onClick,是用来为当前元素注册点击事件
③ ng-model: 用来获取文本框的值,是于input的value值进行了绑定,改变ng-model的属性值对应的值,文本框的值就会改变
④ ng-app: 告诉angular来管理页面的代码(ng-app所在元素及其子元素)
⑤ ng-init 指令: 用于对ng-model指定的值进行初始化操作
2、模块化
① 创建模块:angular.module(‘模块名’,[]),第二个参数是个数组,这个数组里的每一个元素,是我们当前模块依赖的其他模块。即便我们不依赖其他的模块,也需要传递一个空数组。因为如是不传第二个参数的话,这个方法的作用就会变为获取一个名为”模块名”的模块对象。例:angular.module(‘myApp’),是获取一个名为myApp的模块对象。
② 需要给ng-app指令一个属性值,这个值就是我们创建的模块名,告诉anuglar,现在由我们自己创建的这个模块来管理页面。
3、控制器
① 控制器是通过模块对象来创建的
② 语法:
var app = angular.module('模块名',[])
app.controller('控制器的名字',function($scope){
// 在这个function里写我们具体想要执行的代码
// $scope 就是用来存储我们的数据模型.
})
③ 需要在页面上使用了数据模型的元素父级元素上加上ng-controller指令,并给这个指令一个属性值,这个值就是我们创建的控制器名字。
④ 安全的创建控制器的方式
var app.module('myApp',[]);
// 第二个参数是一个数组,数组中除了最后元素,其他元素都我们想要传递的参数的名字,
// angular会根据我们写的这些名字,去动态给我们传递参数
// 就是给数组的最后一个元素传递参数,因最后一个元素要求是function
// 注意://这个function中参数的顺序与数组前端所有元素的顺序需要保持一致
app.controller('demoController',['$scope','$log',function($scope,$log){}])
4、双向数据绑定
① 页面文本框的值改变,导致数据模型的值发生改变
② 数据模型的值的改变,反过来导致页面文本框的值的改变
5、MVC 思想
① 将应用程序的组成划分为三个部分:Model View Controller
② 控制器的作用就是初始化模型用的
③ 模型就是用于存储数据的,做一些业务逻辑的操作
④ 视图用于展现数据
⑤ $watch:
a、用于监视数据模型的变化
b、语法:
$scope.$watch('数据模型的名字的字符串形式',function(变化后的值,变化前的值){
// 当前数据模型发生变化时,就会执行这个function
// 注意:这个function会默认执行一次
})
5、表达式
① {{}}
② 大括号内部写上一个ng-model对应的文本框的值
五、Angular开发流程
1、新建一个html文件
2、引入包: npm/bower/暴力方式/cdn
3、需要在html标签上加上ng-app,表示需要angular来管理我们的页面
4、在js中创建模块angular.module(‘myapp’,[]),需要在页面上的ng-app指令上加上一个值,这个值就是模块名ng-app=”myapp”
5、在js中通过刚刚创建的模块来创建一个控制器 app.controller(‘demoController’,function($scope){}),需要在页面上加上ng-controller指令,指定控制器的名字为demoController
6、初始化数据模型. 建模(指的是抽象页面结构,得到数据模型或者行为模型)
7、写具体的Js代码
六、Angular API
1、指令
① ng-app
② ng-model
③ ng-click
④ ng-controller
⑤ ng-init
⑥ ng-bind:用于解决angular解析表达式闪烁问题,写在双标签的属性位置,最终浏览器会把ng-bind指定的值渲染到它所在标签的innerHTML位置
⑦ ng-cloak:angular会在加载之后移除名为ng-cloak的类样式名,事先给这个类样式添加一个display:none的样式
例:
<style>
.ng-cloak{
display: none;
}
</style>
<body ng-app="myApp">
<div ng-controller="demoController">
<p ng-bind="name"></p>
<!-- {{name}} -->
<p >我是中国人</p>
<!-- angular会在加载之后去名为ng-cloak类样式名 -->
<div class="ng-cloak">
<p>{{name}}</p>
<p>{{name}}</p>
<p>{{name}}</p>
<p>{{name}}</p>
<p>{{name}}</p>
</div>
<p class="ng-cloak">{{name}}</p>
</div>
<script src="node_modules/angular/angular.js"></script>
<script>
// 1.创建模块
var app = angular.module('myApp',[]);
// 2.创建控制器
app.controller('demoController',['$scope',function($scope){
$scope.name='<div>加载</div>';
}]);
</script>
</body>
⑧ ng-bind-html
⑨ ngSanitize:渲染html字符串
⑩ ng-repeat:用于显示数据列表,类似于for in循环。ng-repeat在遍历每一条数据时,都会提供一些额外的参数
例:
<style>
ul,li{
padding: 0;
margin:0;
height: 30;
}
li{
margin-top: 5px;
border-radius: 4px;
color: #fff;
padding: 3px;
}
.red{
background: #F05656;
}
.blue{
background: #326DD8;
}
.grenn{
background: #06D563;
}
</style>
<body ng-app="myApp">
<div ng-controller="demoController">
<ul>
<!-- ng-repeat写在哪个元素的属性位置,表示想重复显示哪个元素.写法类似于for in 循环 var key in data
// 会遍历data这个数组,其中item中每次遍历时这个数组中的当前元素ng-repeat并不是必须写在li上,写在其他元素上也可以-->
<!-- 在ng-repeat遍历到每一条数据时的时候,会提供一个$even和$odd $even:是一个布尔值,表示当前这条数据,为true时表示当前数据是第偶数条(是从索引0开始算的) $odd:是一个布尔值,表示当前这条数据,为true时表示当前数据是第奇数条(是从索引0开始算的)-->
<li ng-repeat="item in data" class="{{$odd?'red':'blue'}}">
{{item.name}},{{item.age}}
</li>
</ul>
</div>
<script src="node_modules/angular/angular.js"></script>
<script>
// 1.创建模块
var app = angular.module('myApp',[]);
// 2.创建控制器
app.controller('demoController',['$scope',function($scope){
var data = [{name:'小明',age:20,salary:'A'}, // >=20
{name:'小红',age:18,salary:'B'}, // >=16
{name:'小月',age:16,salary:'C'}, // >=14
{name:'小王',age:16,salary:'A'},
{name:'小黑',age:28,salary:'C'}]
$scope.data = data;
}])
</script>
</body>
a、
even,是一个布尔值,为true时表示当前数据是否是第【偶】数条数据(索引是从0开始计算的)b、
e
v
e
n
,
是
一
个
布
尔
值
,
为
t
r
u
e
时
表
示
当
前
数
据
是
否
是
第
【
偶
】
数
条
数
据
(
索
引
是
从
0
开
始
计
算
的
)
b
、
odd,是一个布尔值, 为true时表示当前数据是否是第【奇】数条数据(索引是从0开始计算的)
c、
first,是一个布尔值,为true时表示当前数据是否是第一条d、
f
i
r
s
t
,
是
一
个
布
尔
值
,
为
t
r
u
e
时
表
示
当
前
数
据
是
否
是
第
一
条
d
、
last, 是一个布尔值,为true时表示当前数据是否是最后一条
e、
index是当前数据的索引f、
i
n
d
e
x
是
当
前
数
据
的
索
引
f
、
middle,为true时,表示当前数据即不是第一条,也不是最后一条
⑪ng-class 实现从多种样式中选择一个,用来操作所在元素的类样式名,类似于从一个key,value对象中获取值。不一定要和ng-repeat一同使用,可以单独使用的其他元素上。
例1:显示不同颜色
<li ng-class="{'A':'red','B':'blue','C':'grenn'}['A']"></li>
<style>
ul,li{
padding: 0;
margin:0;
height: 30;
}
li{
margin-top: 5px;
border-radius: 4px;
color: #fff;
padding: 3px;
}
.red{
background: #F05656;
}
.blue{
background: #326DD8;
}
.grenn{
background: #06D563;
}
</style>
<body ng-app="myApp">
<div ng-controller="demoController">
<ul>
<!-- ng-class 专门用来操作样式,想要操作谁的样式,就写在谁上
写法,相当于key,value对象,最终就像获取这个对象的值一样去操作
拿到值之后,angualr会把这个值当作类样式名加入到class中
-->
<li ng-class="{'A':'red','B':'blue','C':'grenn'}[item.salary]"
ng-repeat="item in data">
{{item.name}},{{item.age}}
</li>
</ul>
</div>
<script src="node_modules/angular/angular.js"></script>
<script>
// 1.创建模块
var app = angular.module('myApp',[]);
// 2.创建控制器
app.controller('demoController',['$scope',function($scope){
// 数据
var data = [
{name:'小明',age:20,salary:'A'}, // >=20
{name:'小红',age:18,salary:'B'}, // >=16
{name:'小月',age:16,salary:'C'}, // >=14
{name:'小王',age:16,salary:'A'},
{name:'小黑',age:28,salary:'C'}
]
$scope.data = data;
}]);
</script>
</body>
例2:实现从多种样式中选择多个
<li ng-class="{'red': true,'blue':true,'grenn':false}"></li>
<style>
.box{
background: #E71717;
}
.box-color{
color: #fff
}
</style>
<body ng-app="myApp">
<div ng-controller="demoController">
<!-- ng-class 从多种样式中选择多个,
现在这里的这个key,value对象中的key,是想要显示的样式名,
对应的value是一个布尔值,当这个布尔值为true时,会将对应的key做为类样式名加入到class中 -->
<div ng-class="{'box':isTrue,'box-color':isTrue,'test':true}">
我不是小明
</div>
<input type="text" ng-model="name">
</div>
<script src="node_modules/angular/angular.js"></script>
<script>
// 1.创建模块
var app = angular.module('myApp',[]);
// 2.创建控制器
app.controller('demoController',['$scope',function($scope){
$scope.name="小明";
$scope.isTrue=false;
//$watch
$scope.$watch('name',function(newValue,oldValue){
if(newValue=='小明'){
$scope.isTrue=true;
}else{
$scope.isTrue=false;
}
})
}])
</script>
</body>
⑫ ng-show:为true时,【显示】当前元素,为false时【隐藏】当前元素
⑬ ng-hide:为true时,【隐藏】当前元素,为false时【显示】当前元素
⑭ ng-if :为false时,会【移除】当前元素
例:
<body ng-app="myApp">
<div ng-controller="demoController">
<h1>ng-checked</h1>
<input type="checkbox" ng-checked="isAgree">
<input type="checkbox" ng-model="isAgree">
<h1>ng-switch</h1>
<div ng-switch="name">
<div ng-switch-when="小明">我是小明</div>
<div ng-switch-when="小红">我是小红</div>
</div>
<ul>
<!-- 让不想显示的元素从dom中移除
ng-if,与ng-show类似,也要一个布尔值,当为false时,会移除当前元素 -->
<li
ng-if="item.salary!='A+'"
ng-repeat="item in data">
{{item.name}},{{item.age}}
</li>
</ul>
</div>
<script src="node_modules/angular/angular.js"></script>
<script>
// 1.创建模块
var app = angular.module('myApp',[]);
// 2.创建控制器
app.controller('demoController',['$scope',function($scope){
var data = [
{name:'小白',age:17,salary:'A+'},
{name:'小明',age:20,salary:'A'}, // >=20
{name:'小红',age:18,salary:'B'}, // >=16
{name:'小月',age:16,salary:'C'}, // >=14
{name:'小王',age:16,salary:'A'},
{name:'小黑',age:28,salary:'C'}
]
$scope.data = data;
$scope.name="小明";
$scope.isAgree=true;
}])
</script>
</body>
⑮ ng-switch:需要和ng-switch-when配合使用,类似与js里的switch case
例:
<h1>ng-switch</h1>
<div ng-switch="name">
<div ng-switch-when="小明">我是小明</div>
<div ng-switch-when="小红">我是小红</div>
</div>
2、其他指令
① ng-checked=”isAgree” ng-model=”isAgree”:单选/复选是否选中,只是单向绑定数据
② ng-selected:是否选中,只是单向绑定数据
③ ng-disabled:是否禁用
④ ng-readonly:是否只读
3、事件指令
① ng-blur:失去焦点
② ng-change:发生改变
③ ng-copy:拷贝完成
④ ng-click:单击
⑤ ng-dblclick:双击
⑥ ng-focus:得到焦点
⑦ ng-submit:表单提交
4、自定义指令
① 指令创建:app.directive(‘指令的名字’,第二个参数是个数组,写法类似于controller第二个参数) ,app.directive(‘myBtn’,[function(){}])
② 指令的名字需要使用驼峰命名法来命名,我们在使用的时候,需要把所有的大小转换成小写,并且在原先大小之间加上-
③ 自定义指令中回函数里返回的对象的属性:
a、 template:指定一个html字符串,最终angular会把这个字符串渲染到页面上,我们书写自定义指令所在标签的innerHTML位置
b、templateUrl:也是指定一个字符串,只是这个字符串是一个路径,最终angular会帮助我们去请求(ajax)这个文件,然后把这个文件的内容当作模板字符串插入到页面中。
c、- restrict : 指定angualr自定义指令的使用方式,给一个字符串 ‘A’ // ‘CA’
(1)+ ‘C’ : 表示只能以类样式的形式使用 ng-cloak
(2)+ ‘A’ : 表示只能以属性的形式使用
(3)+ ‘E’ : 表示只能以自定义标签的形式使用
(4)+ ‘M’ : 表示只能以注释的形式使用自定义指令。,使用这种方式时,需要设置repace属性为true
d、 - replace: 当为true时表示,angular会用tempate所指定的模板字符串替换自定义指令所在标签。
e、- transclude: 转置,需要一个布尔值,为true时,会将自定义指令所在标签的innerHTML位置的字符串添加到模板字符串中拥有ng-trasclude指令的标签的innerHTML位置
f、- scope: 需要提供一个对象,用来获取自定义指令所在标签的属性值
g、- link:需要提供一个function,这个function有三个参数
h、+ scope,可以暴露一些属性给模板字符串使用,与控制器里的$scope有点类似
i、 + element: 就是angular为我们获取的自定义指令所在标签的jqLite对象
j、+ atrriubtes: 这是一个object对象,里面包含了所有自定义指令所在标签的属性值
k、myClass:’@tmp’,获取自定义指令所在标签的名为tmp的的属性值 ,最终可以在模板字符串中,直接使用表达式显示相应的值{{myClass}}
l、tmp:’@’,//这是上种方式的简写,直接让属性名等于自定义指令所在标签的属性名
例:
<body ng-app="myApp">
<div my-btn>登陆1</div>
<div my-btn>登陆2</div>
<div class="my-btn">登陆3</div>
<my-btn tmp="danger">注册</my-btn>
<my-btn tmp="success">登陆</my-btn>
<my-btn tmp="primary" xx-test="我是属性">注销</my-btn>
<!-- 以注释的形式来使用 -->
<!-- directive:my-btn -->
<!-- { "xx-test": } -->
<script id="tmpl" type="text/ng-template" >
<div>
<button class="btn btn-{{tmp}}" ng-transclude>注册</button>
<p>{{name}}</p>
</div>
</script>
<script src="node_modules/angular/angular.js"></script>
<script>
// 1.创建模块
var app = angular.module('myApp',[]);
// 2.创建自定义指令
// 一般是用来做一些UI的封装.
// directive方法:第一参数:也是一个名字
// 这个名字有个限制:需要按照驼峰命名法来命名.
// 在使用的时候,需要转换成小写,把原先大小写之间加上一个-
// 第二个参数:也是一个数据,写法类似与controller第二个参数,也是为了避免代码压缩带来的问题
app.directive('myBtn',[function(){
var obj={
// 核心是这里的参数:
// 模板:
// template:'<button>注册</button>',
// templateUrl:'./view.html',// 可以指定一个路径,指向的是一个html文件,文件里写的就是html代码
templateUrl:'tmpl',// 也可以指定一个script标签的id,并且需要设置script标签的type属性为:"text/ng-template"
restrict:'CAE', // C class , A attribute ,E element,M Comment,
// replace: true,// 为true时会把template对应的字符替换掉自定义指令所在标签
transclude:true, // 转置,默认为false,为ture,时会把自定义指令所在标签的innerHTML位置的字符串添加到模板字符串中
scope:{ // 需要提供一个对象
// myClass:"@tmp"// 值以@符号开头,通过这种形式,最终可以使用myClass来得到@后这个名字对应的属性值.
tmp:'@' // 这是上一种方式的简写,要求scope属性的属性名与自定义指令所在标签的属性名相同
},
// 只不过,这里需要给的属性值是一个方法
// 我们最终需要写的js代码就是写在这个function里
link:function(scope,element,attributes){
// 这个scope与我们控制器里的$scope非常的象,都是提供一些属性值,然后能够使用表达式输出
// *注意*:这里的scope提供的属性值,只能在模板字符串中使用
scope.name="小明";
// element,指的是自定义指令所在标签的jqLite对象
// angular.element()
console.log(element);
//element.addClass('test');
console.log(attributes);
// attributes:就是得到自定义指令所在标签的所有属性
element.on('click',function(e){
console.log('我是来自点击事件的代码');
})
// angualr.element()
}
};
return obj;// 直接返回一个object对象。
}])
</script>
</body>
5、过滤器
例:格式化数据的过滤器
<body ng-app="filterApp">
<div ng-controller="demoController">
<h1>currency</h1>
<!-- currency过滤器的使用 在我们的数据模型后直接加上|线,参数直接在过滤器后加上:号,冒号后写参数 -->
<p>{{money | currency : '¥'}}</p>
<h1>date</h1>
<!-- 时间过滤器 -->
<p>{{date | date : 'yyyy年MM月dd日 HH:mm:ss'}}</p>
<h1>json</h1>
<!-- json格式化过滤 -->
<pre>{{jsonData|json : 4}}</pre>
<h1>limitTo</h1>
<!-- 限制输出的数据长度 -->
<!-- 第一个参数,表示限制输出的长度 -->
<!-- 第二个参数,表示从第几个开始显示,从索引为0开始计算的。 -->
<p>{{limitStr|limitTo : 2 : 1}}...</p>
<h1>orderBy</h1>
<!-- 对数组进行排序 -->
<!-- 参数,可以指定排序的顺序,+号表示正序,-号表示-序 -->
<p ng-repeat="item in arr | orderBy :'+' track by $index" >
{{item}}
</p>
</div>
<script src="node_modules/angular/angular.js"></script>
<script>
// 1.创建模块
var app =angular.module('filterApp',[]);
// 2.创制控制器
app.controller('demoController',['$scope',function($scope){
$scope.money=25000.41213;
$scope.date=1467364127933;
$scope.jsonData={a:{name:'小是',age:18,sex:'男'},b:{name:'小红',age:16,sex:'女'}};
$scope.limitStr="我是中国人,我爱自己的祖国。";
$scope.arr=[1,2,3,4,1];
}]);
</script>
</body>
例:filte
<body ng-app="filterApp">
<div ng-controller="demoController">
<!-- 参数表示需要如何进行过滤 -->
<!-- 如果直接指定一个值,会转成字符串全局匹配 -->
<p ng-repeat="item in tasks | filter : true">
{{item.name}}
</p>
<!-- 根据数组中每一条元素的属性去查找 -->
<!-- track by $index 表示根据$index,来进行唯一值的确定,来避免数据重复问题 -->
<p ng-repeat="item in tasks | filter : {completed:true} track by $index">
{{item.name}}
</p>
</div>
<script src="node_modules/angular/angular.js"></script>
<script>
// 1.创建模块
var app =angular.module('filterApp',[]);
// 2.创制控制器
app.controller('demoController',['$scope',function($scope){
$scope.tasks = [
{ id: 0, name: "吃饭", completed: true },
{ id: 1, name: "睡觉", completed: true },
{ id: 2, name: "打豆豆", completed: false },
{ id: 3, name: "学习", completed: true },
{ id: 4, name: "学习雷锋,我是true,不是false", completed: false }
]
}]);
</script>
</body>
6、$watch的深度监听
<body ng-app="myApp" ng-controller="myCtrl">
<form ng-submit="a()">
<input type="text" ng-model="val">
</form>
<script src="angular.js"> </script>
<script>
angular.module('myApp',[]).controller('myCtrl',function ($scope) {
$scope.tasks=[
1,2,3,4,5
];
$scope.a=function () {
$scope.tasks.push($scope.val);
};
$scope.$watch('tasks',function (now,old) {
console.log(now);
},true);
})
</script>
</body>
7、路由
① ngRoute
② 安装:npm安装 npm install angular-route –save
③ 配置:app.config
(1)config,只需要一个参数,就是一个数组,类似开controller方法的第二个参数,也是使用了注入了方式传入参数
(2)$routeProvider来书写一些具体的规则
(3)$routeProvider.when(url中锚点值不包含#号,第二个参数是一个object对象)
(4)templateUrl : 指定一个文件路径或者script标签的id,类似于自定义指令中的templateUrl。指定的模板字符串会插入到页面上拥有ng-view指定所在标签的innerHTML位置
(5)controller :指定一个控制器名,表示这里的模板字符串由这个控制器来管理,注意:这里所指定的控制器里通过$scope暴露出来的数据,只能够在这个模板字符串中使用
(6)ng-view只需要使用一次
④ 路由参数
(1)以:号形式后加上一个名字,表示的是参数名
(2)when(“/sutdents/:name“),这里的name就参数名,相当于一个变量,只要Url中相应的位置有字符就会被匹配
(3)$routeParams 其实它就是一个object对象,路由参数就是以它的属性的形式来存在的,它的属性名就是路由参数的属性值
(4)$routeProvider.otherwise ,不满足前面其他规则时,会跳转到指定的url锚点
(5)在路由参数后加上一个?号,表示这个参数可以为空,意思是对应位置的url锚点值可以不写,也会匹配到这个规则
注:在 AngularJS 中将前缀为 ng- 这种属性称之为指令,其作用就是为 DOM 元素调用方法、定义行为绑定数据等。简单说:当一个 Angular 应用启动,Angular 就会遍历 DOM 树来解析 HTML,根据指令不同,完成不同操作。