The release of AngularJS V1.7.1* https://github.com/angular/angular.js/blob/master/CHANGELOG.md#171-momentum-defiance-2018-06-08 introduces the new ng-ref directive https://docs.angularjs.org/api/ng/directive/ngRef#overview. While this new directive enables users to easily do certain things, I see great potential for abuse and problems.
The ng-ref https://docs.angularjs.org/api/ng/directive/ngRef#overview属性告诉 AngularJS 在当前范围内发布组件的控制器。这对于让音频播放器等组件向同级组件公开其 API 非常有用。其播放和停止控件可以轻松访问。
第一个问题是播放器控件undefined
在 - 的里面$onInit
控制器的功能。
Initial vm.pl = undefined <<<< UNDEFINED
Sample = [true,false]
对于依赖于可用数据的代码,我们该如何解决这个问题?
The DEMO http://plnkr.co/edit/Vt8zj589iuNYAjeNLq1E?p=preview
angular.module("app",[])
.controller("ctrl", class ctrl {
constructor() {
console.log("construct")
}
$onInit() {
console.log("onInit", this.pl);
this.initPL = this.pl || 'undefined';
this.sample = this.pl || 'undefined';
this.getSample = () => {
this.sample = `[${this.pl.box1},${this.pl.box2}]`;
}
}
})
.component("player", {
template: `
<fieldset>
$ctrl.box1={{$ctrl.box1}}<br>
$ctrl.box2={{$ctrl.box2}}<br>
<h3>Player</h3>
</fieldset>
`,
controller: class player {
constructor() {
console.log("player",this);
}
$onInit() {
console.log("pl.init", this)
this.box1 = true;
this.box2 = false;
}
},
})
<script src="//unpkg.com/[email protected] /cdn-cgi/l/email-protection/angular.js"></script>
<body ng-app="app" ng-controller="ctrl as vm">
Initial vm.pl = {{vm.initPL}}<br>
Sample = {{vm.sample}}<br>
<button ng-click="vm.getSample()">Get Sample</button>
<br>
<input type="checkbox" ng-model="vm.pl.box1" />
Box1 pl.box1={{vm.pl.box1}}<br>
<input type="checkbox" ng-model="vm.pl.box2" />
Box2 pl.box2={{vm.pl.box2}}<br>
<br>
<player ng-ref="vm.pl"></player>
</body>
获取对组件控制器的引用并不是什么新鲜事,当时的指令允许这样做,这根本不是问题,有必要拥有这样的功能,ng-ref
只是帮助您从模板端执行此操作(与 Angular 2+ 的方式相同)。
然而,如果您需要准备好子组件,您应该使用$postLink()
代替$onInit
. $postLink
在组件与其子组件链接后调用,这意味着ng-ref
当它被调用时就会准备好。
所以你所要做的就是改变你的onInit
像这样:
̶$̶o̶n̶I̶n̶i̶t̶(̶)̶ ̶{̶
$postLink() {
console.log("onInit", this.pl);
this.initPL = this.pl || 'undefined';
this.sample = this.pl || 'undefined';
this.getSample = () => {
this.sample = `[${this.pl.box1},${this.pl.box2}]`;
}
}
$postLink()
- 链接此控制器的元素及其子元素后调用。与 post-link 函数类似,此钩子可用于设置 DOM 事件处理程序并进行直接 DOM 操作。请注意,包含 templateUrl 指令的子元素不会被编译和链接,因为它们正在等待其模板异步加载,并且它们自己的编译和链接已暂停,直到发生这种情况。这个钩子可以被认为类似于ngAfterViewInit
and ngAfterContentInit
Angular 中的钩子。由于 AngularJS 中的编译过程相当不同,因此没有直接映射,升级时应小心。
Ref.: 了解组件 https://docs.angularjs.org/guide/component
完整的工作片段可以在下面找到(我删除了所有console.log
为了更清楚):
angular.module("app",[])
.controller("ctrl", class ctrl {
constructor() {
//console.log("construct")
}
$postLink() {
//console.log("onInit", this.pl);
this.initPL = this.pl || 'undefined';
this.sample = this.pl || 'undefined';
this.getSample = () => {
this.sample = `[${this.pl.box1},${this.pl.box2}]`;
}
}
})
.component("player", {
template: `
<fieldset>
$ctrl.box1={{$ctrl.box1}}<br>
$ctrl.box2={{$ctrl.box2}}<br>
</fieldset>
`,
controller: class player {
constructor() {
//console.log("player",this);
}
$onInit() {
//console.log("pl.init", this)
this.box1 = true;
this.box2 = false;
}
},
})
<script src="//unpkg.com/[email protected] /cdn-cgi/l/email-protection/angular.js"></script>
<body ng-app="app" ng-controller="ctrl as vm">
Initial vm.pl = {{vm.initPL}}<br>
Sample = {{vm.sample}}<br>
<button ng-click="vm.getSample()">Get Sample</button>
<br>
<input type="checkbox" ng-model="vm.pl.box1" />
Box1 pl.box1={{vm.pl.box1}}<br>
<input type="checkbox" ng-model="vm.pl.box2" />
Box2 pl.box2={{vm.pl.box2}}<br>
<player ng-ref="vm.pl"></player>
</body>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)