为什么我的组件绑定在其控制器中未定义?

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.

每个文档 - https://docs.angularjs.org/guide/component

关键字 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>

几点:

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

  2. 如果您要传递对象的值,请在绑定中使用“@”。 如果您正在使用一个对象并将该对象传递给 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,它将被更新。

documentation: https://docs.angularjs.org/guide/component

中提供了更多详细信息

导致 "undefined" 错误的代码有两个问题。

  1. 如上所述,应该首先到达 $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.

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

问题是箭头符号没有它自己的范围,而是使用它的封闭范围。 这意味着当使用 "this" 时将引用 window 对象而不是组件。 所以调用 this.$onInit() 将在 window 上调用,并且不会被触发,因为它在 window.

上不存在