AngularJS指令元素方法绑定-TypeError:无法使用'in'运算符在1中搜索'functionName'

Posted

技术标签:

【中文标题】AngularJS指令元素方法绑定-TypeError:无法使用\'in\'运算符在1中搜索\'functionName\'【英文标题】:AngularJS Directive element method binding - TypeError: Cannot use 'in' operator to search for 'functionName' in 1AngularJS指令元素方法绑定-TypeError:无法使用'in'运算符在1中搜索'functionName' 【发布时间】:2015-07-26 11:37:14 【问题描述】:

这是主模板的控制器:

app.controller('OverviewCtrl', ['$scope', '$location', '$routeParams', 'websiteService', 'helperService', function($scope, $location, $routeParams, websiteService, helperService) 
    ...     
    $scope.editWebsite = function(id) 
        $location.path('/websites/edit/' + id);
    ;
]);

这是指令:

app.directive('wdaWebsitesOverview', function() 
    return 
        restrict: 'E',
        scope: 
            heading: '=',
            websites: '=',
            editWebsite: '&'
        ,
        templateUrl: 'views/websites-overview.html'
    
);

这是指令在主模板中的应用方式:

<wda-websites-overview heading="'All websites'" websites="websites" edit-website="editWebsite(id)"></wda-websites-overview>

这是从指令模板(website-overview.html)调用的方法:

<td data-ng-click="editWebsite(website.id)">EDIT</td>

问题:单击编辑时,控制台中出现此错误:

TypeError: 无法使用 'in' 运算符在 1 中搜索 'editWebsite'

有人知道这里发生了什么吗?

【问题讨论】:

【参考方案1】:

由于您定义了表达式绑定 (&amp;),如果您想在 HTML 中将其绑定为 edit-website="editWebsite(id)",则需要使用包含 id 的对象字面量参数显式调用它。

确实,Angular 需要了解这个 id 在您的 HTML 中是什么,并且由于它不属于您的范围,因此您需要在调用中添加所谓的“locals”:

data-ng-click="editWebsite(id: website.id)"

或者作为替代:

data-ng-click="onClick(website.id)"

使用控制器/链接代码:

$scope.onClick = function(id) 
  // Ad "id" to the locals of "editWebsite" 
  $scope.editWebsite(id: id);


AngularJS 在其文档中包含了对此的解释;在以下 URL 中查找涉及 "close(message: 'closing for now')" 的示例:

https://docs.angularjs.org/guide/directive

【讨论】:

@floribon 我知道这有点老了,但是你有打字回调的例子吗? "通常希望通过表达式将数据从隔离范围传递到父范围;这可以通过将局部变量名称和值的映射传递给表达式来完成包装函数。例如,hideDialog 函数在对话框隐藏时显示一条消息。这是通过调用 close(message: 'closing for now') 在指令中指定的。然后局部变量 message 将在on-close 表达式。" [emph mine] 真相比小说更奇怪。我想知道他们是如何选择这个作为事件处理程序的最佳解决方案的。【参考方案2】:

TL;DR; - 您假设绑定函数正在传递给子组件,就像在 React 中一样。这是不正确的。实际上,AngularJS 正在解析字符串模板并创建一个新函数,然后调用父函数。

这个生成的函数期望接收一个带有键和值的对象,而不是一个普通的变量。

更长的解释

当您使用 '&' 绑定函数并尝试从控制器调用该函数,传递一个普通变量而不是包含普通变量名称的对象时,就会发生这种情况。 模板引擎需要对象键来确定如何将值传递给绑定函数。

例如。你打电话给boundFunction('cats')而不是boundFunction(value: 'cats')

工作示例

假设我创建了一个这样的组件:

const MyComponent = 
  bindings: 
    onSearch: '&'
  ,
  controller: controller
;

这个函数(在父函数中)如下所示:

onSearch(value) 
  // do search

在我的父模板中,我现在可以这样做:

<my-component on-search="onSearch(value)"></my-component>

这里的绑定会从字符串中解析出来。 您实际上并没有传递函数。 AngularJS 正在为您创建一个调用该函数的函数。模板中创建的绑定除了函数调用之外还可以包含很多东西。

AngularJS 需要找出从哪里获取value,它通过从父级接收一个对象来做到这一点。

在 myComponent 控制器中,我需要执行以下操作:

handleOnSearch(value) 
  if (this.onSearch) 
    this.onSearch(value: value)
  

【讨论】:

好吧,有人认为这条评论是多余的,尽管它已被点赞,所以让我再试一次:请注意,这个答案的关键是:你打电话给boundFunction('cats')而不是boundFunction(value: 'cats')"

以上是关于AngularJS指令元素方法绑定-TypeError:无法使用'in'运算符在1中搜索'functionName'的主要内容,如果未能解决你的问题,请参考以下文章

Angularjs-指令

AngularJS 指令

每天看懂一点:AngularJS

AngularJs 指令

AngularJS学习之旅—AngularJS HTML DOM(十三)

AngularJS指令参数详解