[英]Create window with attached svelte component and in the same Javascript context
I use the Sapper framework and I want to open my own dev tools window that should have full access to Javascript objects of the main window.我使用 Sapper 框架,我想打开我自己的开发工具 window,它应该可以完全访问主 window 的 Javascript 对象。
I'm trying to create a new window with a svelte component and with same Javascript context:我正在尝试创建一个新的 window 与一个苗条的组件和相同的 Javascript 上下文:
var win = window.open('abour:blank')
var container = win.document.createElement('div')
var win.document.body.appendChild(container)
var component = new ComponentClass({
target: container,
})
It works but without CSS styles.它可以工作,但没有 CSS styles。
You can use this REPL for tests.您可以使用此 REPL进行测试。
How can I apply the component CSS styles for the new window?如何为新的 window 应用组件 CSS styles?
Or what is the best practices to create such windows?或者创建这样的 windows 的最佳实践是什么?
I solved this problem by simply transferring all styles from the parent window (see the appendCss
function)我通过简单地从父 window 转移所有 styles 解决了这个问题(参见
appendCss
函数)
If you use sapper you can transfer only these styles: link[rel="stylesheet"][href^="client/"]
如果您使用工兵,您只能传输这些 styles:
link[rel="stylesheet"][href^="client/"]
Full solution bellow and you can also see this REPL下面是完整的解决方案,您还可以看到这个 REPL
ComponentWindow.ts组件窗口.ts
export class ComponentWindow {
constructor({
windowName = '',
windowFeatures = 'width=600,height=400,resizable,scrollbars=yes,status=1',
replace = false,
}: {
windowName?: string,
windowFeatures?: string,
replace?: boolean,
} = {}) {
this._windowOptions = [ 'about:blank', windowName, windowFeatures, replace ]
}
// region create window
private readonly _windowOptions: any[]
private _window
public get window() {
if (!this.isOpened) {
this._window = window.open(...this._windowOptions)
this.appendCss()
this.appendContainer()
}
return this._window
}
private appendCss() {
const {window: _window} = this
const parentStyleElements = Array.from(window.document.querySelectorAll(
'link[rel="stylesheet"][href^="client/"], style',
))
for (let i = 0; i < parentStyleElements.length; i++) {
const parentStyleElement = parentStyleElements[i]
let styleElement
switch (parentStyleElement.tagName) {
case 'LINK':
styleElement = _window.document.createElement('link')
styleElement.rel = 'stylesheet'
styleElement.href = (parentStyleElement as any).href
break
case 'STYLE':
styleElement = _window.document.createElement('style')
styleElement.id = parentStyleElement.id
styleElement.innerHTML = parentStyleElement.innerHTML
break
default:
throw new Error('Unexpected style element: ' + styleElement.tagName)
}
_window.document.head.appendChild(styleElement)
}
}
private appendContainer() {
const {window} = this
window.container = window.document.createElement('div')
window.document.body.appendChild(window.container)
}
// endregion
// region attachComponent
private _component
public attachComponent(componentClass?, options?) {
let {_component} = this
if (_component) {
_component.$destroy()
this._component = _component = null
}
if (!componentClass) {
return
}
const {window} = this
_component = new componentClass({
...options,
target: window.container,
})
this._component = _component
window.addEventListener('beforeunload', () => {
this.attachComponent()
})
return _component
}
// endregion
public get isOpened() {
return this._window && !this._window.closed
}
public focus() {
if (this.isOpened) {
this._window.focus()
}
}
public destroy() {
this.attachComponent()
if (this.isOpened) {
this._window.close()
this._window = null
}
}
}
Usage:用法:
<script>
import {ComponentWindow} from './ComponentWindow.js'
import ComponentClass from './ComponentClass.svelte'
import {onMount, onDestroy} from 'svelte'
let componentWindow = new ComponentWindow()
let component
let value = 10
onDestroy(() => componentWindow.destroy())
$: if (component) component.$set({ value })
async function openComponentWindow() {
if (componentWindow.isOpened) {
componentWindow.focus()
return
}
component = await componentWindow.attachComponent(ComponentClass, {
props: {
value
}
})
componentWindow.focus()
}
</script>
<button on:click="{openComponentWindow}">Open component Window</button><br>
<button on:click="{() => value++}">Change value</button>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.