奇怪的是,当我将ng-bind-html应用于模型时,它会产生不同的结果,当我在指令中使用$sanitize或$sce时.
这是我编写的一个示例
http://plnkr.co/edit/iRvK4med8T9Xqs22BkOe?p=preview
第一个文本区域使用ng-bind-html,第二个文本区域使用$sanitize,第三个应该是ng-bind-html指令的代码,因为我从AngularJS源代码中删除了.
&安培; QUOT;只有更正改为“当使用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',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',function($parse,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>
This in "quotes" for testing
与我们调用$sanitize完全相同,那么真正的区别是什么?真正的区别在于文本框的innerHTML和值之间.查看此example plunker.您可以看到调用两种不同方法之间的区别,使用不同的方法来转义双引号.我没有去挖掘w3规范或浏览器代码,但我认为innerHTML赋值是在创建documentFragment,抓取它的textContent,然后将其分配给文本框的值的引擎下做额外的工作.显然,值只是抓住字符串并按原样插入.
那么你的指令有什么问题呢?我看到element.html(已处理)在评论中,但取消注释它没有影响.事实上,它确实可以工作一瞬间!使用调试器逐步调试,文本框的值已正确设置,但随后会触发$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,attrs,ngModelCtrl) { // modify the $render function to process it as HTML ngModelCtrl.$render = function() { element.html(ngModelCtrl.$isEmpty(ngModelCtrl.$viewValue) ? '' : ngModelCtrl.$viewValue); };