Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/468.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 将Iframe传递给SPA中的不同组件(类似于Youtube)_Javascript_Html_Css_Vue.js - Fatal编程技术网

Javascript 将Iframe传递给SPA中的不同组件(类似于Youtube)

Javascript 将Iframe传递给SPA中的不同组件(类似于Youtube),javascript,html,css,vue.js,Javascript,Html,Css,Vue.js,因此,由于Youtube有一段时间可以在页面导航时最小化Youtube播放器的功能,LolEsports.com与Twitch和嵌入式Youtube播放器有类似的功能 我想给我的页面带来一个类似的功能,基本上我的状态如下: 前端的Vue 在子URL上嵌入Youtube播放器 当我离开子URL时,我希望Youtube播放器移动到当前状态的角落,并且仍然在那里 我希望听到一些关于如何实现这一点的灵感,因为当我尝试在不同组件上传递状态重置时,以及播放停止等 我很想听听你的想法。简单的回答是:你不能

因此,由于Youtube有一段时间可以在页面导航时最小化Youtube播放器的功能,LolEsports.com与Twitch和嵌入式Youtube播放器有类似的功能

我想给我的页面带来一个类似的功能,基本上我的状态如下:

  • 前端的Vue
  • 在子URL上嵌入Youtube播放器
  • 当我离开子URL时,我希望Youtube播放器移动到当前状态的角落,并且仍然在那里
我希望听到一些关于如何实现这一点的灵感,因为当我尝试在不同组件上传递状态重置时,以及播放停止等


我很想听听你的想法。简单的回答是:你不能移动iframe DOM节点而不丢失它的状态,如前所述

答案很长:你有其他选择。我认为你最好的办法是直接在“角落播放器”中播放视频,然后重新设置样式,使其位于页面的正确位置。要做到这一点,您需要自己与DOM进行一些交互,通过在希望视频显示的容器上设置
ref
,您可以轻松地进行交互

最后你会得到这样的结果:

在App.vue中,您有标准的
路由器视图
,以及一些包含实际视频的元素

<template>
  <div id="app">
    <router-view/>
    <corner-player/>
  </div>
</template>
播放器组件然后使用这两个事件,并确保应用了正确的样式。我不建议像这里这样应用原始css,但这是一个概念证明

<template>
  <div class="corner-player" :style="styling" v-if="url">
    <iframe
      width="1280"
      height="540"
      :src="url"
      frameborder="0"
      allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
      allowfullscreen
    ></iframe>
  </div>
</template>

<script>
export default {
  name: "CornerPlayer",

  data() {
    return {
      styling: {},
      url: "",

      defaultStyling: {
        border: "3px solid blue",
        position: "fixed",
        bottom: 0,
        right: 0,
        height: "150px",
        width: "220px"
      }
    };
  },

  created() {
    this.$bus.$on("play-video", this.playVideo);
    this.$bus.$on("move-to-corner-player", this.moveToCornerPlayer);
  },

  beforeDestroy() {
    // Prevent memory leaks
    this.$bus.$off("play-video", this.playVideo);
    this.$bus.$off("move-to-corner-player", this.moveToCornerPlayer);
  },

  methods: {
    playVideo({ url, styling }) {
      this.url = url;
      this.styling = styling;
    },

    moveToCornerPlayer() {
      this.styling = {
        ...this.defaultStyling
      };
    }
  }
};
</script>

<style scoped>
iframe {
  width: 100%;
  height: 100%;
}
</style>

导出默认值{
姓名:“角落玩家”,
数据(){
返回{
样式:{},
url:“”,
默认样式:{
边框:“3件纯蓝”,
位置:“固定”,
底部:0,
右:0,,
高度:“150px”,
宽度:“220px”
}
};
},
创建(){
this.$bus.$on(“播放视频”,this.playVideo);
this.$bus.$on(“移动到角落玩家”,this.moveToCornerPlayer);
},
在…之前{
//防止内存泄漏
this.$bus.$off(“播放视频”,this.playVideo);
此。$bus。$off(“移动到角落玩家”,此。移动到角落玩家);
},
方法:{
播放视频({url,样式设置}){
this.url=url;
this.style=样式化;
},
moveToCornerPlayer(){
此项。样式设置={
…这是默认样式
};
}
}
};
iframe{
宽度:100%;
身高:100%;
}
您可以在Codesandbox上玩这个:


谢谢Sumurai8!为了使iframe容器更具响应性,我对您的CodeSandbox进行了一些编辑:


因此,现在在滚动和刷新时,容器将缩放并保持在相同的位置。

非常感谢您非常有趣的方法,我尝试将其引入我的应用程序,并成功地实现了这一点,我决定不使用事件总线,而是选择Vuex,但我想如果不是为了简单起见,你也会这么做。可能会使用事件总线来处理事件,比如通过时间戳向前跳转,因为如果没有观察者和商店的东西,这是行不通的,除非有更好的方法让我知道:)是的,Vuex也可以工作。在这种情况下,您将处理vuex模块中的状态,而不是组件中的状态。除此之外,同样的情况仍然适用。我同意使用事件跳过视频可能是最好的选择,特别是如果您使用某种库与播放器交互,而不仅仅是用一些神奇的url重新加载iframe。
export default {
  name: "child1",

  mounted() {
    const container = this.$refs.player;
    const boundingBox = container.getBoundingClientRect();

    this.$bus.$emit("play-video", {
      url: "https://www.youtube.com/embed/dW4HCi1zZh8",
      styling: {
        position: "absolute",
        top: `${boundingBox.top}px`,
        left: `${boundingBox.left}px`,
        width: `${boundingBox.width}px`,
        height: `${boundingBox.height}px`,
        border: "3px dotted red"
      }
    });
  },

  beforeDestroy() {
    this.$bus.$emit("move-to-corner-player");
  }
};
<template>
  <div class="corner-player" :style="styling" v-if="url">
    <iframe
      width="1280"
      height="540"
      :src="url"
      frameborder="0"
      allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
      allowfullscreen
    ></iframe>
  </div>
</template>

<script>
export default {
  name: "CornerPlayer",

  data() {
    return {
      styling: {},
      url: "",

      defaultStyling: {
        border: "3px solid blue",
        position: "fixed",
        bottom: 0,
        right: 0,
        height: "150px",
        width: "220px"
      }
    };
  },

  created() {
    this.$bus.$on("play-video", this.playVideo);
    this.$bus.$on("move-to-corner-player", this.moveToCornerPlayer);
  },

  beforeDestroy() {
    // Prevent memory leaks
    this.$bus.$off("play-video", this.playVideo);
    this.$bus.$off("move-to-corner-player", this.moveToCornerPlayer);
  },

  methods: {
    playVideo({ url, styling }) {
      this.url = url;
      this.styling = styling;
    },

    moveToCornerPlayer() {
      this.styling = {
        ...this.defaultStyling
      };
    }
  }
};
</script>

<style scoped>
iframe {
  width: 100%;
  height: 100%;
}
</style>