My Little World

angularjs directive编写组件小结

1
<edit-modal dismiss="dismiss()" config="model.config" after-save="model.afterSave()" aaa="model.hello"></edit-modal>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
export function editModalDirective() {
return {
restrict: 'E',
template: template,
controller: EditModalCtrl,
bindToController: true,
controllerAs: 'ctrl',
transclude: true,
scope: {
dismiss: '&',
afterSave: '&',
config: '=',
},
link: function(scope, ele, attrs) {
if (scope.ctrl.config.type === 'Strategy') {
if (scope.ctrl.config.type === 'Strategy') {
ele[0].className += 'strategy';
}
}


},
};
}
//在模块编译时注册指令
coreModule.directive('editModal', editModalDirective);
//参考:https://www.cnblogs.com/wangnuo/p/6305742.html

link函数

link函数仅在编译时执行一次,三个参数:scope, ele, attrs

ele

即是当前的指令DOM对象,因此可以在ele上绑定触发事件,

但谨慎在数据上利用事件订阅触发机制进行事件绑定,

因为如果在外层包react组件的情况下,可能会导致数据刷新,但没有事件绑定,从而无法触发事件

注意在获取深层子dom时可能会获取不到

attrs

指ele所在dom上的属性集合,没有在scope属性中声明的属性也能看到

但要注意,属性值就是标签上变量的名,不是标签上变量指代的值

标签上属性赋值变量的值在参数scope中
attrs

scope

link函数参数scope指向当前指令的作用域

参数scope的ctrl属性(controllerAs属性的值)即EditModalCtrl

因为这里配置了controller,bindToController,controllerAs,

所以在scope属性中声明的属性(config)方法(dismiss,after)会被归并到controller中,会以ctrl的属性形式出现,

即如果我想拿到属性scope中声明的config,可以这样:scope.ctrl.config

同时可以在EditModalCtrl中访问获取config,即this.config

另外如果没有在属性scope中声明的属性aaa,但在标签中进行了配置(aaa=”model.hello”),是无效的,ctrl上是不会有aaa属性的,即传递不进来

因此可以在link函数中拿到父作用域传递过来的值,分情况进行不同处理
scope

scope属性

建立子域,声明所在标签的属性名,以及传值方式,controler存在情况下被合并

@

@ 在 directive 中使用 xxx 属性绑定父 scope 中的属性。当改变父 scope 中属性的值的时候,directive 会同步更新值,当改变 directive 的 scope 的属性值时,父 scope 无法同步更新值。使用{{}}引用绑定值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
app.controller("myController", function ($scope) {
$scope.name = "hello world";
}).directive("isolatedDirective", function () {
return {
scope: {
name: "@"
},
template: 'Say:{{name}} <br>改变隔离scope的name:<input type="buttom" value="" ng-model="name" class="ng-pristine ng-valid">'
}
})


<div ng-controller="myController">
<div class="result">
<div>父scope:
<div>Say:{{name}}<br>改变父scope的name:<input type="text" value="" ng-model="name"/></div>
</div>
<div>隔离scope:
<div isolated-directive name="{{name}}"></div>
</div>
<div>隔离scope(不使用{{name}}):
<div isolated-directive name="name"></div>
</div>
</div>

=

= 无论是改变父 scope 还是隔离 scope 里的属性,父 scope 和隔离 scope 都会同时更新属性值,因为它们是双向绑定的关系,使用“”引用绑定值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
app.controller("myController", function ($scope) {
$scope.user = {
name: 'hello',
id: 1
};
}).directive("isolatedDirective", function () {
return {
scope: {
user: "="
},
template: 'Say:{{user.name}} <br>改变隔离scope的name:<input type="buttom" value="" ng-model="user.name"/>'
}
})

<div ng-controller="myController">
<div>父scope:
<div>Say:{{user.name}}<br>改变父scope的name:<input type="text" value="" ng-model="user.name"/></div>
</div>
<div>隔离scope:
<div isolated-directive user="user"></div>
</div>
<div>隔离scope(使用{{name}}):
<div isolated-directive user="{{user}}"></div>
</div>
</div>

&

& 用来绑定函数,在directive中调用父域中的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 app.controller("myController", function ($scope) {
$scope.value = "hello world";
$scope.click = function () {
$scope.value = Math.random();
};
}).directive("isolatedDirective", function () {
return {
scope: {
action: "&"
},
template: '<input type="button" value="在directive中执行父scope定义的方法" ng-click="action()"/>'
}
})


<div ng-controller="myController">
<div>父scope:
<div>Say:{{value}}</div>
</div>
<div>隔离scope:
<div isolated-directive action="click()"></div>
</div>
</div>

参考: https://blog.coding.net/blog/angularjs-directive-isolate-scope?type=early

transclude

类似于VUE的slot,但不如slot的灵活强,更倾向于定制插入,在固定位置插入

单点嵌入

设置属性 transclude:true

在模板中将 <ng-transclude></ng-transclude>放到要插入的位置

应用时<my-labe><span>1233</span></my-label>;

<span>1233</span> 会自动插入<ng-transclude></ng-transclude>之间

多点嵌入

设置属性 transclude :{模板中flag:页面应用时标签名的驼峰式,}

在模板中制定位置放置flag :<div ng-transclude=”flag”></div>

应用时 <my-label><my-title>123</my-title></my-label>

123 会自动插入<div ng-transclude=”flag”></div>之间

参考:https://segmentfault.com/a/1190000004586636

scope绑定

使用transcludeFn给transclude进来的Dom手动制定scope,

transcludeFn可来自compile,link的参数,或者controller的注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
.directive("todo", function(){

return {
restrict:"E",
transclude:"true",
template:"<header>{{header}}</header><div><span>这里是自定义区域</span><content-transclude></content-transclude></div>"
scope:{
header:"@"
},
controller:["$transclude",function(transcludeFn){
this.transcludeFn = transcludeFn;
}]
};
})

.directive("contentTransclude",funtion(){
return {
restrict:"E",
require:"^todo",
link:function(scope,element,attr,todoController){
todoController.transcludeFn(scope.$parent, function(transcludeContent){
element.append(transcludeContent);
});
}
};
})

参考:https://blog.csdn.net/shut1k/article/details/49848637