【问题标题】:AngularJS Custom Directive replace HTMLAngularJS 自定义指令替换 HTML
【发布时间】:2016-06-28 12:14:16
【问题描述】:

home.html

<videodata></videodata>

videoctrl.js

$rootScope.cameraRTSPUrl = obj.objUrl;

directive.js

directive - myApp.directive('videodata', function() {
    return {
        restrict: 'EA',
        scope : true ,
        link: function(scope, element, attrs) {

            element.replaceWith('<object classid="clsid:9BE31822-FDAD-461B-AD51-BE1D1C159921" '+
                                    'codebase="http://downloads.videolan.org/pub/videolan/vlc/latest/win32/axvlc.cab" '+
                                    'id="vlc" events="True"> '+
                                    '<embed id="123" type="application/x-google-vlc-plugin" version="VideoLAN.VLCPlugin.2" autoplay="yes" '+
                                    'loop="no" width="800" height="600" target="'+scope.cameraRTSPUrl+'"> '+
                                '</object>');

        }
    };
});

上面的代码有效,呈现的 HTML 如下

    <object events="True" id="vlc" 
        codebase="http://downloads.videolan.org/pub/videolan/vlc/latest/win32/axvlc.cab" 
        classid="clsid:9BE31822-FDAD-461B-AD51-BE1D1C159921">
        <embed width="800" height="600" target="rtsp://localhost/media/media.amp" loop="no" autoplay="yes" 
        version="VideoLAN.VLCPlugin.2" type="application/x-google-vlc-plugin" id="123">
    </object>   
  1. 代码适用于element.replaceWith,但这是正确的吗 使用自定义指令替换 HTML 的方法?
  2. 如何使用transclude: true, 属性来替换我的 HTML ?

附:我在link 函数中使用scope.cameraRTSPUrl 值。

【问题讨论】:

  • 使用replace : true 并在返回对象中使用template : &lt;your html&gt;。这可能会有所帮助。对不起,但我没有得到你想要实现的目标。为了超越指令的内部html,您还需要在模板中设置transclude:true并使用ng-transclude指令。 docs.angularjs.org/api/ng/directive/ngTransclude
  • 反对者请解释。我能够达到预期的结果,但想知道最好的方法。
  • 你能告诉我你想要达到什么结果吗?

标签: javascript angularjs angular-directive


【解决方案1】:

该代码适用于element.replaceWith,但这是使用自定义指令替换 HTML 的正确方法吗?

不。这或多或少是最糟糕的错误方式,因为它阻止了任何 Angular 数据或事件绑定,或者实际上是 Angular 值得使用的任何其他原因;您正在将一大块未编译的 HTML 转储到 Angular 并不真正了解的页面中。

你永远不想直接在 Angular 中修改 DOM。如果你直接修改 DOM,你添加的几乎总是首先是$compiled,这样 Angular 就可以在其中找到任何数据或事件绑定。 (经验丰富的 Angular 开发人员可能会对我使用“从不”这个词提出异议。确实,在某些情况下该建议不适用,但作为 Angular 新手,您不太可能遇到它们很长一段时间。最佳实践是让 Angular 完成工作,直到你很好地理解它在做什么。然后仍然让 Angular 完成大部分工作,因为这是它擅长的。)

对于您的示例,按照您的操作方式,ng-hide 将不起作用,如果 scope.cameraRTSPUrl 的值发生更改,则该更改将不会反映在 UI 中。相反,请使用指令模板或templateUrl,这样您就可以访问 Angular 的数据绑定:

myApp.directive('videodata', function() {
    return {
        restrict: 'EA',
        scope : true,
        replace: true,
        templateUrl: 'templates/foo.html',
        link: function(scope, element, attrs) {
            scope.cameraRTSPUrl = "someGeneratedValue.mov"; // could passed into the directive via an attribute or parent data binding, for example
        }
    };
});

foo.html:

<div ng-hide="StartPlay" id="streamingarea">
    <object events="True" id="vlc" codebase="http://downloads.videolan.org/pub/videolan/vlc/latest/win32/axvlc.cab" 
        classid="clsid:9BE31822-FDAD-461B-AD51-BE1D1C159921">
        <embed width="800" height="600" target="{{cameraRTSPUrl}}" loop="no" autoplay="yes" 
        version="VideoLAN.VLCPlugin.2" type="application/x-google-vlc-plugin" id="123">
    </object>   
</div>

现在您只需更改scope.StartPlay 的真实性即可触发ng-hide,对scope.cameraRTSPUrl 的更改将自动出现在DOM 中。

如何使用transclude: true, 属性来替换我的 HTML?

这并不是transclude 的真正用途。 Transclude 允许您创建包含不是从该指令中生成的 html 的指令(来自其他地方的部分是“transcluded”位;transclude 指令是该 transcluded html 的包装器。)

【讨论】:

  • 感谢您的详细解释并将我的代码更改为上述工作并更改目标,但不幸的是我的视频无法播放。这是最初的问题,然后我求助于replaceWith 方法,该方法在目标更改时播放视频。我该如何克服这个问题?
  • 可能是一些事情。您如何将目标网址传递给指令? (有可能使用空目标 URL 绘制指令,视频“自动播放”失败,然后在下一个摘要中设置 cameraRTSPUrl - 如果是这种情况,最简单的解决方法可能是触发视频播放在链接函数中而不是依赖于自动播放。)如果这个猜测不正确,这可能是一个新的单独问题......
  • 用户将拖动视频链接并将其放在一个 div streamingarea 上。拖拽url前,生成的html为&lt;div ng-hide="StartPlay" id="streamingarea" class="ng-hide"&gt; &lt;object classid="clsid:9BE31822-FDAD-461B-AD51-BE1D1C159921" codebase="http://downloads.videolan.org/pub/videolan/vlc/latest/win32/axvlc.cab" id="vlc" events="True"&gt; &lt;embed width="800" height="600" id="123" type="application/x-google-vlc-plugin" version="VideoLAN.VLCPlugin.2" autoplay="yes" loop="no" target=""&gt; &lt;/object&gt; &lt;/div&gt;
  • 指令用法和目标设置后,html设置为&lt;div ng-hide="StartPlay" id="streamingarea" class=""&gt; &lt;object classid="clsid:9BE31822-FDAD-461B-AD51-BE1D1C159921" codebase="http://downloads.videolan.org/pub/videolan/vlc/latest/win32/axvlc.cab" id="vlc" events="True"&gt; &lt;embed width="800" height="600" id="123" type="application/x-google-vlc-plugin" version="VideoLAN.VLCPlugin.2" autoplay="yes" loop="no" target="rtsp://10.103.3.172/axis-media/media.amp"&gt; &lt;/object&gt; &lt;/div&gt;如何从链接函数中触发视频播放而不是依赖自动播放?
  • 在进一步分析中,我发现替换整个embed html 之后才开始播放视频。更改其目标 ot 自动播放选项不会产生任何影响,并且不会加载视频。如何使用您的解决方案替换整个 html?参考 - stackoverflow.com/questions/10629238/…
【解决方案2】:
Best way is to use template

template: 'Name: {{customer.name}} Address: {{customer.address}}'

 myApp.directive('videodata', function() {
    return {
        restrict: 'EA',
        scope : true ,
        link: function(scope, element, attrs) {
        template: '<object classid="clsid:9BE31822-FDAD-461B-AD51-BE1D1C159921" '+
                                    'codebase="http://downloads.videolan.org/pub/videolan/vlc/latest/win32/axvlc.cab" '+
                                    'id="vlc" events="True"> '+
                                    '<embed id="123" type="application/x-google-vlc-plugin" version="VideoLAN.VLCPlugin.2" autoplay="yes" '+
                                    'loop="no" width="800" height="600" target="'+scope.cameraRTSPUrl+'"> '+
                                '</object>'
        }
    };
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-25
    • 1970-01-01
    • 2014-06-24
    • 2015-06-21
    • 1970-01-01
    • 2017-05-26
    • 2014-03-07
    相关资源
    最近更新 更多