vp-frameRender.ts 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  1. //@ts-nocheck
  2. import { createApp, defineComponent, h, onBeforeUpdate, onMounted, ref } from 'vue'
  3. // eslint-disable-next-line vue/one-component-per-file
  4. export default defineComponent({
  5. name: 'RenderToIFrame',
  6. props: {
  7. css: {
  8. type: String,
  9. default: '',
  10. },
  11. },
  12. setup(props, { slots }) {
  13. const iframeRef = ref<HTMLElement | null>(null)
  14. const iframeBody = ref<HTMLElement | null>(null)
  15. const iframeHead = ref(null)
  16. const iframeStyle = ref(null)
  17. let iframeApp = null
  18. onMounted(() => {
  19. iframeBody.value = iframeRef.value.contentDocument.body
  20. iframeHead.value = iframeRef.value.contentDocument.head
  21. const el = document.createElement('div')
  22. iframeRef.value?.classList.add('playground-iframe')
  23. el.id = 'app'
  24. iframeBody.value.appendChild(el)
  25. iframeStyle.value = document.createElement('style')
  26. iframeStyle.value.innerHTML = props.css
  27. iframeHead.value.appendChild(iframeStyle.value)
  28. // eslint-disable-next-line vue/one-component-per-file
  29. iframeApp = createApp({
  30. name: 'IframeRender',
  31. setup() {
  32. return () => slots.default()
  33. },
  34. }).mount(el)
  35. })
  36. onBeforeUpdate(() => {
  37. if (!iframeApp || !iframeRef.value) {
  38. return
  39. }
  40. if (props.css) {
  41. iframeStyle.value.innerHTML = props.css
  42. }
  43. })
  44. return () => h('iframe', { ref: iframeRef })
  45. },
  46. })