Home > Net >  How to wrap JS library which creates elements by itself into Vue component with slot?
How to wrap JS library which creates elements by itself into Vue component with slot?

Time:12-05

I have vanilla JS library which is given root element and callback function (data: any) => HTMLElement. Library calls callback and positions elements within root one.

I want to wrap this library into Vue component with slot to use it like this:

<my-component v-slot='data'>
  <div>{{data.field}}</div>
</my-component>

Slots returned by useSlots are functions which, being called, return virtual DOM. How can I turn this into real DOM element retaining reactivity?

CodePudding user response:

It sounds like you want to create a custom Vue component that uses a vanilla JavaScript library to create elements within the component. To do this, you can create a custom Vue component using the Vue.component() method, and then use the library within the render function of the component.

Here is an example of how this might work:

Vue.component('my-component', {
  render: function (createElement) {
    // Use the createElement function to create a root element for the component
    let root = createElement('div');

    // Use the vanilla JS library to create elements within the root element
    let elements = myLibrary(root, (data) => {
      return createElement('div', data.field);
    });

    // Return the root element with the generated elements as children
    return root;
  }
});

The above code will create a custom Vue component called my-component that uses the myLibrary function to generate elements within the component. You can then use the component in your Vue app like this:

<my-component>
  <!-- Use the slot to provide a template for the generated elements -->
  <template v-slot="data">
    <div>{{data.field}}</div>
  </template>
</my-component>

This will render the elements generated by the myLibrary function using the provided template. The generated elements will be reactive, so any changes to the data will be reflected in the rendered elements.

CodePudding user response:

Seems to work this way:

const component = defineComponent({
  props: ['data', 'render'],
  render: function() {
    return this.render(this.data)
  },
})
function callback(data: any): Element {
  const elem = document.createElement('div')
  const app = createApp(component, {render: slots.default!, data})
  app.mount(elem);
  return elem
}
  • Related