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:
$emitand 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.childREFThis 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:
- Child content updated
- Child emit
inputevent - Parent updates the two-way bidding of
v-model - Since the parent updated the value the child watch updates and thus
onchangehandler is triggered an thus 1. again.