74

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

零件:

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

4

9 回答 9

67

使用 Angular 的组件时,控制器没有通过内部链接连接。如果您尝试在控制器的构造函数中执行此操作,则您尚未链接到绑定。组件 API 公开了一些您可以定义的生命周期钩子,这些钩子将在特定时间触发。你正在寻找$onInit钩子。

$onInit() - 在元素上的所有控制器都已构建并初始化其绑定之后(以及在此元素上的指令的前后链接函数之前)在每个控制器上调用。这是放置控制器初始化代码的好地方。

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

于 2016-07-26T13:53:25.780 回答
33

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

app.component("test", {
  bindings: {
    "myContactId": "<"
  }
}

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

这就是我总是忘记做的事情。

于 2017-05-30T09:44:15.153 回答
7

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

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

使用箭头函数时,this似乎指的是窗口对象,因为

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

于 2016-07-26T13:59:37.617 回答
7

的值在您的控制器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>"
});

在此处链接到您的 Plunker 的另一个版本。

于 2016-07-26T14:05:52.583 回答
6

我会建议一些您真正需要的更改,以避免这些不寻常的错误。

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 cased ex my-contact-id 并且其各自的 javascript 变量将是 cammal cased :myContactId。

  2. 如果您要传递对象的值,请在绑定中使用“@”。如果您正在使用一个对象并将该对象传递给 bindigs,请使用 '<. 如果你想 2-way-binding 到该对象,请在绑定配置中使用 '='

 bindings:{
      value:'@',
      object:'<', // also known as one-way
      twoWay:'='
    }
于 2017-08-10T12:03:16.153 回答
2

它可能不是最佳实践,但您可以更轻松地访问这些值:

$scope.$ctrl.contactId

您可以在 $scope 中获取属性 $ctrl 中的所有绑定。

我希望它的帮助

于 2017-06-19T11:47:21.090 回答
2

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

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

来自官方文档:AngularJs Documentation

$onInit() - 在元素上的所有控制器都已构建并初始化其绑定之后(以及在此元素上的指令的前后链接函数之前)在每个控制器上调用。这是放置控制器初始化代码的好地方。

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

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

于 2019-07-08T08:37:12.983 回答
0

对于那些使用指令(假定组件)的用户,如果指定了绑定{},则似乎将这些相同的参数添加到范围{} 有效:

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

*在我写完上面的内容后发现,在我从 $scope.resolve 分配一个附加范围参数 foo 之前,它在 $scope 上不可用。所以我不得不在 $scope.init() 中这样做:$scope.foo = $scope.resolve.foo。不知道为什么。猜测它与我的 UI Bootstrap Modal + Directives 用法有关

这对其他人来说可能很明显,但对我来说并不是相对较新的 AnguluarJS。

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

于 2018-03-16T23:37:34.993 回答
0

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

文档中提供了更多详细信息: https ://docs.angularjs.org/guide/component

于 2018-11-04T01:19:58.753 回答