Encapsulate the wangEditor5 component to implement the v-model command

1. Goal

Goal: On the basis of wangEditor5 editor, encapsulate it into its own editor component and realize the v-model instruction.

2. Preparations

  1. Download and install wangEditor
npm i @wangeditor/editor @wangeditor/editor-for-vue -s
  1. Add the MyEditor.vue file in the component components and initialize the file:
// MyEditor.vue 文件
<template>
    <div style="border: 1px solid #ccc;">
        <Toolbar
            style="border-bottom: 1px solid #ccc"
            :editor="editor"
            :defaultConfig="toolbarConfig"
            :mode="mode"
        />
        <Editor
            style="height: 500px; overflow-y: hidden;"
            v-model="html"
            :defaultConfig="editorConfig"
            :mode="mode"
            @onCreated="onCreated"
        />
    </div>
</template>

<script>
import Vue from 'vue'
import {
    
     Editor, Toolbar } from '@wangeditor/editor-for-vue'

export default Vue.extend({
    
    
    components: {
    
     Editor, Toolbar },
    data() {
    
    
        return {
    
    
            editor: null,
            html: '<p>hello</p>',
            toolbarConfig: {
    
     },
            editorConfig: {
    
     placeholder: '请输入内容...' },
            mode: 'default', // or 'simple'
        }
    },
    methods: {
    
    
        onCreated(editor) {
    
    
            this.editor = Object.seal(editor) // 一定要用 Object.seal() ,否则会报错
        },
    },
    beforeDestroy() {
    
    
        const editor = this.editor
        if (editor == null) return
        editor.destroy() // 组件销毁时,及时销毁编辑器
    }
})
</script>

<style src="@wangeditor/editor/dist/css/style.css"></style>

  1. Add to parent component and add v-model directive on custom component my-editor
// 父组件
<template>
  <div class="page">
        <my-editor v-model="msg"></my-editor>
  </div>
</template>

<script>
import MyEditor from '../components/Editor.vue'
export default {
    
    
    data(){
    
    
        return {
    
    
            msg:'andy'
        }
    },
    methods:{
    
    
    },
    components:{
    
    
        MyEditor
    }
}
</script>

The preparatory work has been completed above, but the v-model directive cannot be used directly on the custom component, and further processing is required.

3. Knowledge points

1). Syntactic sugar: refers to a certain syntax added to a computer language. This syntax has no actual impact on the compilation results and functions of the language, but it makes it easier for programmers to use the language. The use of syntactic sugar can reduce the amount of code and increase the readability of the program, thereby reducing the chance of program code errors.

2). v-model is a syntactic sugar that will be parsed into a custom attribute named value :valueand a custom event named input@input

// 以下两行代码功能相同,实现了数据的双向绑定
<input type="text" v-model="msg">
<input type="text" :value="msg" @input="">

4. Business realization

  1. So the data transfer method that my-editor 组件can be passed through this custom attribute父传子props 接收 value
// MyEditor.vue 文件
props:{
    
    
        value:{
    
    
            type:String
        }
    },
  1. Monitor the value change through the watch listener and assign it to the editor editor
// MyEditor.vue 文件
// 父组件传过来的值通过 watch 进行监听,变化,就重新赋给编辑器
watch:{
    
    
    value(val) {
    
    
         const context = `<p>${
      
      val}</p>`
         this.editor.setHtml(context);
         // this.html = context; 和上一行代码实现效果一样
        }
    },
  1. The editor onChange() 函数监listens to the change of the content value, changes, and 子传父passes the latest value to the msg in the parent component through the data transmission method
    (the child component only needs to pass the latest content of the editor through this.$emit(), The v-model in the parent component will automatically receive @input custom events, no need to add additional @input events)
// MyEditor.vue 文件
// onChange()函数: 当编辑器内容、选区变化时的回调函数 
// 将变化的数据通过 editor.getText() 得到,通过 子传父 this.$emit 传给父组件
onChange(editor) {
    
    
      const text = editor.getText();
      this.$emit('input',text);
},
  1. Assign an initial value to the editor, once entering the page, the content of the editor displays the value passed from the parent component
// MyEditor.vue 文件
// 方法1 在 created 生命周期中赋初值
created() {
    
    
     // 赋初值
     this.html = `<p>${
      
      this.value}</p>`;
},

// 方法2 在 onCreate 函数中赋初值
onCreated(editor) {
    
    
        this.editor = Object.seal(editor) // 一定要用 Object.seal() ,否则会报错
        // onCreated 编辑器创建完毕时的回调函数。赋 父组件给的初值
        this.editor.setHtml(`<p>${
      
      this.value}</p>`);
},

5. Summary

On the basis of wangEditor5, add v-model instruction and package it as a custom component.

In fact, it lies in the understanding of v-model, v-modelwhich can be regarded :value 和 @inputas the subcomponent my-editor passed through 父传子 props 接收 value. 子传父 this.$emit( ) 传递最新值到 父组件 @inputv-model syntax sugar simplifies the writing of parent component code.

6. Fully implement the code

// 父组件
<template>
  <div class="page">
    <input type="text" v-model="msg">
        <my-editor v-model="msg"></my-editor>
  </div>
</template>

<script>
import MyEditor from '../components/Editor.vue'
export default {
    
    
    data(){
    
    
        return {
    
    
            msg:'xindy'
        }
    },
    methods:{
    
    
    },
    components:{
    
    
        MyEditor
    }
}
</script>

// MyEditor.vue 文件
<template>
    <div style="border: 1px solid #ccc;">
        <Toolbar
            style="border-bottom: 1px solid #ccc"
            :editor="editor"
            :defaultConfig="toolbarConfig"
            :mode="mode"
        />
        <Editor
            style="height: 500px; overflow-y: hidden;"
            v-model="html"
            :defaultConfig="editorConfig"
            :mode="mode"
            @onCreated="onCreated"
            @onChange="onChange"
        />
    </div>
</template>


<script>
import Vue from 'vue'
import {
    
     Editor, Toolbar } from '@wangeditor/editor-for-vue'

export default Vue.extend({
    
    
    components: {
    
     Editor, Toolbar },
    data() {
    
    
        return {
    
    
            editor: null,
            html: '',
            toolbarConfig: {
    
     },
            editorConfig: {
    
     placeholder: '请输入内容...' },
            mode: 'default', // or 'simple'
        }
    },
    props:{
    
    
        value:{
    
    
            type:String
        }
    },
    methods: {
    
    
        onCreated(editor) {
    
    
            this.editor = Object.seal(editor) // 一定要用 Object.seal() ,否则会报错
            // onCreated 编辑器创建完毕时的回调函数。赋 父组件给的初值
             this.editor.setHtml(`<p>${
      
      this.value}</p>`);

        },
        // onChange 编辑器内容、选区变化时的回调函数 将变化的数据通过 editor.getText() 得到,通过 子传父 this.$emit 传给父组件
        onChange(editor) {
    
    
            const text = editor.getText();
            this.$emit('input',text);
        },
    },
    // 父组件传过来的值通过 watch 进行监听,变化,就重新赋给 编辑器
    watch:{
    
    
        value(val) {
    
    
            const context = `<p>${
      
      val}</p>`
            this.editor.setHtml(context);
            // this.html = context;
        }
    },
    created() {
    
    
        // 赋初值
        // this.html = `<p>${this.value}</p>`;
    },
    beforeDestroy() {
    
    
        const editor = this.editor
        if (editor == null) return
        editor.destroy() // 组件销毁时,及时销毁编辑器
    }
})
</script>

<style src="@wangeditor/editor/dist/css/style.css"></style>

Guess you like

Origin blog.csdn.net/qq_45050686/article/details/128020615