今天接着学习指令
ng-style和ng-class一样也可用于动态设置CSS样式
ng-style属性通常被解析为一个js对象(实际上就该算是css中定义的一个类),而昨天学的ng-class是可以根据不同情况解析为字符串和js对象的
解析为字符串的用法就是这样:
<p ng-class="style" >使用字符串</p>
<input type="text" ng-model="style" placeholder="输入:xxxxx">
<hr>
而ng-style虽然也是解析为js对象,但是和ng-class还是不同的,后者是key:boolean的形式(key是有效的css类),前者是属性名:属性值的形式
具体用法看下面一个例子:
<body ng-app>
<input type="button" value="red" ng-click="myStyle={color:'red'}" />
<input type="button" value="blue" ng-click="myStyle={'background-color':'blue'}" >
<input type="button" value="清除" ng-click="myStyle={}"><br/>
<span ng-style="myStyle" >验视章色</span>
<pre>{{myStyle}}</pre>
</body>
这里直接ng-style=一个标准的键对类型就可以了,而ng-class使用时是=类名,像上上面那个例子,因为绑定了input内的内容,所以当输入bold时,style变成了bold,样式也变成了bold
ng-list
这个指令可以把文本框内的字符串按英文逗号分隔成数组,同时你也可以自定义分隔符,通过ng-list=zz设置
<body ng-app>
<form name="my">
输入逗号隔开的字符串<input name="namesInput" ng-model="names" ng-list required >
<span style="color:red;font-size: 10pt" ng-show="my.namesInput.$error.required">你倒是填啊</span>
<p>
<tt>names={{names}}</tt><br>
<tt>my.namesInput.$valid={{my.namesInput.$valid}}</tt><br>
<tt>{{my.namesInput.$error}}</tt><br>
<tt>{{my.$valid}}</tt><br>
<tt>{{!!my.$error.required}}</tt><br>
</form>
</body>
ng-include指令
他的功能是动态地包含目标页面?
使用该指令的时候还可以额外指定如下属性
onload:指定目标页面加载时触发的实践处理函数
autoscroll:指定目标页面是否支持滚动,只有属性为空值或者true的时候,支持滚动,不设置不支持
<body ng-app="app" ng-controller="ctrl" >
<select ng-model="template">
<option value="111" >空白</option>
<option value="xx" >xxx</option>
<option value="yy" >yyy</option>
</select>
<br>
被加载的页面:<code>{{template}}</code>
<hr>
<div class="slide">
<div class="a" ng-include="template"></div>
</div>
<script type="text/javascript">
angular.module("app",[])
.controller("ctrl",function($scope){
});
</script>
</body>
这个涉及到跳转页面的内容我具体也不好实现,就留到以后用到在说吧
除了上面的学的一些内置指令,AngularJS允许开发者执行开发自定义指令
调用Angular.Module对象的-----direrctive(name,directiveFactory)----方法
第一个参数name是自定义指令的名称
第二个参数directiveFactory是一个函数,该函数负责返回一个js对象
该js对象支持以下的属性:
template:该属性指定对应的模板内容
templateUrl:和前者差不多,用于模板太多时放在单独的文件中,用+url的指向
restrict:EACM最多4中适应格式,分别是元素、属性、样式、注释
replace:如果将其设置为true,则对应的html模板会完全替代指定该指令的元素
priority::描述优先级
replace:
terminal:
scope:设置标签的scope行为
transclude
link:指定一个函数,为DOM元素绑定事件处理函数
compile:指定一个函数,修改目标DOM元素
controller:用于分配一个函数
require:用于指定一个指令需要调用另一个自定义指令的函数时的依赖指令
注意:在html中使用指令时用烤串写法(ng-xx)。在js中用到指令的时候用驼峰写法(ngXx)
<body ng-app="app">
<fk-a></fk-a>
<div fk-a >xxx</div>
<hr>
<div class="fk-a">yyy</div>
<hr><hr><hr><hr>
<script>
angular.module('app',[])
.directive('fkA',function(){
return{
restrict:"EACM",
template:'<p>第一条指令</p>'
}
});
</script>
</body>
这是一个简单的自定义指令,restrict表明了适用范围,这里是4种情况都可以,然后template规定了模板
下面继续自定义指令的其他属性
replace很好理解,他对应的值如果是true的话,会将原本的元素完全替换
然后是scope属性
自定义的scope属性用于设置对应的scope行为,那么什么是scope行为呢?
scope属性支持以下属性:
false:就是让所在标签直接使用父scope,据说比较危险
true:所在标签继承父scope,然后父scope的变量也会随之传入该标签
JS对象:创造一个独立隔离的scope,可以和父的scope安全通信
这是直接使用父的scope的
<body ng-app="app">
<p>父:<input type="text" ng-model="name" /></p>
<fk-dir></fk-dir>
<script>
angular.module('app',[])
.directive('fkDir',function(){
return{
replace:true,
template:'<div>\
<p>自定义的scope:<input type="text" ng-model="name" /></p>\
<p>结果:{{name}}</p>\
<div>',
scope:false
}
});
</script>
</body>
这是继承父的scope的
<body ng-app="app">
<p>父:<input type="text" ng-model="name" /></p>
<fk-dir></fk-dir>
<script>
angular.module('app',[])
.directive('fkDir',function(){
return{
replace:true,
template:'<div>\
<p>自定义的scope:<input type="text" ng-model="name" /></p>\
<p>结果:{{name}}</p>\
<div>',
scope:true
}
});
</script>
</body>
这两个运行的区别就在于直接使用的那个,相当于和父没差,内容和父是同步,父加,她也加,她加,父也加,但是第二个继承的就不是这样,刚开始子没加过时,父加,子也加,当子加过一次后,就不再收到父的影响,独立了,前面一个相当于啃老,后一个就是成年独立的。
如果需要多次重复使用自定义指令,就不能像前面的一样依赖父的scope,也就是说,从出生起就要独立
为了将父scope的变量传入自定义的指令中,AngularJS提供了3种绑定方式
1.@:单向绑定,只能捡父scope中的字符串值传入自定义scope中,只针对字符串
2.=:这种绑定支持解析变量
3.&:用于将父scope中函数绑定到自定义指令的scope中
<body ng-app="app" ng-controller="ctrl">
<fk-panel title="bookTitle" my-data="books"></fk-panel>
<hr />
<div fk-panel title="bookTitle" my-data="books"></div>
<script>
angular.module('app',[])
.controller('ctrl',function($scope){
$scope.bookTitle="xxx";
$scope.books = ["1","2","3"];
})
.directive('fkPanel',function(){
return{
restrict : 'EA', //E是元素,A是属性
replace : true, //表示完全替代
scope:{
title:'=', //表示支持解析变量
myData : '='
},
template : '<div><h3>{{title}}</h3>\
<ul><li ng-repeat="data in myData">{{data}}</li></ul></div>',
}
});
</script>
</body>
上述代码实现了使用自定义的指令替换了原来的html模板,使元素以指令里面编写的格式呈现
自定义指令中的transclude属性
是一个Boolean属性值,用来实现把原始的内容嵌入到自定义的指令模板中
具体实现分为两步:
1.将自定义指令中的transclude属性设置为true
2.使用ng-transclude指令将原始元素内部的内容插入到自定义指令的模板中
**
代码<ng-transclude></ng-transclude>
所在的位置就是原始元素插入内嵌的位置
自定义指令属性之link、compile
link是用来绑定事件处理函数的,它能接受一个形如function(scope,element,attrs,[controller]{ }的函数
下面是几个参数的解析:
scope:表示当前自定义对应的scope
element:表示自定义指令模板中html元素被封装成的jqLite对象。如果在页面开始就导入了jQuery库,那么对象就是jQuery
attrs:表示该html元素上的自定义属性
controller:可选的控制器参数
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
</head>
<body ng-app="app" ng-controller="ctrl">
<my-tab my-id="div1" my-data="sports" class="fk-tab" width="400" height="120"></my-tab>
<my-tab my-id="div2" my-data="books" class="fk-tab" width="300" height="90"></my-tab>
<script>
var app = angular.module('app',[]);
app.controller('ctrl',function($scope){
$scope.sports = [
{title:'HTML 5',content:'html是xxx'},
{title:'jQuery',content:'jjjjjj'},
{title:'AngularJS',content:'aaaaa'}
];
$scope.books=[
{title:'sss',content:'1111'},
{title:'xxx',content:'7474'}
];
});
app.directive('fkTab',function(){
return {
restrict:'E',
replace:true,
scope:{
myId:'@',
myData:'=',
width:'@',
height:'@'
},
templateUrl:'panel.html',
link:function(scope,element,attr){
element.on('click','input',function(){
var self = $(this);
var i = self.index();
self.addClass('active').siblings('input').removeClass('active');
self.siblings('div').eq(i).show().siblings('div').hide();
});
}
};
});
</script>
</body>
</html>
panel:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
</head>
<body ng-app>
<div id="{{myId}}">
<input ng-repeat = "data in myData" type="button" ng-value="data.title" ng-class="{active:$last}" />
<div ng-repeat="data in myData" ng-bind-html="data.content" ng-style="border:'1px solid black',height:'{{height}}px',width:'{{width}}px',display:$last?'block':'none'"></div>
</div>
</body>
</html>
上面的代码是书上的一段关于link的,我跑不通,下午人迷迷糊糊的看了半天没看出来原因,留下个小问题,日后复习看到的时候再解决
下面这个是关于compile的
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js"></script>
</head>
<body ng-app="app" ng-controller="ctrl">
<table border="1" width="600">
<tr ng-repeat="book in books" fk-dir1 fk-dir2 ></tr>
</table>
<script>
var app = angular.module('app',[]);
app.directive('fkDir1',function(){
return {
templste:'<td width=60%>{{ book.name }}</td>',
compile:function(element,attrs,transclude){
console.log('开始了');;
element.append(angular.element('<td>{{book.price}}</td>'));
return {
pre:function preLink(scope,iElement,iAttrs,controller){
console.log('fkDir1 preLink函数');
},
post:function postLink(scope,iElement,iAttrs,controller){
iElement.on('click',function(){
scope.$apply(function(){
scope.book.name = '修改的书名';
scope.book.price = ++scope.book.price;
});
});
console.log('fkDir1 ppostLink函数');
}
};
},
link:function(scope,iElement,iAttrs,bookListController){
console.log("......")
}
}
})
app.directive('fkDir2',function(){
return {
compile:function(element,attrs,transclude){
console.log('fkDir2开始');
return {
pre:function preLink(){
console.log('fkDir2 preLink');
},
post:function postLink(){
console.log('fkDir2 ppppp');
}
};
}
}
})
app.controller('fkCtrl',function($scope){
$scope.books = [
{id:1,name:'xxxxxxxxxx',price:22},
{id:2,name:'sddadsd',price:11},
{id:3,name:'sdaadsff',price:44},
];
});
</script>
</body>
</html>