为什么我的组件绑定在它的控制器中没有定义?

我在写一个简单的角度分量。我传递一个参数作为绑定,并在屏幕上显示它的值。一切正常: 我可以看到屏幕上显示的参数。

组成部分:

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>"
});

网址:

<test contact-id="8"></test>

但是,当我尝试从控制器中访问绑定时(请参阅 console.log) ,绑定值是 undefined。我不明白为什么它在视图中可用,而在控制器中却不可用。

我做错了什么?

这里有一个 普林克来说明这个问题。

53304 次浏览

当使用角的组件,有一点控制器没有通过内部的 连接连接起来。如果您试图在控制器的构造函数中执行此操作,那么您还没有成为绑定的 联系在一起。组件 API 公开了一些生命周期挂钩,您可以定义这些挂钩在特定时间触发。你在找 $onInit钩子。

$onInit ()-在构造了元素上的所有控制器并初始化了它们的绑定之后(在该元素上的指令的 pre & post 链接函数之前)对每个控制器调用。这是放置控制器初始化代码的好地方。

每份文件-https://docs.angularjs.org/guide/component

关键字 这个似乎不适用于箭头函数,这适用于

controller: function() {
alert('contact id from controller: ' + this.contactId);
}

在使用箭头函数 这个时,似乎引用了窗口对象,因为

箭头函数不创建它自己的上下文,而是创建它自己的上下文 捕获封闭上下文的这个值

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>"
});

链接到另一个版本的普朗克 给你

确保在 HTML 中使用 连字符进行绑定,在 Javascript 中使用 camelCase 进行绑定。

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>

一些观点:

  1. 将绑定传递给 html 中的组件总是以 kebab 大小写的方式使用 my-contact-id,其各自的 javascript 变量将以 cammal 大小写的方式使用: myContactId。

  2. 如果传递的是代替对象的值,请在绑定中使用“@”。 如果您正在使用一个对象并将该对象传递给 bindigs,请使用’< 。 如果希望对该对象进行双向绑定,请在 bindings 配置

  3. 中使用“ =”
 bindings:{
value:'@',
object:'<', // also known as one-way
twoWay:'='
}

对于那些使用指令(其中假定为组件)的用户,如果指定了绑定{} ,那么将这些相同的参数添加到作用域{}可以工作:

/*bindings: {
modalInstance: '<',
resolve: '<'
},*/
scope: {
modalInstance: '<',
resolve: '<'
},

* 在我编写上面的代码之后发现,在 $scope 上没有额外的 scope 参数 foo,直到我从 $scope.Resolz 中分配了它。因此,我必须在 $scope.init () : $scope.foo = $scope.Resolve.foo 中执行此操作。不知道为什么。我猜这和我的 UI Bootstrap Modal + Directive 使用有关

对于其他人来说,这可能是显而易见的,但对于我来说,AnguluarJS 相对来说并不新鲜。

我的问题是使用指令和 UI-Bootstrap 模式,这些模式与指令兼容,但是设计和记录是为了与组件一起使用。

我将添加另一个答案作为@jusopi 和接受的答案的后续,只是为了那些可能遇到我的问题的人。对于组件,即使在 $onInit挂钩之后,我的数据仍然为空,因为仍然没有接收到来自服务器的值。为了解决这个问题(尽管可能有更好的方法来处理这种情况) ,我还利用了 $onChanges挂钩。$onChanges将返回传递给它时已经更改的数据,您可以解析该信息,或者简单地将绑定调用为 this.contactId,它将被更新。

更多细节在 文件: https://docs.angularjs.org/guide/component中提供

代码有两个问题导致“未定义”错误。

  1. 如上所述,应该首先到达 $onInit 生命周期钩子,当所有绑定都完成时,将触发 onInit。

来自官方文件: AngularJs 文档

$onInit ()-在控制器上的所有控制器之后对每个控制器调用 元素,并初始化了它们的绑定(和 在此指令的前置和后置链接函数之前 这是放置初始化代码的好地方 控制器。

  1. 您可能遇到的第二个问题是,当使用“() = >”箭头符号作为控制器函数的参数时,您的控制器将无法到达生命周期钩子。

问题是,箭头符号不会有它自己的作用域,而是使用它的封闭作用域。 这意味着当使用“ this”时将引用窗口对象而不是组件。 所以就这么定了。$onInit ()将在窗口上调用,并且不会被激发,因为它在窗口上不存在。