preface

Today to write this article is mainly to solve how to use the rich text editor in vue to add a custom menu, a key to achieve through rich text uploaded pictures typesetting function make the default styles center fixed width processing images, text first line indentation, and other functions, from the source to eliminate the portal website to show users write, copy and other problems such as image design layout disorder;Copy the code

1. Create an independent file wlayoutmenu.js

First create a separate file wlayoutmenu. js and write the following code content in the fileCopy the code
/ * * *@module WLayoutMenu One button for typesetting@author cy
 * @date 2021/03/29
 * @description Customize a one-click typesetting function */
/ / introduce wangEditor
import E  from "wangeditor";
const { $, BtnMenu } = E;
 
// Set the default style
const initPStyle = "text-indent: 2em; margin: 0; font-size: 1em; font-weight: normal; color: #000";
export default class wLayoutMenu extends BtnMenu {
    constructor(editor) {
        // The data-title attribute indicates the function description of the button when the mouse hovers over it
        const $elem = $(` < div class = "w - e - the menu data -" title = "one-click publishing" > < I class = "el - -help icon - s" > < / I > < / div > `);
        super($elem, editor);
    }
 
    clickHandler() {
        // Get the DOM of the rich text editing area
        let childDoms = this.editor.$textElem.elems[0].childNodes;
        if (childDoms.length > 0) {
            childDoms.forEach(item= > {
                // Rich text editing content is enclosed by the p tag by default, so the default typesetting style is set directly on the P tag
                if(item.nodeName == 'P') {
                    item.style.cssText = initPStyle;
                }
                if(item.childNodes.length>0) {
                    // Set the default style by traversing through the content of the child element where the IMG tag exists
                    item.childNodes.forEach(child= > {
                        if(child.localName == 'img') {
                            // Get the original image width and height
                            let width = child.width;
                            let height = child.height;
                            let ratio = width / height;
                            let setW = 600;
                            let setH = 0;  // Calculate the ratio
                            if(setW / setH ! = ratio) { setH = setW / ratio; }// Set inline styles for the img tag
                            child.setAttribute('width', setW);
                            child.setAttribute('height', setH);
                            child.style.cssText = "text-align: center"; }})}})}// Whether the menu is active (if not, this function can be left blank)
    tryChangeActive(){}}Copy the code

2. Create a new WangEditor component

Import the above wlayoutmenu.js file and write the following codeCopy the code
import E from 'wangeditor';
import { getToken } from "@/utils/auth";
import wLayoutMenu from "@/utils/wLayoutMenu";
export default {
    name: 'editor'.props: {
        content: {
            require: true.type: String.default: ' '}},data() {
        return {
            editor: null}},watch: {content: function (newVal,oldval) {
            console.log(newVal,oldval)
            this.editor.txt.html(newVal)
        }
    },
    mounted() {
        this.editor = new E(this.$refs.editor); Instantiate the rich text editor
        this.editor.config.height = 750 // Set the edit area height to 750px
        // Register menu
        this.editor.menus.extend('shortcutLayout', wLayoutMenu)
        // You can also configure menus to adjust the order of the menus. Refer to the documentation in the "Configure Menus" section
        this.editor.config.menus = this.editor.config.menus.concat('shortcutLayout')
        this.editor.config.zIndex = 500; // Set the level of the editor
        // Child to parent real-time input data
        this.editor.config.onchange = html= > {
            this.$emit('editorChange', html);
        };
        // Configure the Element UI message prompt
        this.editor.config.customAlert = (s, t) = > {
            switch (t) {
            case 'success':
                this.$message.success(s);
                break
            case 'info':
                this.$message.info(s);
                break
            case 'warning':
                this.$message.warning(s);
                break
            case 'error':
                this.$message.error(s)
                break
            default:
                this.$message.info(s);
                break}}// Configure the image uploading server interface
        this.editor.config.uploadImgServer = _this.getBaseApi()+"/api/site/file/upload";
        this.editor.config.uploadImgMaxSize = 10 * 1024 * 1024;
        this.editor.config.uploadImgMaxLength = 1;
        this.editor.config.uploadFileName = 'file' // The name attribute in formData
        this.editor.config.uploadImgHeaders = {
            Authorization: "Bearer " + getToken() // Set the request header
        }
        this.editor.config.uploadImgHooks = {
            // Image uploads and returns results, but is triggered when the image is inserted incorrectly
            fail: function (xhr, editor, result) {
                console.log('error',result)
            },
            success: function (xhr, editor, result) {
                // Upload the image and return the result
                console.log(result, 'success')
                debugger;
            },
            customInsert: function (insertImgFn, result) {
                // Upload the image and return the result, customize the event of inserting the image (instead of the editor automatically inserting the image!!)
                // insertImgFn is the function that inserts the image, editor is the editor object, and result is the result returned by the server
 
                // For example, if the image is uploaded successfully, the server returns {url:'.... ' '} to insert the image like this:
                const { code, msg, data } = result
                if (code == 200) {
                    var url = data.fileUrl;
                    insertImgFn(_this.getBaseApi()+ url)
                    // Result must be a JSON string!! Otherwise an error
                    setTimeout(() = > {
                        // The image is uploaded with a default style
                        let img = document.querySelector('.w-e-text-container img[src="'+_this.getBaseApi()+url+'"]);
                        let parentDom = img.parentNode;
                        let width = img.width;
                        let height = img.height;
                        let ratio = width / height;
                        let setW = 600;
                        let setH = 0;  // Calculate the ratio
                        if(setW / setH ! = ratio) { setH = setW / ratio; } img.setAttribute('width', setW);
                        img.setAttribute('height', setH);
                        parentDom.style.cssText = "text-align: center";
                    }, 100);
                } else {
                    _this.$message.warning(msg)
                }
            }
        }
        
        this.editor.create(); // Create a rich text editor
        this.editor.txt.html(this.content); // Initialize the default content
    },
    methods: {
        /** * empty the contents */
        clearContent() {
            this.editor.txt.clear(); }},beforeDestroy() {
        // Destroy the editor
        this.editor.destroy()
        this.editor = null}}Copy the code

Before typesetting, as shown below

After one-click typesetting, see the picture below