Javascript 如何在 Angular 1.5 组件中等待绑定(没有 $scope.$watch)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35639435/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to wait for binding in Angular 1.5 component (without $scope.$watch)
提问by tcmoore
I'm writing an Angular 1.5 directive and I'm running into an obnoxious issue with trying to manipulate bound data before it exists.
我正在编写一个 Angular 1.5 指令,我遇到了一个令人讨厌的问题,试图在绑定数据存在之前对其进行操作。
Here's my code:
这是我的代码:
app.component('formSelector', {
bindings: {
forms: '='
},
controller: function(FormSvc) {
var ctrl = this
this.favorites = []
FormSvc.GetFavorites()
.then(function(results) {
ctrl.favorites = results
for (var i = 0; i < ctrl.favorites.length; i++) {
for (var j = 0; j < ctrl.forms.length; j++) {
if (ctrl.favorites[i].id == ctrl.newForms[j].id) ctrl.forms[j].favorite = true
}
}
})
}
...
As you can see, I'm making an AJAX call to get favorites and then checking it against my bound list of forms.
如您所见,我正在通过 AJAX 调用获取收藏夹,然后根据绑定的表单列表进行检查。
The problem is, the promise is being fulfilled even before the binding is populated... so that by the time I run the loop, ctrl.forms is still undefined!
问题是,甚至在填充绑定之前就已经实现了承诺......所以当我运行循环时,ctrl.forms 仍然未定义!
Without using a $scope.$watch (which is part of the appeal of 1.5 components) how do I wait for the binding to be completed?
不使用 $scope.$watch (这是 1.5 组件吸引力的一部分)如何等待绑定完成?
采纳答案by Cosmin Ababei
You could use the new lifecycle hooks, specifically $onChanges
, to detect the first change of a binding by calling the isFirstChange
method. Read more about this here.
您可以使用新的生命周期钩子,特别$onChanges
是通过调用isFirstChange
方法来检测绑定的第一次更改。在此处阅读更多相关信息。
Here's an example:
下面是一个例子:
<div ng-app="app" ng-controller="MyCtrl as $ctrl">
<my-component binding="$ctrl.binding"></my-component>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.4/angular.js"></script>
<script>
angular
.module('app', [])
.controller('MyCtrl', function($timeout) {
$timeout(() => {
this.binding = 'first value';
}, 750);
$timeout(() => {
this.binding = 'second value';
}, 1500);
})
.component('myComponent', {
bindings: {
binding: '<'
},
controller: function() {
// Use es6 destructuring to extract exactly what we need
this.$onChanges = function({binding}) {
if (angular.isDefined(binding)) {
console.log({
currentValue: binding.currentValue,
isFirstChange: binding.isFirstChange()
});
}
}
}
});
</script>
回答by Ced
I had a similar issue, I did this to avoid calling the component until the value I am going to send is ready:
我有一个类似的问题,我这样做是为了避免在我要发送的值准备好之前调用组件:
<form-selector ng-if="asyncValue" forms="asyncValue" ></form-selector>
回答by Oli
The original poster said :
原海报说:
the promise is being fulfilled even before the binding is populated... sot hat by the time I run the loop, ctrl.forms is still undefined
甚至在绑定填充之前就已经实现了承诺......当我运行循环时,ctrl.forms 仍然未定义
Ever since AngularJS 1.5.3, we have lifecycle hooksand to satisfy the OP's question, you just need to move the code that is depending on the bindings being satisfied inside $onInit()
:
从 AngularJS 1.5.3 开始,我们就有了生命周期钩子,为了满足 OP 的问题,您只需要移动依赖于内部满足的绑定的代码$onInit()
:
$onInit() - Called on each controller after all the controllers on an element have been constructed and had their bindings initialized (and before the pre & post linking functions for the directives on this element). This is a good place to put initialization code for your controller.
$onInit() - 在元素上的所有控制器都被构造并初始化它们的绑定之后(以及在此元素上的指令的前后链接函数之前)在每个控制器上调用。这是放置控制器初始化代码的好地方。
So in the example:
所以在例子中:
app.component('formSelector', {
bindings: {
forms: '='
},
controller: function(FormSvc) {
var ctrl = this;
this.favorites = [];
this.$onInit = function() {
// At this point, bindings have been resolved.
FormSvc
.GetFavorites()
.then(function(results) {
ctrl.favorites = results;
for (var i = 0; i < ctrl.favorites.length; i++) {
for (var j = 0; j < ctrl.forms.length; j++) {
if (ctrl.favorites[i].id == ctrl.newForms[j].id) {
ctrl.forms[j].favorite = true;
}
}
}
});
}
}
So yes there is a $onChanges(changesObj)
, but $onInit()
specifically addresses the original question of when can we get a guarantee that bindings have been resolved.
所以是的,有一个$onChanges(changesObj)
,但$onInit()
专门解决了我们什么时候可以保证绑定已经解决的原始问题。
回答by tperdue321
I had a similar problem and I found this article very helpful. http://blog.thoughtram.io/angularjs/2016/03/29/exploring-angular-1.5-lifecycle-hooks.html
我有一个类似的问题,我发现这篇文章非常有帮助。 http://blog.thoughtram.io/angularjs/2016/03/29/exploring-angular-1.5-lifecycle-hooks.html
I have an ajax call that hits the server on page load and my component needs the ajax return value to properly load. I implemented it this way:
我有一个 ajax 调用,它在页面加载时命中服务器,我的组件需要 ajax 返回值才能正确加载。我是这样实现的:
this.$onChanges = function (newObj) {
if (newObj.returnValFromAJAX)
this.returnValFromAJAX = newObj.returnValFromAJAX;
};
Now my component works perfectly. For reference I am using Angular 1.5.6
现在我的组件完美运行。作为参考,我使用的是 Angular 1.5.6