簡體   English   中英

AngularJS處理不同類型的DOM操作

[英]AngularJS handling different types of DOM manipulation

我目前有2條指令:

  1. 創建文本框和工具欄div的編輯器指令。
  2. 包含在編輯器中的粗體按鈕

標記

<editor content="text">
  <bold-button>B</bold-button>
</editor>

編輯指令

.directive('editor', function () {
  return {
    restrict: 'E',
    replace: true,
    transclude: true,
    scope: {
      'content': '='
    },
    template: '<div class="editor">' +
                '<div class="toolbar" ng-transclude></div>' +
                '<textarea ng-model="content"></textarea>' +
              '</div>',
    controller: function ($scope, $element, $attrs) { },
    link: function (scope, elem, attrs, ctrl) {
      var editor = new Editor();
      editor.onPostUpdateDom = function () {
        scope.content = elem.find('textarea').val();
      };
      // Expose editor to other directives
      ctrl.editor = editor;
    };
});

粗體按鈕指令

.directive('boldButton', function () {
  return {
    require: '^editor',
    restrict: 'E',
    replace: true,
    transclude: true,
    scope: {},
    template: '<button type="button" ng-click="format()" ng-transclude>'+
              '</button>',
    link: function (scope, elem, attrs, editorCtrl) {
      scope.format = function () {
        editorCtrl.editor.formatCommand("bold");
      };
    };
});

編輯器指令使用第三方插件,該插件提供用於更改textarea值的formatCommand()方法。

粗體button指令通過編輯器的控制器觸發此方法。

現在,每次插件更改DOM時,它都會引發一個onPostUpdateDOM事件,我使用該事件來獲取新值並將其分配給editor指令內的作用域:

scope.content = elem.find('textarea').val();

這真的很好。 按下按鈕,數值改變。

但是,該插件還通過鍵盤快捷鍵提供了DOM操作。 更改DOM后, scope.content = elem.find('textarea').val(); 行不起作用,因為它發生在Angular之外。 $apply包裝該行是formatCommand()但隨后來自button指令的formatCommand()調用將引發“應用已在進行中”錯誤。

這是“安全應用”反模式的情況嗎?

編輯器指令中的這些行:

editor.onPostUpdateDom = function () {
  scope.content = elem.find('textarea').val();
};

就是這個問題, onPostUpdateDom事件處理程序會從Angular世界內部或外部觸發,並且由於依賴第三方插件而不受開發人員的控制。

為了解決這個問題,我們本質上需要一個安全的應用程序來處理Angular和Non-Angular事件:

請參見: AngularJS:在調用$ scope。$ apply()時防止錯誤$ digest已經在進行中

因此,答案是將代碼包裝在$timeout

editor.onPostUpdateDom = function () {
  $timeout(function () {
    // anything you want can go here and will safely be run on the next digest.
    scope.content = elem.find('textarea').val();
  });
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM