Angular JS(2)
关于angularjs的特点
1.数据的双向绑定:这可能是其最激动人心的特性吧,view层的数据和model层的数据是双向绑定的,其中之一发生更改,另一方会随之变化,这不用你写任何代码!(想想jQuery方式下怎么做吧)
2.代码模块化,每个模块的代码独立拥有自己的作用域,model,controller等。
3.强大的directive可以将很多功能封装成HTML的tag,属性或者注释等,这大大美化了HTML的结构,增强了可阅读性;
4.依赖注入,将这种后端语言的设计模式赋予前端代码,这意味着前端的代码可以提高重用性和灵活性,未来的模式可能将大量操作放在客户端,服务端只提供数据来源和其他客户端无法完成的操作;
5.测试驱动开发,angularjs一开始就以此为目标,使用angular开发的应用可以很容易地进行单元测试和端对端测试,这解决了传统的js代码难以测试和维护的缺陷
1、自定义指令
可以通过自定义指令实现高度复用的模块
app.directive(directiveName,function(){
//directiveName 建议驼峰命名
return {
template : HtmlString 模板内容
//replace 为 true 时,必须返回唯一一个根节点
restrict : String 指令渲染方式
// E 标签 C class M 注释 A 属性,最长使用的时E、A
replace : Bolean 是否替换为原节点(当渲染方式为M时 ,replace 必须为true,才能生效)
controller : String | Function 指定或创建一个控制器
// 当为String 时,要求所指定的控制器必须被创建
//当为Function 时,接受 scope 形参
}
})
在正式的开发过程中,为了实现指令的复用,指令不应该影响父级的数据,而数据来源也不应该是直接使用父级数据,而是要由父级传入数据。
scope:{
//创建一个隔离的作用域,不是直接使用父级数据
@ | @attrName: 单项数据(字符串)传递
= | =attrName : 双向数据(变量)传递
& | &attrName :父级方法传递
当只有单个字符时,要求键名与标签的属性名相同,如果标签属性有横线,键名要使用驼峰命名式:如:<h1 p-msg = " "></h1> === pMsg:"@"
}
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<meta charset="utf-8">
<title></title>
<script src="./angular.min.js" charset="utf-8"></script>
</head>
<body ng-controller="mainController">
原父级内容pmsg: {{pmsg}}
<input type="text" ng-model="pmsg">
<my-directive msg1="abc" a="def" per-msg="ghi" b={{pmsg}} c="pmsg" d="pEvent(m)"> </my-directive>
</body>
<script type="text/javascript">
angular.module("myApp",[])
.controller("mainController",["$scope",function($scope){
$scope.pmsg = "父级内容";
$scope.pEvent = function(m){
console.log("事件被执行",m);
return "a";
}
}])
.directive("myDirective",function(){
return {
scope:{
msg1:"@",
msg2:"@a",
perMsg : "@",
pmsg :"@b",
c : "=",
d : "&"
}
,template : `
<div>
<h2>自定义指令</h2>
使用父级的消息: {{pmsg}}
<input type="text" ng-model="pmsg"/>
<h3 style="background:red;">{{msg1}}</h3>
<h3>{{msg2}}</h3>
<h3>{{perMsg}}</h3>
<input type="text" ng-model = "c">
<h3>{{d({m:"此消息来自子级"})}}</h3>
</div>
`
,link:function(scope,el,attrs){
// console.log(scope,el,attrs)
//angular 内置轻量级的jQuery 名字叫jqLite
//link 阶段操作DOM是安全的,常用于事件添加或样式后修改
angular.element(el).find("h3").css("background","pink")
}
,controller : "myController"
}
})
.controller("myController",["$scope",function($scope){
$scope.cmsg = "指令变量 cmsg 内容"
}])
</script>
</html>
绑定html
Sanitize 模块 过滤净化 html 字符串
会将标签上的属性全部移除,只保留一个干净的标签
使用方法: 引入 angular-sanitize 脚本
在模块中依赖ngSanitize
就可以直接使用 ng-bind-html了
内置$sce 服务,用来信任某html 字符串
在控制器中依赖此服务
调用$sce.trustAsHtml(htmlStr)方法,信任传入的html
返回被信任的html,可使用 ng-bind-html
使用$sce 信任html,请确保html 是安全的(风险自行承担)
脏查询
脏查询机制:$digest
$watch ==> $watcher list
$watch 监听数据变化
$apply() 手动强制触发脏查询
$timeout
$interval
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="./angular.min.js"></script>
</head>
<body ng-controller="myController">
{{name}}
<input type="text" ng-model="a">
</body>
<script>
angular.module("myApp",[])
.controller("myController",["$scope","$timeout",function($scope){
$scope.name="sun";
setTimeout(function(){
$scope.name="new name";
console.log($scope.name);
},1000);
$scope.$watch("name",function(){
console.log(arguments)
})
// setTimeout(function(){
// $scope.name="new name";
// console.log($scope.name);
// $scope.$apply();
// },1000)
}])
</script>
</html>
$http
angular-resource 用来发送网络请求的模块,依赖于ngResource ,可以发RESTful等请求
angular.module("myApp",[])
.controller("myController",["$scope","$http",function($scope,$http){
$scope.items=[];
//动态的请求数据
//$httop.get() 返回一个promise 对象
//success 和 error 只是语法糖,是对then()的封装
$http.get("./data.json").success(function(res){
console.log(res)
});
}])
依赖注入
angular 提供五个可被直接注入的服务,分别是:
service 单例的,调用时会自动使用new关键字,返回的是同一个实例;适用于数据持久化(共享数据或与后台通信)
factory 工厂服务(适用于通用的逻辑计算、工具类的东西)
value 创建变量
constant 创建常量,可以注入到任何地方(config阶段)
provider
注意:不要试图去复用控制器,一个控制器一般只负责一小块视图;
不要在控制器里操作DOM,这不是控制器的职责,而是指令的职责;不要在控制器里做数据格式化,ng有很好用的过滤器实现此功能;不要在控制器里面做数据过滤操作,ng有$filter服务;一般来说,controller是不会互相调用的,控制器之间的交互是通过事件进行的。
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="./angular.min.js"></script>
</head>
<body ng-controller="myController"></body>
<script>
var app = angular.module("myApp",[]);
app.config(function(z5Provider){
});
app.controller("myController",[
"$scope","z1","z2","z3","z4","z5"
,function($scope,z1,z2,z3,z4,z5){
z1();
z2.say();
console.log(z2);
console.log(z3())
console.log(z4)
console.log(z5)
}])
app.factory("z1",function(){
return function(){
console.log("这是z1-factory")
}
})
app.service("z2",function(){
this.name="abc",
this.say = function(){
console.log("这是z2-service",this.name)
}
})
app.value("z3",function(){
return "这是z3-value"
})
app.constant("z4","3.14");
app.provider("z5",function(){
this.$get = function(){
return "这是z5-provider"
}
})
</script>
</html>
路由配置文件
配置路由规则需要在 config 阶段
1、引入 ui-router 脚本
2、在 app 创建时加载* ui.router* 依赖
3、在* config* 阶段,注入$stateProvider、$urlRouterProvider
4、在页面中声明ui-view 元素 声明跳转链接 a * ui-sref*
http://mockjs.com/
生成随机数据,拦截 Ajax 请求