在新窗口打开 VueJS 组件

新手上路,请多包涵

我有一个只有一页的基本 VueJS 应用程序。它不是 SPA,我也不使用 vue-router。

我想实现一个按钮,单击该按钮时会使用我的一个 Vue 组件中的内容执行 window.open() 函数。

查看来自 window.open() 的文档—我看到了以下 URL 语句:

URL 接受 HTML 页面、图像文件或浏览器支持的任何其他资源的路径或 URL。

是否可以将组件作为 window.open() 的参数传递?

原文由 user3142 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 618
1 个回答

我能够使用 一篇关于 React 中的 Portals 的文章中的 一些见解来创建一个 Vue 组件,该组件能够将其子项安装在新窗口中,同时保持反应性!很简单:

 <window-portal>
  I appear in a new window!
</window-portal>

在这个 codeandbox 中试试吧!

该组件的代码如下:

 <template>
  <div v-if="open">
    <slot />
  </div>
</template>

<script>
export default {
  name: 'window-portal',
  props: {
    open: {
      type: Boolean,
      default: false,
    }
  },
  data() {
    return {
      windowRef: null,
    }
  },
  watch: {
    open(newOpen) {
      if(newOpen) {
        this.openPortal();
      } else {
        this.closePortal();
      }
    }
  },
  methods: {
    openPortal() {
      this.windowRef = window.open("", "", "width=600,height=400,left=200,top=200");
      this.windowRef.addEventListener('beforeunload', this.closePortal);
      // magic!
      this.windowRef.document.body.appendChild(this.$el);
    },
    closePortal() {
      if(this.windowRef) {
        this.windowRef.close();
        this.windowRef = null;
        this.$emit('close');
      }
    }
  },
  mounted() {
    if(this.open) {
      this.openPortal();
    }
  },
  beforeDestroy() {
    if (this.windowRef) {
      this.closePortal();
    }
  }
}
</script>

关键是这一行 this.windowRef.document.body.appendChild(this.$el) ;此行有效地从父窗口中删除与 Vue 组件关联的 DOM 元素(顶级 <div> )并将其插入到子窗口的主体中。由于此元素与 Vue 通常会更新的 _引用相同_,只是在不同的位置,所以一切都 Just Works - Vue 继续更新元素以响应数据绑定更改,尽管它已安装在新窗口中。我真的很惊讶这是多么简单!

原文由 Alex Van Liew 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题