在指令的链接函数中修改事件中的范围变量

Modifying scope variables in an event in a directive's link function

本文关键字:变量 事件 范围 修改 函数 指令 链接      更新时间:2023-09-26

我在指令的链接函数中的元素上有一个jQuery事件。 我想修改该事件回调中的范围变量。 它不起作用 - 呈现该变量的模板永远不会更新:

joyableApp.directive('foobar', [function() {
  var FoobarLink = function(scope, element, attrs){
    scope.foo = 'bar';
    element.click(function(){
      console.log("clicked!");
      scope.foo = 'clicked_result';
    });
  };
  return {
    template: '<div>foo = {{foo}}</div>',
    scope: {},
    link: FoobarLink
  }
}]);

在此示例中,我尝试在单击指令元素时更新scope.foo。 但是,当我运行它并单击元素时,模板不会从bar更新到 clicked_result . 我怀疑我错过了一些关于linkscope如何在这里工作的基本知识。

一些不相关的背景故事,以防万一有帮助:我正在尝试创建一个可以在<input>领域使用的指令。 当您专注于此输入字段时,它将显示弹出工具提示。 因此,使用该指令的界面看起来像<input input-tooltip content=‘some tooltip content here’>。 但是,为此,我需要指令来侦听根元素以获取focus事件。 我能找到的唯一方法是在传递给链接函数的元素上使用 jQuery 事件。 但是,在该事件的焦点事件的回调中,我似乎无法成功修改范围变量。

$scope.foo

Angular 进入摘要循环(即所谓的 dirty check )之前不会刷新。在指令中,您需要自己手动触发摘要循环,如下所示

scope.$apply(function () {
  scope.foo = 'clicked_result';
});

但是您可能会遇到Error: $digest already in progress,因此最好使用evalAsyncapplyAsync来触发安全的消化周期,例如

scope.$evalAsync(function () {
  scope.foo = 'clicked_result';
});

DOM 操作包装在$timeout中。

  element.click(function(){
    console.log("clicked!");
    $timeout(function () {
      scope.foo = 'clicked_result';
    },0);
  });

$timeout将导致安全消化周期开始。不要忘记注射$timeout:

joyableApp.directive('foobar', ['$timeout', function($timeout) {

希望这有帮助。

  element.click(function(){
    console.log("clicked!");
    scope.$apply(function () {
      scope.foo = 'clicked_result';
    });
  });

在这里使用$apply是合适的,不需要注射$timeout。 根据我的经验,$timeout仅在您在链接函数中修改 DOM 并且需要等待 angular 编译添加的元素的情况下才有用。