【问题标题】:AngularJS: Is it possible to do post-processing of ng-bind-html without $watch?AngularJS:是否可以在没有 $watch 的情况下对 ng-bind-html 进行后处理?
【发布时间】:2015-07-15 06:18:06
【问题描述】:

我有 html 内容 应该由 ng-bind-html 指令输出,并且在我想对此内容进行一些操作(例如 DOM 操作、jQuery 插件等)。

stackoverflow 为我提供such solution:

<div ng-app="myApp" ng-controller="myCtrl">
   <div ng-bind="sometext" my-directive>before</div>
</div>

所以要创建具有更高优先级的自定义指令并在里面观察:

angular.module('myApp').directive('myDirective', function() { 
    return {
        priority: 10, 
        link: function(scope,element,attrs) {
            scope.$watch(attrs.ngBind, function(newvalue) {
              console.log("element ",element.text());
            });           
        }
    };      
 });

还有Demo

但就我不打算更改此内容而言,我不想使用 $watch。可以不用$watch吗?

【问题讨论】:

  • 这对我来说没有任何意义。您正在将 HTML 存储在您想要一些 3rd 方插件操作的模型中?这里感觉有些不对劲,似乎与 Angular 的目标背道而驰。
  • 如何设置ng-bind-html 的值?通过 ajax 还是使用一些动作?
  • @Claies,我们将 HTML 存储在数据库中,所以是的 - 在模型中,通过 ajax(是的 @Pankaj)
  • 老实说,将 HTML 存储在数据库中的做法毫无意义。
  • 为什么会这样?我有在 WYSIWYG 编辑器中准备的内容,可以在那里粘贴你想要的任何内容(如图像、视频)。

标签: angularjs angularjs-directive ng-bind-html ng-bind


【解决方案1】:

选项 1(根据要求避免使用 $watch):

一种选择是跳过ng-bind-html$compile$parse 您自己的html。 Angular 的 ngBindHtml 本身做了以下事情:

var ngBindHtmlGetter = $parse(tAttrs.ngBindHtml);
// ... It does some other, less relevant stuff between these
element.html($sce.getTrustedHtml(ngBindHtmlGetter(scope)) || '');

Angular's relevant source code can be viewed here

因此,您始终可以编写一个自定义指令来执行这些操作以及后处理(如果需要,甚至是预处理)。大致如下:

var ngBindHtmlGetter = $parse(attrs.someAttrContainingContent);
element.html($sce.getTrustedHtml(ngBindHtmlGetter(scope)) || '');
doPostProcessing(element); // Your additional stuff goes here

选项 2(保留$watch,但取消绑定):

如果您想使用ng-bind-html 并且您只是担心周围有额外的观察者,那么另一个选项对您来说可能更简单,那就是取消绑定观察者。你可以很容易地解除绑定($watch 返回一个“解除绑定”函数):

var unbindPostProcess = scope.$watch(attrs.ngBind, function(newvalue) {
    doPostProcessing(element); // Whatever the additional function may be
    unbindPostProcess(); // Perhaps guarded to unbind at the right time.
});

【讨论】:

  • 我觉得在第一个选项中我们仍然需要手表,请您提供小提琴吗?
  • 对,会有一个观察者。 ngBindngBindHtml 自己添加了一个观察者,而你建议使用它,所以我假设你试图避免 additional 观察者(即来自你的指令)。如果你想在你的代码中避免它们,你可以做一些杂技:&lt;div ng-if="sometext.length" my-directive="sometext"&gt;,现在在链接时你将拥有 HTML 内容并且不需要更多的观察者(notengIf 添加观察者本身)。这是一个例子:jsfiddle.net/cnU4Z/12
  • 如果你根本不需要观察者,我建议将我的选项 1 与我的选项 2 结合起来。如,使用选项 1 来构建 HTML,选项 2 来杀死一个观察者 - 使用任何内部 Angular 指令将添加观察者。所有人都说:我并没有真正提出任何建议,并且不认为不惜一切代价避开观察者是一件好事。观察者首先使 Angular 变得有用。
  • 感谢您的详细解答!我非常了解观察者是什么,甚至对他们进行了介绍 - youtu.be/UjnL8w9XRvk?t=268 :) 只是想开箱即用。并感谢您使用ng-if 提供非常有趣的变体!
  • 对,我并不怀疑您知道它们是什么。如果你真的担心太多的观察者,你可能真的想更多地使用它们——如果你添加了观察者,那么 Angular 不会为你做这件事(ngIf 添加了一个观察者,ngBind 添加了一个,等等.),如果您自己添加了观察者,那么您也可以取消绑定(在上面帖子的选项 2 中概述),留下 0 个观察者。使用ng-if,您将永远拥有一个:jsfiddle.net/cnU4Z/13
【解决方案2】:

我可能完全误解了您要查找的内容,但是,如果问题是;

如何在没有 $watcher 的情况下将 HTML 绑定到视图?

this jsBin 展示了如何。

通过升级到 angular-1.3.x,您可以访问一次性绑定 {{::expr}}

因此,实际上只需要相信sometext 可能是HTML(通过使用$sce)并使用ng-bind-html="::sometext" 输出它。

瞧,没有$watchers,您可以完全废弃自定义指令。


哦,还有 如果这不是你想要的,请告诉我,我会删除我的答案。

【讨论】:

  • 是的,不幸的是这不是我要找的。我的问题更多关于后处理。
  • 想详细说明一下吗?我的意思是,您想要公开的 HTML 内容是什么样的? HTML 是您要运行的指令的载体吗?我很难理解这里的最终目标是什么。
  • 我有由所见即所得编辑器创建的内容。例如,对于图像我需要应用 jquery fancybox,对于 iframe(即嵌入式视频),我创建包装器以使它们在手机上响应。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-22
  • 1970-01-01
  • 2016-05-12
  • 2013-08-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多