为什么我的组件绑定在其控制器中未定义?
Why are my component bindings undefined in its controller?
我正在编写一个简单的 angular 组件。我将一个参数作为绑定传递并在屏幕上显示它的值。一切正常:我可以看到屏幕上显示的参数。
组件:
var app = angular.module("test", []);
app.component("test", {
bindings: {
"contactId": "<"
},
controllerAs: "model",
controller: () => {
//output: 'contact id from controller: undefined'
console.log(`contact id from controller: ${this.contactId}`);
},
template: "<div>Contact id from view: {{model.contactId}}</div>"
});
Html:
<test contact-id="8"></test>
但是,当我尝试从控制器内部访问绑定时(参见 console.log),绑定值为 undefined
。我不明白它如何在视图中可用,但在控制器中不可用。
我做错了什么?
这里 plnkr 说明了这个问题。
当使用 angular 的组件时,有一点控制器没有通过内部 链接 连接。如果您尝试在控制器的构造函数中执行此操作,则说明您尚未链接 到绑定。组件 API 公开了一些您可以定义的生命周期挂钩,这些挂钩将在特定时间触发。您正在寻找 $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.
关键字 this 似乎不适用于箭头函数,这适用于
controller: function() {
alert('contact id from controller: ' + this.contactId);
}
当使用箭头函数时,this,似乎指的是window对象,因为
An arrow function does not create it's own this context, rather it
captures the this value of the enclosing context
contactId
的值在您控制器的 $scope
上可用:
var app = angular.module("test", []);
app.component("test", {
bindings: {
"contactId": "<"
},
controllerAs: "model",
controller: ($scope) => {
var model = $scope.model;
alert(`contact id from controller: ${model.contactId}`);
},
template: "<div>Contact id from view: {{model.contactId}}</div>"
});
Link 到另一个版本的 Plunker here.
确保在 HTML 中使用 连字符 绑定,在 Javascript.
中使用驼峰式绑定
app.component("test", {
bindings: {
"myContactId": "<"
}
}
<test my-contact-id="8"></test>
那是我总是忘记做的事情。
这可能不是最佳做法,但您可以更轻松地访问这些值:
$scope.$ctrl.contactId
您可以在 $scope 内的 属性 $ctrl 中获取所有绑定。
希望对你有所帮助
我会提出一些您真正需要的更改来避免这些不寻常的错误。
app.component("test", {
bindings: {
"myContactId": "<"
},
controller:function(){
var self=this;
this.$onInit=function(){
// do all your initializations here.
// create a local scope object for this component only. always update that scope with bindings. and use that in views also.
self.myScopeObject=self.myContactId
}
},
template:'<p>{{$ctrl.myScopeObject}}</p>'
}
<test my-contact-id="8"></test>
几点:
将绑定传递给 html 中的组件总是会采用 kebab 大小写 ex my-contact-id,其各自的 javascript 变量将采用 cammal 大小写:myContactId。
如果您要传递对象的值,请在绑定中使用“@”。
如果您正在使用一个对象并将该对象传递给 bindigs,请使用 '<.
如果您想双向绑定到该对象,请在绑定配置中使用“=”
bindings:{
value:'@',
object:'<', // also known as one-way
twoWay:'='
}
对于那些使用指令的人来说,假设是组件,如果指定了绑定{},似乎将这些相同的参数添加到范围{}是有效的:
/*bindings: {
modalInstance: '<',
resolve: '<'
},*/
scope: {
modalInstance: '<',
resolve: '<'
},
*在我写完上面的内容后发现,在我从 $scope.resolve 分配它之前,$scope 上没有一个额外的范围参数 foo。所以我必须在 $scope.init() 中这样做:$scope.foo = $scope.resolve.foo。不知道为什么。猜测这与我的 UI Bootstrap 模态 + 指令用法有关
这对其他人来说可能是显而易见的,但对我来说不是 AnguluarJS 的新手。
我的问题是将指令与 UI-Bootstrap 模态一起使用,模态与指令兼容,但设计和记录是为了与组件一起使用。
我将添加另一个答案作为对@jusopi 和已接受答案的跟进,仅供那些可能遇到我的问题的人使用。关于组件,即使在 $onInit
钩子之后,我的数据仍然是空的,因为仍然没有收到来自服务器的值。为了抵消这种情况(尽管可能有更好的方法来处理这种情况),我还利用了 $onChanges
挂钩。 $onChanges
将 return 传递给它时已更改的数据,您可以解析该信息,或者简单地将绑定调用为 this.contactId
,它将被更新。
中提供了更多详细信息
导致 "undefined" 错误的代码有两个问题。
- 如上所述,应该首先到达 $onInit 生命周期挂钩,在完成所有绑定后触发 onInit。
来自官方文档:AngularJs Documentation
$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.
- 您可能会遇到的第二个问题是,当使用“() =>”箭头符号作为控制器函数的参数时,您的控制器将不会到达生命周期钩子。
问题是箭头符号没有它自己的范围,而是使用它的封闭范围。
这意味着当使用 "this" 时将引用 window 对象而不是组件。
所以调用 this.$onInit() 将在 window 上调用,并且不会被触发,因为它在 window.
上不存在
我正在编写一个简单的 angular 组件。我将一个参数作为绑定传递并在屏幕上显示它的值。一切正常:我可以看到屏幕上显示的参数。
组件:
var app = angular.module("test", []);
app.component("test", {
bindings: {
"contactId": "<"
},
controllerAs: "model",
controller: () => {
//output: 'contact id from controller: undefined'
console.log(`contact id from controller: ${this.contactId}`);
},
template: "<div>Contact id from view: {{model.contactId}}</div>"
});
Html:
<test contact-id="8"></test>
但是,当我尝试从控制器内部访问绑定时(参见 console.log),绑定值为 undefined
。我不明白它如何在视图中可用,但在控制器中不可用。
我做错了什么?
这里 plnkr 说明了这个问题。
当使用 angular 的组件时,有一点控制器没有通过内部 链接 连接。如果您尝试在控制器的构造函数中执行此操作,则说明您尚未链接 到绑定。组件 API 公开了一些您可以定义的生命周期挂钩,这些挂钩将在特定时间触发。您正在寻找 $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.
关键字 this 似乎不适用于箭头函数,这适用于
controller: function() {
alert('contact id from controller: ' + this.contactId);
}
当使用箭头函数时,this,似乎指的是window对象,因为
An arrow function does not create it's own this context, rather it captures the this value of the enclosing context
contactId
的值在您控制器的 $scope
上可用:
var app = angular.module("test", []);
app.component("test", {
bindings: {
"contactId": "<"
},
controllerAs: "model",
controller: ($scope) => {
var model = $scope.model;
alert(`contact id from controller: ${model.contactId}`);
},
template: "<div>Contact id from view: {{model.contactId}}</div>"
});
Link 到另一个版本的 Plunker here.
确保在 HTML 中使用 连字符 绑定,在 Javascript.
中使用驼峰式绑定app.component("test", {
bindings: {
"myContactId": "<"
}
}
<test my-contact-id="8"></test>
那是我总是忘记做的事情。
这可能不是最佳做法,但您可以更轻松地访问这些值:
$scope.$ctrl.contactId
您可以在 $scope 内的 属性 $ctrl 中获取所有绑定。
希望对你有所帮助
我会提出一些您真正需要的更改来避免这些不寻常的错误。
app.component("test", {
bindings: {
"myContactId": "<"
},
controller:function(){
var self=this;
this.$onInit=function(){
// do all your initializations here.
// create a local scope object for this component only. always update that scope with bindings. and use that in views also.
self.myScopeObject=self.myContactId
}
},
template:'<p>{{$ctrl.myScopeObject}}</p>'
}
<test my-contact-id="8"></test>
几点:
将绑定传递给 html 中的组件总是会采用 kebab 大小写 ex my-contact-id,其各自的 javascript 变量将采用 cammal 大小写:myContactId。
如果您要传递对象的值,请在绑定中使用“@”。 如果您正在使用一个对象并将该对象传递给 bindigs,请使用 '<. 如果您想双向绑定到该对象,请在绑定配置中使用“=”
bindings:{ value:'@', object:'<', // also known as one-way twoWay:'=' }
对于那些使用指令的人来说,假设是组件,如果指定了绑定{},似乎将这些相同的参数添加到范围{}是有效的:
/*bindings: {
modalInstance: '<',
resolve: '<'
},*/
scope: {
modalInstance: '<',
resolve: '<'
},
*在我写完上面的内容后发现,在我从 $scope.resolve 分配它之前,$scope 上没有一个额外的范围参数 foo。所以我必须在 $scope.init() 中这样做:$scope.foo = $scope.resolve.foo。不知道为什么。猜测这与我的 UI Bootstrap 模态 + 指令用法有关
这对其他人来说可能是显而易见的,但对我来说不是 AnguluarJS 的新手。
我的问题是将指令与 UI-Bootstrap 模态一起使用,模态与指令兼容,但设计和记录是为了与组件一起使用。
我将添加另一个答案作为对@jusopi 和已接受答案的跟进,仅供那些可能遇到我的问题的人使用。关于组件,即使在 $onInit
钩子之后,我的数据仍然是空的,因为仍然没有收到来自服务器的值。为了抵消这种情况(尽管可能有更好的方法来处理这种情况),我还利用了 $onChanges
挂钩。 $onChanges
将 return 传递给它时已更改的数据,您可以解析该信息,或者简单地将绑定调用为 this.contactId
,它将被更新。
导致 "undefined" 错误的代码有两个问题。
- 如上所述,应该首先到达 $onInit 生命周期挂钩,在完成所有绑定后触发 onInit。
来自官方文档:AngularJs Documentation
$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.
- 您可能会遇到的第二个问题是,当使用“() =>”箭头符号作为控制器函数的参数时,您的控制器将不会到达生命周期钩子。
问题是箭头符号没有它自己的范围,而是使用它的封闭范围。 这意味着当使用 "this" 时将引用 window 对象而不是组件。 所以调用 this.$onInit() 将在 window 上调用,并且不会被触发,因为它在 window.
上不存在