【问题标题】:Why do ng-bind-html and $sanitize produce different results?为什么 ng-bind-html 和 $sanitize 会产生不同的结果?
【发布时间】:2015-07-27 14:44:13
【问题描述】:

我正在尝试清理某些文本区域的内容,我无法使用 ng-bind-html,因为它破坏了双向绑定(ng-model 不能同时工作)

奇怪的是,当我将ng-bind-html 应用于模型时,它会产生与在指令中使用$sanitize 或$sce 时不同的结果。

这是我制作的示例

http://plnkr.co/edit/iRvK4med8T9Xqs22BkOe?p=preview

第一个文本区域使用ng-bind-html,第二个使用$sanitize,第三个应该是我从AngularJS源代码中提取的ng-bind-html指令的代码。

" 仅在使用 ng-bind-html 时更正更改为 ",在其他两个示例中更改为 "

如何在我的指令中复制ng-bind-html 的结果 - 同时保持双向绑定?

angular.module('sanitizeExample', ['ngSanitize'])
  .controller('ExampleController', ['$scope', '$sce',
    function($scope, $sce) {

      $scope.value = 'This in "quotes" for testing';
      $scope.model = 'This in "quotes" for testing';

    }
  ]).directive('sanitize', ['$sanitize', '$parse', '$sce',
    function($sanitize, $parse, $sce) {
      return {
        restrict: 'A',
        replace: true,
        scope: true,
        link: function(scope, element, attrs) {

          var process = function(input) {
            return $sanitize(input);
            //return $sce.getTrustedHtml(input);
          };

          var processed = process(scope.model);
          console.log(processed); // Output here = This in "quotes" for testing
          $parse(attrs.ngModel).assign(scope, processed);
          //element.html(processed);
        }
      };
    }
  ])
  .directive('sanitizeBindHtml', ['$parse', '$sce',
    function($parse, $sce) {
      return {
        restrict: 'A',
        replace: true,
        scope: true,
        link: function(scope, element, attrs) {

          var parsed = $parse(attrs.ngModel);

          function getStringValue() {
            var value = parsed(scope);
            getStringValue.$$unwatch = parsed.$$unwatch;
            return (value || '').toString();
          }

          scope.$watch(getStringValue, function ngBindHtmlWatchAction(value) {
            var processed = $sce.getTrustedHtml(parsed(scope)) || '';

            $parse(attrs.ngModel).assign(scope, processed)
          });
        }
      };
    }
  ]);
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular-sanitize.js"></script>

<!doctype html>
<html lang="en">


<body ng-app="sanitizeExample">

  <div ng-controller="ExampleController">
    <textarea ng-bind-html="value"></textarea>
    <br/>{{value}}
    <br/>
    <br/>
    <textarea sanitize ng-model="model"></textarea>
    <br/>
    <br/>
    <textarea sanitize-bind-html ng-model="model"></textarea>

  </div>
</body>

【问题讨论】:

  • 这很有趣。 ngModel 指令似乎在这里给您带来了问题,设置 priority 不会解决它。在您的最后一个示例中,复制ngBindHtml,如果您将ngModel 替换为另一个名称(例如bob、bob="model"),它将起作用。 plnkr.co/edit/eVA9lvMmwOcWKL1B2fjM?p=preview 。与您的第二个指令类似,除了它需要一些其他小的更改:解析。
  • 很想听听有更多经验的人的完整回答,或者有时间深入研究ngModel 指令。如果这没有发生,我会在有更多时间时深入研究该来源:)。目前,正如我所提到的,更新到另一个属性也适用于你的另一个指令plnkr.co/edit/lVH1IQAhMfAot116xfiM?p=preview
  • 如果有机会,我将不得不看看我能在ngModel 上挖掘出什么。很遗憾,更改属性不允许双向绑定仍然起作用!

标签: angularjs ngsanitize


【解决方案1】:

结果如我们所料,环卫服务返回了相同的结果。在ngBindHtmlDirective 中放置一个断点,我们可以介入看看发生了什么。我们深入研究$SanitizeProvider 中的值。将返回给 ngBindHtmlDirective 的buf 的值为:

这在"quotes"用于测试

与调用 $sanitize 得到的完全相同,那么真正的区别是什么?真正的区别在于文本框的 innerHTML 和 value 之间。查看此example plunker。您可以看到调用这两种不同方法之间的区别,以及转义双引号的不同方式。我没有去挖掘 w3 规范或浏览器代码,但我假设 innerHTML 分配在创建 documentFragment 的底层做额外的工作,获取它的 textContent,然后将其分配给文本框的值。显然 value 只是抓取字符串并按原样插入。


那么你的指令有什么问题?我看到 element.html(processed) 在评论中,但取消评论它没有影响。好吧,事实是它确实在一瞬间起作用!尽管使用调试器单步执行,文本框的值已正确设置,但随后会触发 $digest 循环并立即更改它!事实是 ngModelDirective 阻碍了它,特别是 $render function of the baseInputType。我们可以在代码中看到它使用了element.val 方法。

我们如何在指令中解决这个问题?要求 ngModelController 并覆盖其 $render 函数以使用 element.html 方法 (example plunker)。

// Add require to get the controller
require: 'ngModel',

// Controller is passed in as the 4th argument
link: function(scope, element, attrs, ngModelCtrl) {

// modify the $render function to process it as HTML
ngModelCtrl.$render = function() {
    element.html(ngModelCtrl.$isEmpty(ngModelCtrl.$viewValue) ? '' : ngModelCtrl.$viewValue);
};

【讨论】:

    猜你喜欢
    • 2017-04-03
    • 2013-01-21
    • 2017-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多