gpt4 book ai didi

svelte - 在相同的 Javascript 上下文中创建带有附加 svelte 组件的窗口

转载 作者:行者123 更新时间:2023-12-05 05:08:34 24 4
gpt4 key购买 nike

我使用 Sapper 框架,我想打开我自己的开发工具窗口,该窗口应该可以完全访问主窗口的 Javascript 对象。

我正在尝试创建一个带有精巧组件和相同 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,
})

它可以工作,但没有 CSS 样式。

您可以使用 this REPL用于测试。

如何为新窗口应用组件 CSS 样式?

或者创建此类窗口的最佳做法是什么?

最佳答案

我通过简单地从父窗口传输所有样式解决了这个问题(参见 appendCss 函数)

如果您使用 sapper,您只能传输这些样式:链接[rel="stylesheet"][href^="client/"]

下面是完整的解决方案,您还可以查看 this REPL

ComponentWindow.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
}
}
}

用法:

<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>

关于svelte - 在相同的 Javascript 上下文中创建带有附加 svelte 组件的窗口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58187495/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com