JSFiddle - React, Tailwind, and code Playground

by skirtle

HTML

<script src="https://unpkg.com/[email protected]/dist/vue.global.js"></script>
<div id="app">
  <p>
    Main application
  </p>
  <button @click="add">
    Add toast
  </button>
  <button :disabled="toasts.length === 0" @click="remove">
    Remove toast
  </button>
</div>

<div id="target"></div>

CSS

#target {
  border: 1px solid blue;
  padding: 10px;
}

.toast {
  border: 1px solid #777;
  padding: 5px;
}

JavaScript

const { createApp, h, render } = Vue

const Toast = {
  template: `<p class="toast">Toast - {{ egProp }} - {{ locale }}</p>`,
  props: ['egProp'],
  inject: ['locale']
}

const app = createApp({
  data () {
    return {
      count: 0,
      toasts: []
    }
  },
  methods: {
    add () {
      const vm = app.render(Toast, {
			  egProp: `Example ${++this.count}`
			}, '#target')
      
      this.toasts.push(vm)
    },
    remove () {
      app.unrender(this.toasts.shift())
    }
  }
})

app.render = function(Component, props, el) {
  if (typeof el === 'string') {
    el = document.querySelector(el)
  }

  if (!el) {
    throw new Error('el not found')
  }

  if (props && {}.toString.call(props) !== '[object Object]') {
    throw Error('props must be an object')
  }

  const childTree = h(Component, props)
  childTree.appContext = app._context

  // Creating a wrapper element here is clunky and ideally wouldn't be necessary
  const div = document.createElement('div')
  el.appendChild(div)

  render(childTree, div)

  return childTree.component.proxy
}

app.unrender = function (vm) {
  const el = vm.$el.parentNode
  
  render(null, el)
  
  el.parentNode.removeChild(el)
}

app.provide('locale', 'en')

app.mount('#app')