在新窗口中打开一个 VueJS 组件 [英] Open a VueJS component on a new window
问题描述
我有一个只有一页的基本 VueJS 应用程序.它不是 SPA,我也不使用 vue-router.
我想实现一个按钮,当点击该按钮时,它会使用我的一个 Vue 组件中的内容执行 window.open() 函数.
查看来自 window.open()
我看到以下 URL 语句:
URL 接受指向 HTML 页面、图像文件或浏览器支持的任何其他资源的路径或 URL.
是否可以将组件作为 window.open()
的参数传递?
我能够使用来自 一篇关于 React 中的 Portals 的文章 创建一个 Vue 组件,该组件能够在新窗口中挂载其子项,同时保持反应性!就这么简单:
我出现在一个新窗口!</窗口门户>
在这个 codesandbox 中试试吧!
该组件的代码如下:
<div v-if="打开"><插槽/>
</模板><脚本>导出默认{name: '窗口门户',道具: {打开: {类型:布尔型,默认值:假,}},数据() {返回 {窗口引用:空,}},手表: {打开(新打开){如果(新打开){this.openPortal();} 别的 {this.closePortal();}}},方法: {打开门户(){this.windowRef = window.open("", "", "width=600,height=400,left=200,top=200");this.windowRef.addEventListener('beforeunload', this.closePortal);//魔法!this.windowRef.document.body.appendChild(this.$el);},关闭门户(){如果(this.windowRef){this.windowRef.close();this.windowRef = null;this.$emit('close');}}},安装(){如果(this.open){this.openPortal();}},beforeDestroy() {如果(this.windowRef){this.closePortal();}}}
关键是行this.windowRef.document.body.appendChild(this.$el)
;这一行有效地从父窗口中删除了与 Vue 组件(顶级
I have a basic VueJS application with only one page. It's not a SPA, and I do not use vue-router.
I would like to implement a button that when clicked executes the window.open() function with content from one of my Vue Components.
Looking at the documentation from window.open()
I saw the following statement for URL:
URL accepts a path or URL to an HTML page, image file, or any other resource which is supported by the browser.
Is it possible to pass a component as an argument for window.open()
?
I was able to use some insights from an article about Portals in React to create a Vue component which is able to mount its children in a new window, while preserving reactivity! It's as simple as:
<window-portal>
I appear in a new window!
</window-portal>
Try it in this codesandbox!
The code for this component is as follows:
<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>
The key is the line this.windowRef.document.body.appendChild(this.$el)
; this line effectively removes the DOM element associated with the Vue component (the top-level <div>
) from the parent window and inserts it into the body of the child window. Since this element is the same reference as the one Vue would normally update, just in a different place, everything Just Works - Vue continues to update the element in response to databinding changes, despite it being mounted in a new window. I was actually quite surprised at how simple this was!
这篇关于在新窗口中打开一个 VueJS 组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!