Ember更新视频源但未被浏览器反映

时间:2014-09-08 05:12:35

标签: javascript ember.js ember-data client-side

我有一个带有嵌套资源的ember应用程序,我在其中显示视频。外部资源(视频)只显示所有视频。单击视频时,将激活嵌套的video资源,并显示标题/播放器。

这非常适合您点击某些内容的第一次时间。视频显示并播放。但是,当点击另一个视频时,嵌套资源视频会更新,并且DOM <source>会更新,但OLD视频会继续播放!为什么会发生这种情况?如何解决?

Working Example on JSFiddle

5 个答案:

答案 0 :(得分:3)

我会使用一个组件来创建视频播放器,并将重新渲染逻辑包装在组件中。

该组件看起来像

App.VideoPlayerComponent = Ember.Component.extend({
  src: null,  
  rerenderPlayer: function(){
    if(this.$()) {
      Ember.run.debounce(this, this.rerender, 200);
    }
  },
  srcObserver: function(){
    this.rerenderPlayer();
  }.observes('src')
});

,组件模板看起来像

<script type="text/x-handlebars" data-template-name="components/video-player">
  <video controls>
  <source {{bind-attr src=src}} type = "video/mp4"></source>
  </video>
</script>

然后,您就可以像这样引用模板中的组件

<script type="text/x-handlebars" data-template-name="video">
  <h2>{{title}}</h2>
  {{video-player src=src}}
</script>

您可以在此处查看工作箱:http://emberjs.jsbin.com/fehipa/2/edit


作为奖励..如果您创建了视频播放器组件,您还可以完成暂停和播放组件中视频的功能。这样您就可以在应用中的任何位置使用完全可重复使用的视频播放器。

答案 1 :(得分:1)

如果您将{{bind-attr src="src"}}<source>元素移到<video>元素,它就可以正常运行。

您的代码将改为:

<video controls>
  <source {{bind-attr src="src"}} type = "video/mp4"></source>
</video>

<video controls {{bind-attr src="src"}}></video>

工作示例:http://jsfiddle.net/jfmzwhxx/

答案 2 :(得分:0)

它有点难看,但这可以通过重新渲染视图来实现。添加以下代码:

App.VideoRoute = Ember.Route.extend({
    oldVideoId: null,
    afterModel: function (resolvedModel) {
        if (this.get('oldVideoId') !== resolvedModel.id) {
            this.set('oldVideoId', resolvedModel.id);
            $.each(Ember.View.views, function( i, view ) {
                if (view.renderedName === "videos"){
                   view.rerender();
                }
            });
        }
    }
});

Working Fiddle

答案 3 :(得分:0)

我会对@AlliterativeAlice采取类似的方法,但我肯定不建议在路由级别执行此操作。这个问题是DOM安全性的结果,因此是视图的工作。您最好的选择是在视图类中设置一个观察者并从那里调用rerender。 E.g:

App.VideoView = Ember.View.extend({
  _didChangeVideoSrc: function() {
    // Make the view is still in the DOM
    if(this.$()) {
      this.rerender();
    }
  }.observes('controller.src')
});

我还更新了你的小提琴,使其成功:http://jsfiddle.net/rverobx9/2/

答案 4 :(得分:0)

虽然建议以任何方式重新渲染的答案可能会解决您的问题,但如果您可以访问播放器的API,那么很高兴看到您是否停止了willDestroyElement的视频视图不会解决这个问题。

此外,您可以让您的视频播放器成为Ember组件,确保良好的设置,拆卸和更新:

App.VideoPlayerComponent = Ember.Component.extend({
    source: null, // used in the template using that component
    isPlayerReady: false, // used to know internally if the player is ready

    setupPlayer: (function(){
      // somehow setup the video player if needed
      // (if Flash player for example, make the flash detection and whatever)
      // once ready, trigger our `videoPlayerReady` event
      this.set('isPlayerReady', true);
      this.trigger('videoPlayerReady');
    }).on('didInsertElement'),

    updatePlayerSource: (function(){
      // start playing if we have a source and our player is ready
      if ( this.get('isPlayerReady') && this.get('source') )
      {
        // replace with the correct js to start the video
        this.$('.class-of-player').videoPlay(this.get('source'));
      }
    }).observes('source').on('videoPlayerReady'),

    teardownSource: (function(){
      // stop playing if our player is ready since our source is going to change
      if ( this.get('source') && this.get('isPlayerReady') )
      {
        // replace with the correct js to stop the player
        this.$('.class-of-player').videoStop();
      }
    }).observesBefore('source'),

    teardownPlayer: (function(){
      // teardown the player somehow (do the opposite of what is setup in `setupPlayer`)
      // then register that our player isn't ready
      this.set('isPlayerReady', false);
    }).on('willDestroyElement')
});

这样您就可以确保所有内容都已正确设置和拆卸,并且由于它是您可以重复使用的组件,因此您可以很容易地回退到Flash播放器。然后,无论你必须处理和修复与玩家相关的东西,它都将在那个组件中,你只需要用播放器替换模板的一部分:

{{video-player source=ctrl.videoUrl}}