一、自定义标签
1、在JS里,使用驼峰命名法来命名,如:myDirective;在html页面调用该指令时需要以 - 分割,如: my-directive。
2、在自定义组件中,template,构成DOM,(1)compile,生成DOM、监听DOM、修改呈现内容,(2)controller:用来提供可在指令间复用的行为,(3)link,在compile后操作DOM,需要用scope.$apply(scope.doSomething())调用scope.doSomething()。
if (that.alertHtml && that.alertMethod) {
that.alertScope = $rootScope.$new();
angular.extend(that.alertScope, that.alertMethod);
angular.element(document.getElementById('#myAlert')).empty().append($compile(angular.element(that.alertHtml))(that.alertScope));
//$compile(DOM元素)(作用域)
}
示例一:
<!DOCTYPE html>
<html lang="en" ng-app="appModule" >
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="https://cdn.bootcss.com/angular.js/1.5.8/angular.js"></script>
</head>
<body >
<div ng-controller="parent">
{{ message }}
<div otc-dynamic></div>
</div>
</body>
</html>
<script>
var app = angular.module('appModule',[]);
app.controller("parent",function($scope){
$scope.label = "Please click";
$scope.message = "点击-前";
$scope.doSomething = function(){
$scope.message = "点击-后";
};
});
/*app.directive("otcDynamic",function(){
return{
template:"<button ng-click='doSomething()'>{{label}}</div>"
};
});*/
app.directive("otcDynamic", function(){
return {
link: function(scope, element){
element.html("<button ng-click='doSomething()'>点击</button>");//这是数据绑定,能绑定事件的compile早已经执行完毕
element.on("click",function () {
scope.$apply(scope.doSomething());//此处换成scope.doSomething(),点击后不会执行
});
}
};
});
</script>
二、自定义标签嵌套
示例二:
<!DOCTYPE html>
<html lang="en" ng-app="appModule" ng-controller="ancestorCtrl">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<my-parent>
{{ancestorName}}
<my-child selfAttr="myAttr">{{childName}}</my-child>
</my-parent>
<script type="text/javascript" src="https://cdn.bootcss.com/angular.js/1.5.8/angular.js"></script>
<script>
var app = angular.module('appModule', []);
app.controller("ancestorCtrl", function ($scope) {
$scope.ancestorName = "我所处的位置,表明我只能在ng-transclude里出现。";
$scope.childName = "变量必须定义在作用域里,myParent和myChild的作用域我进不去。";
});
app.directive('myParent', function () {
return {
template: "<div><p>第一段</p>" + "<div ng-transclude></div>" + "<p>第二段</p>" + "<div>{{parentName}}</div></div>",
//template: '<div>我是指令生<div ng-transclude></div>成的内容</div>',//templateUrl导入自定义元素的模板
restrict: 'E',//指令类型 E:element A:attribute M:comment C: class
replace: true,//模板放在<my-parent>内部还是取代它,默认是false,放在其内部
transclude: true,//是否保留自定义指令开闭标签之间的内容,该内容插入模板中使用ng-transclude属性的地方,默认为false,如上。<div ng-view></div>通过路由放入数据
scope: {
//获取自定义标签的属性值//false:继承父作用域;true:继承父作用域且创建独立作用域;{}:不继承父作用域且创建独立作用域。
//scope:{name:'@name',绑定字符串 name:'=name',绑定变量 name:'&name',绑定函数}。传进来的变量,在值改变后,父作用域的该变量的值也随之改变。
},
controller: function ($scope) {/*左边的controller是上面template的控制器*/
//指令的controller和link可以进行互换。controller主要是用来(1)提供可在指令间复用的行为;(2)导入内置或自定义服务。
$scope.focusAAA = function () {
};
$scope.parentName = "定义在myParent里的变量。";
this.parentMethod = function () {
console.log('这个方法是给子作用域调用的。');
}
},
/* compile: function(element, attributes) {
//compile和link是相斥的。如果同时设置了两项,compile返回的函数会被当作链接函数把后面定义的link函数所取代,也就是说,后面的link函数将起不到作用。controller先运行,compile后运行,link不运行
},*/
link: function (scope, element, attr, ctrl, linker) {
//指令的controller和link可以进行互换。link主要是用来(1)定义当前指令内部的行为,无法在指令间复用;(2)不能导入内置或自定义服务。
//scope:指令所在的作用域
//element:指令元素的封装,可以调用angular封装的简装jq方法和属性,如element.css()
//attr:指令元素的属性的集合,如attr.selfAttr
//ctrl:用于调用其他指令的方法,指令之间的互相通信使用,需要require配合,如下面myChild内部、link中的ctrl.parentMethod()。
//linker:用于操作transclude里面嵌入的内容;linker函数有2个参数,第1个参数scope,第2个参数是函数,函数接受参数clone,clone就是transclude里面被嵌套的内容
}
}
});
app.directive('myChild', function () {
return {
template: "<div><span>这里是span1;</span><span>这里是span2。</span><div ng-transclude></div></div>",
restrict: 'E',
replace: true,
transclude: true,
scope: {},
require: '?^myParent',//?不要抛出异常;^允许查找父元素的controller
controller: function ($scope) {
},
/*compile: function(element, attributes) {},*/
//'myParent':在当前指令中查找控制器;'^myParent'在上游指令中查找控制器;'?^myParent':当前指令若没有,就向上游查找
link: function (scope, element, attr, ctrl, linker) {
ctrl.parentMethod();
linker(scope, function (clone) {
console.log(clone.text())
})
}
}
})
</script>
</body>
</html>