JSFiddle - React, Tailwind, and code Playground

by skirtle

HTML

<script src="https://unpkg.com/[email protected]/dist/vue.global.js"></script>
<div id="app">
  <button @click="onClick">
    Change
  </button>
  <input-component :class="a" :style="{ fontWeight: b }" :value="c" :data-value="c"></input-component>
</div>

CSS

.red {
  color: red;
}

JavaScript

const { createApp, onBeforeUpdate, ref, onRenderTracked, onRenderTriggered } = Vue

// Function to partition the attrs
const splitter = function (attrs) {
  const outer = {}
  const inner = {}

  for (const prop in attrs) {
    if (/^(class$|style$|data-)/.test(prop)) {
      outer[prop] = attrs[prop]
    } else {
      inner[prop] = attrs[prop]
    }
  }

  return { inner, outer }
}

const InputComponent = {
  inheritAttrs: false,

  template: `
		<div v-bind="splitAttrs.outer">
			Label:
			<input v-bind="splitAttrs.inner">
		</div>
	`,

  setup (props, ctx) {
    const splitAttrs = ref(splitter(ctx.attrs))
    
    // Called after render, which is too late
    onBeforeUpdate(() => {
      //splitAttrs.value = splitter(ctx.attrs)
    })

    onRenderTracked(() => {
      console.log('tracked')
      splitAttrs.value = splitter(ctx.attrs)
    })

    onRenderTriggered(() => {
      console.log('triggered')
      //splitAttrs.value = splitter(ctx.attrs)
    })

    return {
      splitAttrs
    }
  }
}    

createApp({
  components: {
    InputComponent
  },
  
  data () {
    return {
      a: 'red',
      b: 'bold',
      c: 'Hi'
    }
  },
  
  methods: {
    onClick () {
      this.a = 'red'.replace(this.a, '')
      this.b = 'bold'.replace(this.b, '')
      this.c += '!'
    }
  }
}).mount('#app')