Да, существует более правильный способ клонирования содержимого компонента и отображения его во всплывающем окне, используя методы `cloneVNode` и `render` вместо `cloneNode` и `append`.
Вместо атрибута `ref` вы можете использовать слот `<template>` для обертки содержимого, которое вы хотите склонировать. Ваш код может выглядеть следующим образом:
```html
<div ref="overlay">
<div ref="popup"></div>
</div>
<div>
<template ref="clone">
...
</template>
<button @click="openPopup"></button>
</div>
```
Затем вы можете использовать методы `cloneVNode` и `render` для клонирования и отрисовки содержимого в блоке "popup":
```javascript
methods: {
openPopup() {
const cloneVNode = this.$options.render.call(this, this.$createElement)
this.$refs.popup.innerHTML = ''
this.$refs.popup.appendChild(cloneVNode.el)
}
}
```
Этот способ более "правильный", потому что он использует внутренний рендеринг Vue, который может учитывать состояние компонента и обновлять только измененные части. Таким образом, вы можете избежать потери данных или обновления всего компонента.
Также обратите внимание, что использование `innerHTML` может привести к потере привязки данных Vue. Если вы хотите сохранить привязку данных Vue, вы можете использовать `v-html` вместо `innerHTML`:
```html
<div ref="overlay">
<div ref="popup">
<div v-html="popupContent"></div>
</div>
</div>
<div>
<template>
<div>
...
</div>
</template>
<button @click="openPopup"></button>
</div>
```
В этом случае, вместо использования `appendChild`, вы можете обновить `popupContent` в методе `openPopup`:
```javascript
data() {
return {
popupContent: ''
}
},
methods: {
openPopup() {
const cloneVNode = this.$options.render.call(this, this.$createElement)
this.popupContent = cloneVNode.el.outerHTML
}
}
```
Теперь клонирование будет сохранять привязку данных Vue и обновляться при изменении состояния компонента.