使用附加的 svelte 组件并在相同的 Javascript 上下文中创建窗口
Posted
技术标签:
【中文标题】使用附加的 svelte 组件并在相同的 Javascript 上下文中创建窗口【英文标题】:Create window with attached svelte component and in the same Javascript context 【发布时间】:2020-01-30 21:43:52 【问题描述】:我使用 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 样式?
或者创建此类窗口的最佳做法是什么?
【问题讨论】:
【参考方案1】:我通过简单地从父窗口传输所有样式解决了这个问题(参见appendCss
函数)
如果您使用 sapper,则只能传输以下样式:
link[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 上下文中创建窗口的主要内容,如果未能解决你的问题,请参考以下文章