Wrapping a JS library in a Vue Component

Viewed 322

I need to know which is best practice for wrapping a JS DOM library in Vue. As an example I will use EditorJS.

<template>
    <div :id="holder"></div>
</template>

import Editor from '@editorjs/editorjs'

export default {
  name: "editorjs-wrapper",
  props: {
    holder: {
      type: String,
      default: () => {return "vue-editor-js"},
      required: true
    }
  },
  data(){
    return {
        editor: null
    };
  },
  methods: {
    init_editor(){
      this.editor = new Editor({
        holder: this.holder,
        tools: {
        }
      });
    }
  },
  mounted(){
    this.init_editor();
  },
    //... Destroy on destroy
}

First:

Supose I have multiple instances of <editorjs-wrapper> in the same View without a :hook then all intances would have the same id.

<div id="app">
    <editorjs-wrapper></editorjs-wrapper>
    <editorjs-wrapper></editorjs-wrapper>
</div>

Things get little weird since they both try to process the DOM #vue-editor-js. Would it be better if the component generated a random id as default?

Second:

EditorJS provides a save() method for retrieving its content. Which is better for the parent to be able to call save() method from the EditorJS inside the child?

I have though of two ways:

  • $emit and watch (Events)

// Parent
<div id="#app">
    <editorjs-wrapper @save="save_method" :save="save">
</div>
// Child

...
    watch: {
        save: {
            immediate: true,
            handler(new_val, old_val){
                if(new_val) this.editor.save().then(save=>this.$emit('save', save)) // By the way I have not tested it it might be that `this` scope is incorrect... 
            }
        }
    }
...

That is, the parent triggers save in the child an thus the child emits the save event after calling the method from the EditorJS.

  • this.$refs.childREF This way would introduce tight coupling between parent and child components.

Third:

If I want to update the content of the child as parent I don't know how to do it, in other projects I have tried without success with v-modal for two way binding:

export default{
    name: example,
    props:{
        content: String
    },
    watch:{
        content: {
            handler(new_val, old_val){
                this.update_content(new_val);
            }
        }
    },
    data(){
        return {
            some_js_framework: // Initialized at mount        
        }
    },
    methods: {
        update_content: function(new_val){
            this.some_js_framework.update(new_val)
        },
        update_parent: function(new_val){
            this.$emit('input', this.some_js_framework.get_content());
        }
    },
    mounted(){
        this.some_js_framework = new Some_js_framework();
        this.onchange(this.update_parent);
    }
}

The problem is:

  1. Child content updated
  2. Child emit input event
  3. Parent updates the two-way bidding of v-model
  4. Since the parent updated the value the child watch updates and thus onchange handler is triggered an thus 1. again.
0 Answers
Related