zjxlicheng

项目背景:vue element
image

  1. 下载Kindeditor
npm i kindeditor

2.在项目的组件中封装components/kindeditor/index.vue
参考 官方文档 内置参数 也可根据项目要求进行定制化
下面代码对图片上传进行了定制 摒弃了自带的 弹窗的样式 直接现在文件的形式,把上传的文件 转化成base64进行存储 还可加一些校验!!!

<template>
  <div class="kindeditor">
    <textarea :id="id" name="content" v-model="outContent" placeholder="请输入"></textarea>
    <input
      @change="selectedFile"
      style="visibility: hidden;height:0;"
      type="file"
      name
      id="inputFile"
    />
  </div>
</template>
 
<script>
import \'kindeditor/kindeditor-all.js\'
import \'kindeditor/lang/zh-CN.js\'
import \'kindeditor/themes/default/default.css\'
 
export default {
  name: \'kindeditor\',
  data () {
    return {
      editor: null,
      outContent: this.content
    }
  },
  props: {
    content: {
      type: String,
      default: \'\'
    },
    id: {
      type: String,
      required: true
    },
    width: {
      type: String
    },
    height: {
      type: String
    },
    minWidth: {
      type: Number,
      default: 650
    },
    minHeight: {
      type: Number,
      default: 100
    },
    items: {
      type: Array,
      default: function () {
        return [
          \'source\', \'|\', \'undo\', \'redo\', \'|\', \'preview\', \'print\', \'template\', \'code\', \'cut\', \'copy\', \'paste\',
          \'plainpaste\', \'wordpaste\', \'|\', \'justifyleft\', \'justifycenter\', \'justifyright\',
          \'justifyfull\', \'insertorderedlist\', \'insertunorderedlist\', \'indent\', \'outdent\', \'subscript\',
          \'superscript\', \'clearhtml\', \'quickformat\', \'selectall\', \'|\', \'fullscreen\', \'/\',
          \'formatblock\', \'fontname\', \'fontsize\', \'|\', \'forecolor\', \'hilitecolor\', \'bold\',
          \'italic\', \'underline\', \'strikethrough\', \'lineheight\', \'removeformat\', \'|\', \'image\', \'multiimage\',
          \'flash\', \'media\', \'insertfile\', \'table\', \'hr\', \'emoticons\', \'baidumap\', \'pagebreak\',
          \'anchor\', \'link\', \'unlink\', \'|\', \'about\'
        ]
      }
    },
    noDisableItems: {
      type: Array,
      default: function () {
        return [\'source\', \'fullscreen\']
      }
    },
    filterMode: {
      type: Boolean,
      default: true
    },
    htmlTags: {
      type: Object,
      default: function () {
        return {
          font: [\'color\', \'size\', \'face\', \'.background-color\'],
          span: [\'style\'],
          div: [\'class\', \'align\', \'style\'],
          table: [\'class\', \'border\', \'cellspacing\', \'cellpadding\', \'width\', \'height\', \'align\', \'style\'],
          \'td,th\': [\'class\', \'align\', \'valign\', \'width\', \'height\', \'colspan\', \'rowspan\', \'bgcolor\', \'style\'],
          a: [\'class\', \'href\', \'target\', \'name\', \'style\'],
          embed: [\'src\', \'width\', \'height\', \'type\', \'loop\', \'autostart\', \'quality\',
            \'style\', \'align\', \'allowscriptaccess\', \'/\'],
          img: [\'src\', \'width\', \'height\', \'border\', \'alt\', \'title\', \'align\', \'style\', \'/\'],
          hr: [\'class\', \'/\'],
          br: [\'/\'],
          \'p,ol,ul,li,blockquote,h1,h2,h3,h4,h5,h6\': [\'align\', \'style\'],
          \'tbody,tr,strong,b,sub,sup,em,i,u,strike\': []
        }
      }
    },
    wellFormatMode: {
      type: Boolean,
      default: true
    },
    resizeType: {
      type: Number,
      default: 2
    },
    themeType: {
      type: String,
      default: \'default\'
    },
    langType: {
      type: String,
      default: \'zh-CN\'
    },
    designMode: {
      type: Boolean,
      default: true
    },
    fullscreenMode: {
      type: Boolean,
      default: false
    },
    basePath: {
      type: String
    },
    themesPath: {
      type: String
    },
    pluginsPath: {
      type: String,
      default: \'\'
    },
    langPath: {
      type: String
    },
    minChangeSize: {
      type: Number,
      default: 5
    },
    loadStyleMode: {
      type: Boolean,
      default: true
    },
    urlType: {
      type: String,
      default: \'\'
    },
    newlineTag: {
      type: String,
      default: \'p\'
    },
    pasteType: {
      type: Number,
      default: 2
    },
    dialogAlignType: {
      type: String,
      default: \'page\'
    },
    shadowMode: {
      type: Boolean,
      default: true
    },
    zIndex: {
      type: Number,
      default: 811213
    },
    useContextmenu: {
      type: Boolean,
      default: true
    },
    syncType: {
      type: String,
      default: \'form\'
    },
    indentChar: {
      type: String,
      default: \'\t\'
    },
    cssPath: {
      type: [ String, Array ]
    },
    cssData: {
      type: String
    },
    bodyClass: {
      type: String,
      default: \'ke-content\'
    },
    colorTable: {
      type: Array
    },
    afterCreate: {
      type: Function
    },
    afterChange: {
      type: Function
    },
    afterTab: {
      type: Function
    },
    afterFocus: {
      type: Function
    },
    afterBlur: {
      type: Function
    },
    afterUpload: {
      type: Function
    },
    uploadJson: {
      type: String
    },
    fileManagerJson: {
      type: Function
    },
    allowPreviewEmoticons: {
      type: Boolean,
      default: true
    },
    // 本地上传
    allowImageUpload: {
      type: Boolean,
      default: false
    },
    allowFlashUpload: {
      type: Boolean,
      default: false
    },
    allowMediaUpload: {
      type: Boolean,
      default: false
    },
    allowFileUpload: {
      type: Boolean,
      default: true
    },
    allowFileManager: {
      type: Boolean,
      default: false
    },
    fontSizeTable: {
      type: Array,
      default: function () {
        return [\'9px\', \'10px\', \'12px\', \'14px\', \'16px\', \'18px\', \'24px\', \'32px\']
      }
    },
    // 0 网络图片 1本地图片
    imageTabIndex: {
      type: Number,
      default: 0
    },
    formatUploadUrl: {
      type: Boolean,
      default: true
    },
    fullscreenShortcut: {
      type: Boolean,
      default: false
    },
    extraFileUploadParams: {
      type: Array,
      default: function () {
        return []
      }
    },
    filePostName: {
      type: String,
      default: \'imgFile\'
    },
    fillDescAfterUploadImage: {
      type: Boolean,
      default: false
    },
    afterSelectFile: {
      type: Function
    },
    pagebreakHtml: {
      type: String,
      default: \'<hr style=”page-break-after: always;” class=”ke-pagebreak” />\'
    },
    // 在线上传
    allowImageRemote: {
      type: Boolean,
      default: false
    },
    autoHeightMode: {
      type: Boolean,
      default: false
    },
    fixToolBar: {
      type: Boolean,
      default: false
    },
    tabIndex: {
      type: Number
    }
  },
  watch: {
    content (val) {
      this.editor && val !== this.outContent && this.editor.html(val)
    },
    outContent (val) {
      this.$emit(\'update:content\', val)
      this.$emit(\'on-content-change\', val)
    }
  },
  mounted () {
    var _this = this
    _this.editor = window.KindEditor.create(\'#\' + this.id, {
      width: _this.width,
      height: _this.height,
      minWidth: _this.minWidth,
      minHeight: _this.minHeight,
      items: _this.items,
      noDisableItems: _this.noDisableItems,
      filterMode: _this.filterMode,
      htmlTags: _this.htmlTags,
      wellFormatMode: _this.wellFormatMode,
      resizeType: _this.resizeType,
      themeType: _this.themeType,
      langType: _this.langType,
      designMode: _this.designMode,
      fullscreenMode: _this.fullscreenMode,
      basePath: _this.basePath,
      themesPath: _this.cssPath,
      pluginsPath: _this.pluginsPath,
      langPath: _this.langPath,
      minChangeSize: _this.minChangeSize,
      loadStyleMode: _this.loadStyleMode,
      urlType: _this.urlType,
      newlineTag: _this.newlineTag,
      pasteType: _this.pasteType,
      dialogAlignType: _this.dialogAlignType,
      shadowMode: _this.shadowMode,
      zIndex: _this.zIndex,
      useContextmenu: _this.useContextmenu,
      syncType: _this.syncType,
      indentChar: _this.indentChar,
      cssPath: _this.cssPath,
      cssData: _this.cssData,
      bodyClass: _this.bodyClass,
      colorTable: _this.colorTable,
      afterCreate: _this.afterCreate,
      afterChange: function () {
        _this.afterChange
        _this.outContent = this.html()
      },
      afterTab: _this.afterTab,
      afterFocus: _this.afterFocus,
      afterBlur: _this.afterBlur,
      afterUpload: _this.afterUpload,
      uploadJson: _this.uploadJson,
      fileManagerJson: _this.fileManagerJson,
      allowPreviewEmoticons: _this.allowPreviewEmoticons,
      allowImageUpload: _this.allowImageUpload,
      allowFlashUpload: _this.allowFlashUpload,
      allowMediaUpload: _this.allowMediaUpload,
      allowFileUpload: _this.allowFileUpload,
      allowFileManager: _this.allowFileManager,
      fontSizeTable: _this.fontSizeTable,
      imageTabIndex: _this.imageTabIndex,
      formatUploadUrl: _this.formatUploadUrl,
      fullscreenShortcut: _this.fullscreenShortcut,
      extraFileUploadParams: _this.extraFileUploadParams,
      filePostName: _this.filePostName,
      fillDescAfterUploadImage: _this.fillDescAfterUploadImage,
      afterSelectFile: _this.afterSelectFile,
      pagebreakHtml: _this.pagebreakHtml,
      allowImageRemote: _this.allowImageRemote,
      autoHeightMode: _this.autoHeightMode,
      fixToolBar: _this.fixToolBar,
      tabIndex: _this.tabIndex
    })
    // 添加点击图片回调函数
    _this.editor.clickToolbar("image", () => {
      // 禁用自带的图片弹窗
      this.editor.hideDialog();
      // 打开文件
      this.handleOpenFile();
    });
  },
  methods:{
    // 打开文件
    handleOpenFile() {
      let input = window.document.getElementById("inputFile");
      // 解决同一个文件不能监听的问题
      input.addEventListener(
        "click",
        function() {
          this.value = "";
        },
        false
      );
      // 点击input
      input.click();
    },
    // 图片上传
    async  selectedFile($event) {
      const file = $event.target.files[0];
      // console.log($event,file,this.file2Base64(file,res=>{console.log(res)}))
      this.file2Base64(file,res=>{
        this.$emit(\'base64Flie\',res)
      })
    },
    file2Base64(file, cb){
      let url = URL.createObjectURL(file);
      let reader = new FileReader();
      reader.onload = function (evt) {
        let base64 = evt.target.result;
        cb(base64);
      };
      reader.readAsDataURL(file);
    }
  }
}
</script>
  1. 对自定义的组件进行二次封装 views/components/kindeditor.vue
    通过自定义属性 对kindeditor组件进行样式上的自定义
    对组件返回的base64图片格式进行显示内容的拼接(注意直接修改prorps里text的值 是不生效的 父组件无法捕捉到值) 可参考文档
<template>
  <div id="app">
     <editor id="editor_id" :height="height" :width="width" :content.sync="text" :items="items"
            :afterChange="afterChange"
            @base64Flie="base64Flie"
            :loadStyleMode="false"
            @on-content-change="onContentChange"></editor>
    <!-- <div> editorTextCopy: {{ editorTextCopy }} </div> -->
 
  </div>
</template>
 
<script>
import editor from \'@/components/kindeditor/index.vue\'
 
export default {
  name: \'kindeditor\',
  components: {
    editor
  },
  props:{
    height: {
      type: String,
      default: \'500px\'
    },
    width: {
      type: String,
      default: \'700px\'
    },
    text: {
      type: String,
      default: \'\'
    },

  },
  data () {
    return {
      editorText: \'直接初始化值\', // 双向同步的变量
      editorTextCopy: \'\' , // content-change 事件回掉改变的对象
      items: [
          \'justifyleft\', \'justifycenter\', \'justifyright\',\'justifyfull\', \'insertorderedlist\', \'insertunorderedlist\', \'indent\', \'outdent\', \'subscript\',
          \'superscript\',  \'quickformat\', \'selectall\', 
          \'|\', \'fullscreen\',
          \'formatblock\', \'fontname\', \'fontsize\', 
          \'|\', \'image\', \'forecolor\', \'hilitecolor\', \'bold\',
          \'italic\', \'underline\', \'strikethrough\', \'lineheight\', \'removeformat\', 
        ]
    }
  },
    methods: {
    onContentChange (val) {
      this.editorTextCopy = val;
      // window.console.log(this.editorTextCopy)
      this.$emit(\'update:text\',this.editorTextCopy)
    },
    afterChange (e) {
      console.log(e)
    },
    base64Flie (base64) {
      this.text+=`<img src="${base64}" alt="">`
	  //注意
      this.$emit(\'update:text\',this.text)
    }
  }
}
</script>
  1. 在表单中使用 封装好的组件 kindeditor
<template>
  <div>
  <el-form ref="formData" :model="formData" label-width="100px" @submit.native.prevent>
  <el-row :gutter="3">
  <el-col :span="24">
  <el-form-item label="内容" prop="news_content" placeholder="内容" 
  :rules="[
  { required: true, message:\'请输入\'}
  ]">
  <kindeditor ref="news_content" :text.sync=\'formData.news_content\' :width="\'100%\'"/>
  </el-form-item>
  </el-col>
  </el-row>
  </el-form>
  </div>
</template>
<script>
import kindeditor from \'./kindeditor.vue\'
export default {
  props: {
    formData: {
      type: Object,
      default: () => {
        return {}
      }
    },
  },
  components:{
    kindeditor
  },
}

遇到的问题
1.打包上线 在点击上传图片时 会加载 refresh.png align_top.gif align_left.gif align_right.gif加载 错误的情况?
可通过修改pluginsPath的值
也可对 源码kindeditor-all.js 7221 7225 7226 7227进行注释 (在不影响需求的前提下 已解决问题优先)
碰到背景图片加载问题 修改打包文件目录

分类:

技术点:

相关文章:

  • 2022-12-23
  • 2021-06-16
  • 2022-12-23
  • 2021-12-09
  • 2021-11-20
  • 2021-10-10
猜你喜欢
  • 2022-12-23
  • 2021-06-22
  • 2021-11-27
  • 2022-12-23
  • 2021-12-28
  • 2022-12-23
  • 2021-07-31
相关资源
相似解决方案