Angular
配置
模块
Angular项目流程: 模块化(分工合作) + 自动构建工具(优化性能与代码)
主模块与分模块方式开发;
最后利用Gulp合并,压缩,重命名JS;
格式:
//-----------------模块化开发-------------
ng-app="lagouApp"//主模块的名称 主模块是整个程序的作用域
//定义一个主模块
var app = angular.module("lagouApp", ["app2", "app3", "app4", "app5"]);
//定义分模块
var app4 = angular.module("app4", [])
//定义分模块的控制器
app.controller("footerCtrl", function($scope) {
//点击事件
$scope.link = function() {
console.log(666);
};
$scope.img =['../../img/weui/icon_tabbar.png','../../img/weui/icon_tabbar.png','../../img/weui/icon_tabbar.png']
});
//-----------------自动构建工具-----
<!-- 合并后的分模块 -->
<script src="dist/js/main.js"></script>
<!-- 分模块 -->
<!-- <script src="controller/headerCtrl.js"></script>
<script src="controller/swiperCtrl.js"></script>
<script src="controller/listCtrl.js"></script>
<script src="controller/footerCrel.js"></script> -->
注意:
angular规定依附在$scope上的数据才能传递给视图
只要$scope定义了,{{}}对应显示对应的值
比如:$scope=>{{}} $scope.name=>{{name}}
angular表达式很像js表达式:它们可以包含文字、运算符和变量
指令
内置指令
>ng-XX="" //内置指令
ng-app //定义主模块的作用域
ng-controller //定义分模块的控制器
ng-init //初始化应用程序数据(定义数据放在HTML标签内)
ng-click = "function()" //点击事件执行对应的函数
ng-bind = "name"// ==> 等同于{{name}} 代替表达式的写法
//常用
ng-model="value"//双向绑定(双方数值都能互相改变彼此);此指令只能配合input select textarea标签使用
ng-repeat = " arr in arrays" //"单项数组 in 整个数组"
ng-show = "bool" //"布尔值" 真则显示,反之则隐藏 适合频繁绑定事件的环境
ng-if = "bool" //增加/删除DOM节点 不适合频繁绑定事件的环境;
ng-class = "{'am-active':page===n}" //ng-class接受的对象,键名是类名,键值是布尔值,如果右边的布尔值为真,那左边的类就出现,反之就隐藏
//其他
ng-src="{{路径}}"
ng-href="{{路径}}"
ng-switch="变量"配合ng-switch-when=""
拓展:
指令 | 作用 |
---|---|
ng-app | 定义应用程序的根元素。 |
ng-bind | 绑定 HTML 元素到应用程序数据 |
ng-bind-html | 绑定 HTML 元素的 innerHTML 到应用程序数据,并移除 HTML 字符串中危险字符 |
ng-bind-template | 规定要使用模板替换的文本内容 |
ng-blur | 规定blur事件的行为 |
ng-change | 规定在内容改变时要执行的表达式 |
ng-checked | 规定元素是否被选中 |
ng-class | 指定 HTML 元素使用的 CSS类 |
ng-class-even | 类似 ng-class,但只在偶数行起作用 |
ng-class-odd | 类似 ng-class,但只在奇数行起作用 |
ng-click | 定义元素被点击时的行为 |
ng-cloak | 在应用正要加载时防止其闪烁 |
ng-controller | 定义应用的控制器对象 |
ng-copy | 规定拷贝事件的行为 |
ng-csp | 修改内容的安全策略 |
ng-cut | 规定剪切事件的行为 |
ng-dblclick | 规定双击事件的行为 |
ng-disabled | 规定一个元素是否被禁用 |
ng-focus | 规定聚焦事件的行为 |
ng-form | 指定 HTML表单继承控制器表单 |
ng-hide | 隐藏或显示 HTML元素 |
ng-href | 为 the<a>元素指定链接 |
ng-if | 如果条件为 false移除 HTML元素 |
ng-include | 在应用中包含 HTML文件 |
ng-init | 定义应用的初始化值 |
ng-jq | 定义应用必须使用到的库,如:jQuery |
ng-keydown | 规定按下按键事件的行为 |
ng-keypress | 规定按下按键事件的行为 |
ng-keyup | 规定松开按键事件的行为 |
ng-list | 将文本转换为列表 (数组) |
ng-model | 绑定 HTML 控制器的值到应用数据 |
ng-mousedown | 规定按下鼠标按键时的行为 |
ng-model-options | 规定如何更新模型 |
ng-mouseenter | 规定鼠标指针穿过元素时的行为 |
ng-mouseleave | 规定鼠标指针离开元素时的行为 |
ng-mousemove | 规定鼠标指针在指定的元素中移动时的行为 |
ng-mouseover | 规定鼠标指针位于元素上方时的行为 |
ng-mouseup | 规定当在元素上松开鼠标按钮时的行为 |
ng-non-bindable | 规定元素或子元素不能绑定数据 |
ng-open | 指定元素的open属性 |
ng-options | 在 <select> 列表中指定 <options>
|
ng-paste | 规定粘贴事件的行为 |
ng-pluralize | 根据本地化规则显示信息 |
ng-readonly | 指定元素的readonly属性 |
ng-repeat | 定义集合中每项数据的模板 |
ng-selected | 指定元素的selected属性 |
ng-show | 显示或隐藏HTML元素 |
ng-src | 指定元素的src属性 |
ng-srcset | 指定元素的srcset属性 |
ng-style | 指定元素的 style属性 ng-style="{{n.left}}
|
ng-submit | 规定 onsubmit事件发生时执行的表达式 |
ng-switch | 规定显示或隐藏子元素的条件 |
ng-transclude | 规定填充的目标位置 |
ng-value | 规定 input元素的值 |
坑:脏值检测
在双向数据绑定中:
原生/JQ + angular 可能会导致 脏值检查机制失效,从而导致双向绑定失效;
解决:手动刷新或者全部用Angular方法;
服务
定义:
服务是一个函数或'单例对象',就相当于我们可以在angular程序中封装好一些方法然后在需要用的时候 '注入' 到需要用到的地方<span style="color: red">(控制器,自定义服务,自定义指令和自定义过滤器中)</span>,这样可以增强我们程序的扩展性和复用性
内置服务
$scope
用来绑定数据模型,是控制器独有的服务.控制器中的数据需要依赖$scope服务才能传递到View视图层
$rootScope
是ng-app的作用域范围,它可以用在两个控制器之间传递数据,你可以把它看做ng的全局作用域
$sce
处理html为安全字符的一个服务 跟 ng-bind-html 配合
//view
<div ng-bind-html="html"></div>
//model
$scope.html = "<p>Hello Wscat</p>";
$scope.html = $sce.trustAsHtml($scope.html)
$http
Get请求
$http({
method:"get",
url:"Oaoafly.php"
params:{}
})
.then(function(data){
//成功的回调
},function(err){
//失败的回调
})
Post请求
$http({
method: 'post',
url: 'http://localhost:8081/search',
data: {
"page": $scope.page,
"pageNum": $scope.pageNum
},
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
},
transformRequest: function(obj) {
var str = [];
for (var p in obj) {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]))
}
return str.join('&')
}
}).then(function(data) {
console.log(data)//打印服务端返回的数据
}, function(err) {
console.log(err)//打印错误信息
});
注意点:POST请求参数处理
$filter服务
$window && $document
- $window服务对应了JS的全局window
- $document服务对应了JS的document,用的时候注意要这样用$document[0]
注意:
如果需要用到原生JS代码,最好在前面加上$window有利于解决双向绑定数值失效的问题;
$location
获取url的哈希值
var app = angular.module('app', []);
app.controller('div', function($scope,$location) {
$scope.name = 'heightzhang';
var abc = $location.search({
"foo": "yipee",
"abc":"1231"
}); //1.=>设置哈希值为 : #!?foo=yipee&abc=1231;
var def = $location.search()
console.log(def);//2.=>获取哈希值的结果为 : {abc:"1231",foo:"yipee"}
});
注意: angular使用 $location服务比使用 window.location对象更好。
angular会一直监控应用,处理事件变化,window.location 对象在angular应用中有一定的局限性.
$timeout && $interval
- $timeout服务对应了JS的window.setTimeout函数
- $interval服务对应了JS的window.setInterval函数
$scope.interval = 0;
$scope.timeout = 0;
$timeout(function(){
$scope.timeout = 1;
},1000)
$interval(function(){
$scope.interval++
},1000)
过滤器
语法
过滤器可以通过一个管道字符(|)和一个过滤器添加到表达式中
{{num|过滤器的名字:参数}}
内置过滤器
filter | methods |
---|---|
currency | currency:"货币符号" |
uppercase | uppercase大写 |
lowercase | lowercase小写 |
filter | 接受一个对象,一般配合ng-repeat |
orderBy | 接受两个参数,第一个是要排序的键值,第二个是个布尔值 |
limitTo | 可以用于分页,第一个参数就是截取的长度,第二个是截取的位置,可以用于截取字符串和数组 |
json | 就是把对象转为字符串显示,一般用于调试页面数据 |
date | 接受时间戳格式,处理成常用的时间格式 |
number | 精确到就是小数点后几位 |
$fiter服务
这个服务可以注入到过滤器或者控制器里面
在AngularJS的controller, service或者driective中使用filter
$filter("过滤器名字")("处理的数据","过滤器的参数")
前端筛选组合
orderBy和filter和limitTo 排序 搜索 分页
orderBy:A:B
接收两个参数
a是要排序的对象,b是个布尔值
true为降序 ,false为升序;
#Bug 数字排序; 存入数据库类型要是int;
实现升序或降序
filter:A|filter:B 或者接收一个对象 实现一级搜索或者二级搜索
limitTo:A:B a数量,b索引值 截取字符串或者数组,实现分页效果;
注意:过滤器支持链式调用
路由
第一种:原生路由
引入../js/angular-route.js
var app = angular.module('routeApp',['ngRoute','routes','controller','directives']);
//路由
//建立路由模块
var routes = angular.module("routes",[]);
//1.配置路由Url
routes.config(function($routeProvider){
$routeProvider.when("/home",{
templateUrl:"template/home.html"
}).when("/detail",{
templateUrl:"template/detail.html"
})
//3.路由传参
.when("/detail/:id/:skill",{
controller:"ulCtrl" //建立子控制器
templateUrl:"template/detail.html"
})
//2.默认重定向的路由路径(默认值设定)
.otherwise({
redirectTo: '/home'
})
// 注意:传参要设置两个路由,一个模版,一个传参路由;
})
//建立控制器模块;
var controller = angular.module('controller',[]);
//配置控制器
controller.controller('ulCtrl',function($scope,$routeParams){
$scope.name = 'heightzhang'
//3.路由传参 ,打印传递的url参数
console.log($routeParams)
});
controller.controller('aCtril',function($scope){
$scope.name = "zhangggao";
$scope.url = "#!/home?id=5"
});
//4.建立组件化模版
var directives = angular.module("directives", []);
directives.directive("xheader", function() {
return {
template: "<header>今日头条</header>"
}
});
第二种:UI路由
引入../js/angular-ui-router.js
//建立主模块
var app = angular.module('uirouterApp',['ui.router']);
//配置路由
app.config(function($stateProvider,$urlRouterProvider){
//设置默认路由;
$urlRouterProvider.when('', '/index');
//Angular
//一层
$stateProvider.state("index",{
url:"/index",
templateUrl:"1.2template/angular.html"
})
//"."表示从属关系
//二层
.state("index.a",{
url:"/a",
templateUrl:"1.2template/angular2.html"
})
//三层
.state("index.a.aa",{
url:"/aa",
templateUrl:"1.2template/angular3.html"
})
//Jquery
.state("home",{
url:"/home",
templateUrl:"1.2template/jquery.html"
})
.state("home.a",{
url:"/a",
templateUrl:"1.2template/jquery2.html"
})
.state("home.a.aa",{
url:"/aa",
templateUrl:"1.2template/jquery3.html"
})
//传参数
.state("detail",{
url:"/detail/:id",
//设置子控制器;
controller:"detailCtrl",
templateUrl:"1.2template/detail.html"
})
});
//接收url参数
app.controller("detailCtrl",function($state){
console.log($state.params)
});
//注意 :路由随便写也能进入网页,是不会报错的,只是你需要打印的东西无法打印出来;
我们开发中一般使用UI路由,UI路由可以嵌套;原生路由不支持嵌套
自定义过滤器
适合:修饰的复用;
//#自定义无参数过滤器:
//比如:过滤HTML结构
//格式:
<div ng-bind-html="html|htmled"></div>
app.filter("htmled", function($sce) {
return function(input) {
//input => 需要过滤的数据处理成新的数据
return $sce.trustAsHtml(input)
}
})
//#自定义有参数过滤器:
//适用在需要设置第二个数据才可以过滤的情形下;
//比如:高亮搜索内容(搜索内容为需要高亮的部分)
<div ng-bind-html="html|highlight:search"></div>
app.filter("highlight", function() {
return function(input, search) {
console.log(search)
console.log(input)
var arr = input.split(search);
var output = arr.join("<span style='color:red'>" + search + "</span>")
return output;
}
})
自定义服务
适合:方法的复用
//主模块
var app = angular.module('app', ['div','service']);
//分模块
var div = angular.module('div', []);
//分模块控制器
div.controller('divCtrl', function($scope,tool,abc,exchange) {
$scope.name = "heightzhang";
console.log(tool); //共享自定义服务;
console.log(abc); //自定义服务引用其他服务
console.log(exchange.name) //自定义服务通信, 传递数据;
});
//服务模块; 1.主模块引入服务'依赖', 所有的分模块 通过注入该新服务,可以共享新服务;
var service = angular.module('service', []);
service.service('tool', function() {
return {
add: function(a, b) {
return a + b
}
}
});
//2.第二个自定义服务中使用之前自定义服务或者内置服务的时候;用传参方法;
service.service('abc', function($http) {
return {
tool:$http
}
});
//3.service作为通信 传递数据;
service.service('exchange',function(){
return {
name:'heightzhang'
}
})
其他自定义服务;
- value就是一个简单的可注入的值
- service是一个可注入的构造器
- factory是一个可注入的方法
- decorator可以修改或封装其他的供应商,当然除了constant
- provider是一个可配置的factory
自定义组件/指令
适合:组件适合HTML结构的复用
关于自定义的四种状态
自定义组件
//自定义了一个<xheader></xheader>组件
app.directive("xheader", function() {
return {
restrict: "E", //元素
template: `
<div>
<header ng-transclude></header>
<p>Hello {{name}}</p>
</div>
`
}
})
自定义指令
//自定义了一个<div ng-header></div>的指令
app.directive("ngHeader", function() {
return {
restrict: "A", //属性
template: `
<div>
<header ng-transclude></header>
<p>Hello {{name}}</p>
</div>
`
}
})
自定义类指令
//自定义了一个<div class = "ng-header"></div>类的指令
app.directive("ngHeader", function() {
return {
restrict: "C", //类
template: `
<div>
<header ng-transclude></header>
<p>Hello {{name}}</p>
</div>
`
}
})
ECMA:
值 | value |
---|---|
element | 元素,标签 |
attribute | 属性 |
class | 类 |
m | 注释 |
Tips:
- restrict:ECMA或者不写,则默认允许呈现四种状态;
- template(模版)的规范,建议先定义一个外围容器包围;
- 控制器可以理解为唯一的ID, <span style="color: red">控制器不能去复用</span>;
replace
true:组件的自定义的标签名会消失,模版的div结构出现;
true的好处:对一些不兼容自定义表情的浏览器有好处;
false:组件的自定义标签名出现,模版的div结构也出现,
false的好处:可以方便我们进行分组管理这些组件;
replace默认值为false
controller :组件内部自身的控制器作用域;提供给template模版使用;
transclude :true 组件支持嵌入
replace \ controller transclude 简单代码如下:
<xheader><p>新闻</p></xheader>
app.directive("xheader", function() {
return {
restrict: "ECMA",
//组件自定义标签名出现
replace: false,
//组件支持嵌入<p>新闻</p>嵌入到模版<header ng-transclude></header>里面
transclude: true,
//组件的子控制器,给template模版使用
controller: function($scope, $http) {
$scope.name = "laoyao"
},
template: `
<div>
<header ng-transclude></header>
<p>Hello {{name}}</p> //子控制器的作用域是该模版区域;
</div>
`
}
})
link子控制器:
scope,ele,attr
注意:Controller与scope的区别:两者区别不大,我们开发一般会选用link;
app.directive("xheader", function($http) {
return {
//View
template: `<div>
<ul>
<li ng-repeat="arr in arrs track by $index">{{arr}}</li>
</ul>
<button ng-click="loadMore()">{{isShow}}</button> //触发事件
</div>`,
//Contrl
//link 是组件的控制器 scope是存放该组件的数据模型model;
link: function(scope, ele, attr) {
//Model
//--------1.scope----------
scope.arrs = [];
scope.loadMore = function() {
//请求后端数据返回给模版
$http({
method: "GET",
url: "http://localhost:81/1702/angular/test.php"
}).then(function(data) {
console.log(data)
scope.arrs = scope.arrs.concat(data.data.arrs)
});
//------2.ele ----jQlite----------
console.log(ele)
ele.on("click",function(){
alert("hello")
});
// ----3.attr ----------
console.log(attr) //获取xheader上的attr属性,有利于通过JQlite改变原先的attr值;
}
}
})
汇:控制器之间通信数据的方法
1.Angular事件广播
2.$rootScope
3.Cookies和本地存储
4.基于服务器Service通信数据
5.Angular基于$window的数据通信
6.路由传参(跨页面跨路由的情况)