可编辑 div demo

先看视频

可编辑div 视频

然后是代码

<style lang='less' scoped>
.editable {
  display: block;
  width: 100%;
  height: 100%;
  overflow: auto;
  outline: none;
  -webkit-user-modify: read-write-plaintext-only;
}

.editable:empty:before {
  content: attr(placeholder);
  color: #a9abb2;
}

.editable:focus:before {
  content: none;
}

style>
<template>
  <div ref='editable' class='editable' contenteditable spellcheck='false' placeholder="Enter发送,Shift+Enter换行"
      @paste='inputPaste'/>
template>

<script>
import UploadRequest from "../../assets/upload.request";
import {getMinioUrl} from "../../assets/global.util";

export default {
  name: "S3DivInput",
  extends: {},
  mixins: [],
  components: {},
  emits: [],
  props: {},
  data() {
    return {
      uploadRequest: undefined,
      result: []
    }
  },
  mounted() {
    this.uploadRequest = new UploadRequest(this)
  },
  methods: {
    buildResult() {
      const nodes = this.$refs.editable.childNodes
      const result = []
      let index = -1;
      let nodeType = null;
      nodes.forEach(node => {
        if (node.nodeType === 1) { // 图片
          nodeType = node.nodeType;
          index += 1;
          result[index] = {msgType: 'img', content: node.getAttribute('data')}
        } else if (node.nodeType === 3) { // 文字
          if (nodeType !== (nodeType = node.nodeType)) index += 1;
          if (node.data) {
            if (!result[index]) {
              result[index] = {msgType: 'font', content: node.data}
            } else {
              result[index].content += node.data
            }
          }
        }
      })
      return result
    },
    inputPaste(e) {
      e.preventDefault();
      const clipboardData = e.clipboardData || window.clipboardData;
      const {items: [item]} = clipboardData;
      const {kind, type} = item;
      console.log(kind, type)
      if (kind === 'string') {
        let text = clipboardData.getData('text/plain');
        if (!text) return;
        let selection = window.getSelection();
        const range = selection.getRangeAt(0)
        let textNode = document.createTextNode(text);
        range.insertNode(textNode)
        range.collapse(true)
        range.setStart(textNode, text.length)
        console.log('change2....')
        this.buildResult();
      } else if (kind === 'file') {
        const file = item.getAsFile();
        const params = {
          file, filename: 'file',
          onSuccess: (res) => {
            let element;
            if (type.match(/^image\/*/)) {
              element = document.createElement('img');
              element.src = getMinioUrl(res.data.visitPath);
              element.setAttribute('data', res.data.visitPath)
              element.setAttribute('style', 'height: 20%;object-fit: contain;')
            } else if (type.match(/^video\/*/)) {
              console.log("视频处理,暂未支持")
            }
            if (element) {
              let selection = window.getSelection();
              const range = selection.getRangeAt(0)
              range.insertNode(element)
              range.collapse(true)
              range.setStartAfter(element)
              console.log('change1....')
              this.buildResult();
            }
          },
          onProgress: (percent) => {}
        };
        this.uploadRequest.upload(params)
      }
    },
  }
}
script>

你可能感兴趣的:(javascript,前端,vue.js)