【问题标题】:AngularJS: ng-src behavior on non-standard attributes?AngularJS:非标准属性上的 ng-src 行为?
【发布时间】:2013-11-27 06:45:51
【问题描述】:

我正在使用“Video For Everybody”生成器在我的应用中集成媒体播放器。如果浏览器不支持 HTML5 videoaudio,则播放器会回退到 flash,我必须使用视频和占位符(图像)源构建具有 param 属性的 object 元素。

不出所料,我遇到了表达式没有及时解决的经典问题,我的浏览器将请求发送到my.media.com/{{video.src}}而不是my.media.com/somevideo.mp4

不幸的是,有几个属性(poster, flashvars, placeholder 仅举几例)我面临同样的问题。我将如何创建与 ng-src 或 ng-href 指令相同的行为?我尝试寻找相关的源代码,但没有找到。这是一个展示有问题的 HTML 的 sn-p,

<video controls="controls" poster="{{mediaModel.mediaFile2}}" width="300" height="150">
<source ng-src="{{mediaModel.mediaFile}}" type="{{mediaModel.contentType}}" />
<object type="application/x-shockwave-flash" data="http://player.longtailvideo.com/player.swf" width="300" height="150">
    <param name="movie" value="http://player.longtailvideo.com/player.swf" />
    <param name="allowFullScreen" value="true" />
    <param name="wmode" value="transparent" />
    <param name="flashVars" value="{{'controllerbar=over&amp;image=' + media.mediaFile2 + '&amp;file=' + mediaModel.mediaFile}}" />
    <img ng-src="{{mediaModel.mediaFile2}}" width="300" height="150" title="{{mediaModel.uploadedTime}}" />
</object>

【问题讨论】:

  • 您能分享一些无效的方法吗?
  • 在这一点上,我或多或少在黑暗中磕磕绊绊,试图弄清楚是否可以应用自定义属性,所以我认为我没有任何代码此刻将是建设性的问题。我当然会在我有什么感觉时立即更新。

标签: angularjs angularjs-directive


【解决方案1】:

在官方 API 文档中可以轻松找到内置指令的来源。在这种情况下,请转到ngSrc 的文档,在页面顶部您会看到两个按钮,“改进此文档”和“查看源代码”,单击“查看源代码”,它会自动将您带到正确的定义指令的源文件。这适用于所有内置指令,非常方便!

下面我粘贴 ngSrc 的代码,有趣的是它看起来一点也不复杂,关键行似乎是priority: 99,根据旁边的注释意味着优先级为 99 的指令将运行 在属性被插值之后。

// ng-src, ng-srcset, ng-href are interpolated
forEach(['src', 'srcset', 'href'], function(attrName) {
  var normalized = directiveNormalize('ng-' + attrName);
  ngAttributeAliasDirectives[normalized] = function() {
    return {
      priority: 99, // it needs to run after the attributes are interpolated
      link: function(scope, element, attr) {
        attr.$observe(normalized, function(value) {
          if (!value)
             return;

          attr.$set(attrName, value);

          // on IE, if "ng:src" directive declaration is used and "src" attribute doesn't exist
          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need
          // to set the property as well to achieve the desired effect.
          // we use attr[attrName] value since $set can sanitize the url.
          if (msie) element.prop(attrName, attr[attrName]);
        });
      }
    };
  };
});

鉴于上述情况,实现您自己的指令应该是微不足道的。

【讨论】:

  • 太好了,非常感谢。不敢相信我在 Angular 文档中花了这么多时间,却忽略了这个简单但非常实用的功能。仅供参考:我会暂时接受/奖励赏金,以防出现更多答案。
  • @KGChristensen NP 很高兴我能提供帮助。
【解决方案2】:

因此,最通用、可维护、可配置和可重用的解决方案是创建一个自定义指令来为您处理它。

看看这个-->PLNKR<--,那里几乎有你需要的一切。你只需要弱一点。

它是如何工作的:向指令传递配置对象(如果需要更多对象,只需创建附加属性)。元素可以处于两种状态:准备好或未准备好。 $scope.isReady 只是说明是否已收集所有成分。如果是这样,ngSwitch 会加载 videoPlayer 模板,并且由于所有信息都已发送,因此不会发送不需要的请求。

【讨论】:

  • 感谢您的努力,虽然固定超时并不是真正的用户友好或可行的选择。我设法使用 $observe 创建自己的 ngSrc 指令实现,以观察表达式解析。
  • @KGChristensen 您可能不理解代码。使用$timeout 只是为了证明这种方法确实有效,并且它用于控制器而不是指令本身。指令等待填充范围,检查所有数据是否设置正确,然后仅加载模板。您如何填充范围完全不相关:我使用了$timeout,因为它最简单。如果您在初始化控制器时已经拥有所有相关信息,则该指令也将起作用。
  • 啊,抱歉——现在又看了一眼,上次有点快。虽然我可以看到这种方法有效,但感觉有点麻烦:在数据准备好之前不包括模板并不能发挥指令方法的优势(尤其是与 ngSrc 方法相比)。
  • @KGChristensen 请问你这种方法到底有什么问题?您只需在此处传递一个配置对象,无需手动设置每个单独的属性——您认为这比手动设置每个 ngSrc 更糟糕吗? (怎么可能?)
  • @KGChristensen 如果你担心下载模板本身——不知道还有什么可能是你担心的原因——AngularJS 内置了$templateCache
【解决方案3】:

您现在可以使用ng-attr-poster,或更一般地说:ng-attr-whatever

【讨论】:

    【解决方案4】:

    我在video 标签上的poster 属性遇到了类似的问题。如果您将ng-cloak 应用于具有类似src 属性的元素,它们将不会尝试加载任何内容,直到它们在披风被移除后变得可见。

    【讨论】:

      猜你喜欢
      • 2015-04-08
      • 1970-01-01
      • 2013-03-14
      • 1970-01-01
      • 1970-01-01
      • 2014-02-01
      • 1970-01-01
      • 2017-05-21
      • 2020-03-07
      相关资源
      最近更新 更多