文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

vue中wangEditor5编辑器如何使用

2023-07-05 18:58

关注

这篇文章主要介绍了vue中wangEditor5编辑器如何使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇vue中wangEditor5编辑器如何使用文章都会有所收获,下面我们一起来看看吧。

一、wangEditor5是什么

wangEditor是一款富文本编译器插件,其他的我就不再过多赘述,因为官网上有一大截对于这个编译器的介绍,但我摸索使用的这两天里给我的最直观的感受就是,它是由中国开发者开发,所有的文档都是中文的,这一点上对我这个菜鸡来说非常友好,不用再去逐字逐句翻译,然后去读那些蹩脚的机翻中文。而且功能很丰富,能够满足很多需求,wangEditor5提供很多版本的代码,vue2,vue3,react都支持。

二、wangEditor5基本使用

(一)、安装

yarn add @wangeditor/editor-for-vue# 或者 npm install @wangeditor/editor-for-vue --save

(二)、编译器引入

import { Editor, Toolbar } from '@wangeditor/editor-for-vue';

Editor:引入@wangEditor编译器 

Toolbar:引入菜单栏

(三)、css及变量引入

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

这里需要注意,引入的样式写在带有scoped标签的style内无效。只能引入在全局样式里,但可能会造成样式覆盖,一般会有个清除样式的文件,会把里面的样式覆盖掉。

三、wangEditor5工具栏配置

工具栏配置有很多选项,这里以官方为主,我只做一些常用的配置介绍。

(一)、editor.getAllMenuKeys() 

查询编辑器注册的所有菜单 key (可能有的不在工具栏上)这里注意要在

    onCreated(editor) {            this.editor = Object.seal(editor)         },

这个函数中去调用 (这个函数是基本配置之一),不然好像调不出来,当然也有可能是博主太菜。

(二)、toolbarConfig中的excludeKeys

toolbarConfig: {        excludeKeys:["uploadVideo","fullScreen","emotion","insertTable"]       },

这个是菜单栏配置的一种:排除某项配置 ,这里填写的key值就是用上面那个方法,查出来的key值。

四、wangEditor5上传图片

首先在data中return以下信息。

editorConfig: {         placeholder: '请输入内容...' ,        MENU_CONF: {uploadImage: {customUpload: this.uploadImg,},}      },

然后书写this.uploadImg函数。

 uploadImg(file, insertFn){      let imgData = new FormData();imgData.append('file', file);      axios({        url: this.uploadConfig.api,        method: 'post',        data: imgData,      }).then((response) => {       insertFn(response.data.FileURL);      });    },

注意,这里因为返回的数据结构与@wangeditor要求的不一致,因此要使用 insertFn 函数 去包裹返回的url地址。

五、wangEditor5的一些问题收集及解决

(一)、引入@wangEditor 编译报错 " Module parse failed: Unexpected token (12828:18)You may need an appropriate loader to handle this file type."

vue中wangEditor5编辑器如何使用

解决方法:在 wwebpack.base.conf.js 文件的module>rules>.js 的include下加入

resolve('node_modules/@wangeditor')

 就可以了。

vue中wangEditor5编辑器如何使用

(二)、@wangeditor有序列表无序列表的样式消失问题。

大概率是全局样式清除导致的样式消失,可以去调试工具里看一看,样式覆盖的问题。

然后在style里deep一下改变样式就行了。

.editorStyle{  /deep/ .w-e-text-container>.w-e-scroll>div ol li{    list-style: auto ;  }  /deep/ .w-e-text-container>.w-e-scroll>div ul li{    list-style: disc ;  }  /deep/ .w-e-text-placeholder{    top:7px;  }  }

六、完整代码

<template>  <div v-loading="Loading" class="app_detail">    <el-form ref="form" :rules="rules" :model="appDetail" label-width="80px">      <el-form-item prop="name" label="应用名称">        <el-input v-model="appDetail.name" ></el-input>      </el-form-item>      <el-form-item label="分类">        <el-select          v-model="appDetail.appClassificationID"                    placeholder="选择应用分类"        >          <template v-for="item in classes">            <el-option              v-if="item.parentAppClassificationID"              :key="item.appClassificationID"              :label="item.appClassificationName"              :value="item.appClassificationID"            ></el-option>          </template>        </el-select>        <div class="inputdesc">为了适应前台展示,应用只能属于二级分类</div>      </el-form-item>      <el-form-item label="所属组织">        <el-select          v-model="appDetail.orgID"          placeholder="请选择所属组织"                  >          <el-option            v-for="item in myorgs"            :key="item.orgID"            :label="item.name"            :value="item.orgID"          ></el-option>        </el-select>      </el-form-item>      <el-form-item prop="tags" label="标签">        <el-select          v-model="appDetail.tags"          multiple          filterable                    placeholder="请输入或选择应用标签"        >          <el-option            v-for="item in existTags"            :key="item"            :label="item"            :value="item"          ></el-option>        </el-select>      </el-form-item>      <el-row>        <el-col :span="8" class="appsFrom">          <el-form-item            label="应用Logo"            ref="uploadpic"            class="el-form-item-cen"            prop="logo"          >            <el-upload              class="avatar-uploader"              :action="uploadConfig.api"              :with-credentials="true"              :headers="uploadConfig.headers"              :show-file-list="false"              :on-success="handleAvatarSuccess"              :on-error="handleAvatarError"              :before-upload="beforeAvatarUpload"            >              <img v-if="appDetail.logo" :src="appDetail.logo" class="avatar" />              <i v-else class="el-icon-plus avatar-uploader-icon"></i>              <i                v-if="appDetail.logo"                class="el-icon-delete"                @click.stop="() => handleRemove()"              ></i>            </el-upload>            <span >              建议上传 100*100 比例的Logo            </span>          </el-form-item>        </el-col>      </el-row>      <el-form-item prop="desc" label="应用简介">        <el-input          type="textarea"          v-model="appDetail.desc"          :rows="3"                  ></el-input>      </el-form-item>      <el-form-item prop="introduction" label="应用详情">        <div >        <Toolbar                        :editor="editor"            :defaultConfig="toolbarConfig"            :mode="mode"            class="barStyle"        />        <Editor                        v-model="appDetail.introduction"            :defaultConfig="editorConfig"            :mode="mode"            @onCreated="onCreated"            class="editorStyle"        />    </div>      </el-form-item>    </el-form>    <el-button      class="save_btn"      type="primary"      @click="onSubmit"      :loading="commitLoading"      >保存</el-button    >  </div></template> <script>import { updateApp } from '@/api/app';import { getStoreAvailableTags } from '@/api/appStore';import { getToken } from '@/utils/auth';import axios from 'axios';import { errorHandle } from '../../../../utils/error';import { Editor, Toolbar } from '@wangeditor/editor-for-vue';import { IToolbarConfig, DomEditor, IEditorConfig } from '@wangeditor/editor'export default {  name: 'BasicInfo',  components: { Editor, Toolbar },  props: {    appDetail: {      type: Object    },    marketID: {      type: String    },    Loading: Boolean  },  data() {    var baseDomain = process.env.BASE_API;    if (baseDomain == '/') {      baseDomain = window.location.origin;    }    const isChinese = (temp) => {      return /^[\u4e00-\u9fa5]+$/i.test(temp);    };    const tagValidate = (rule, value, callback) => {      let checked = true;      value.map((tag) => {        if (tag.length < 2) {          callback('每个标签至少两个字符');          checked = false;          return;        }        if (isChinese(tag) && tag.length > 5) {          callback('中文标签字数应处于2-5个之间');          checked = false;          return;        }        if (Number(tag) > 0) {          callback('标签不能为纯数字组成');          checked = false;          return;        }      });      if (checked) {        callback();      }    };    return {      editor: null,      toolbarConfig: {        excludeKeys:["uploadVideo","fullScreen","emotion","insertTable"]       },      editorConfig: {         placeholder: '请输入内容...' ,        MENU_CONF: {uploadImage: {customUpload: this.uploadImg,},}      },      mode: 'default', // or 'simple'      commitLoading: false,      classes: [],      existTags: [],      appPublishTypes: [        {          value: 'public',          label: '免费公开'        },        {          value: 'integral',          label: '金额销售'        },        {          value: 'private',          label: '私有'        },        {          value: 'show',          label: '展览'        }      ],      uploadConfig: {        api: `${baseDomain}/app-server/uploads/picture`,        headers: {          Authorization: getToken()        },      },      editorOption: {},      rules: {        name: [          { required: true, message: '应用名称不能为空', trigger: 'blur' },          { min: 2, message: '至少两个字符', trigger: 'blur' },          { max: 24, message: '应用名称建议不超过24个字符', trigger: 'blur' }        ],        desc: [          { required: true, message: '应用简介不能为空', trigger: 'blur' },          { min: 10, message: '至少10个字符', trigger: 'blur' },          { max: 82, message: '描述最多82个字符', trigger: 'blur' }        ],        introduction: [          { max: 10140, message: '描述最多10240个字符', trigger: 'blur' }        ],        tags: [{ validator: tagValidate, trigger: 'change' }]      }    };  },  created() {    this.fetchStoreAppClassList();    this.fetchStoreAppTags();  },  computed: {    myorgs() {      return this.$store.state.user.userOrgs;    }  },    methods: {    uploadImg(file, insertFn){      let imgData = new FormData();imgData.append('file', file);      axios({        url: this.uploadConfig.api,        method: 'post',        data: imgData,      }).then((response) => {       insertFn(response.data.FileURL);      });    },    onCreated(editor) {            this.editor = Object.seal(editor)         },    fetchStoreAppTags() {      getStoreAvailableTags({        marketID: this.marketID,        size: -1      })        .then((res) => {          if (res && res.tags) {            const tags = [];            res.tags.map((item) => {              tags.push(item.name);            });            this.existTags = tags;          }        })        .catch((err) => {          this.Loading = false;        });    },    fetchStoreAppClassList() {      this.$store        .dispatch('GetStoreAppClassificationList', {          marketID: this.marketID,          disableTree: true        })        .then((res) => {          if (res) {            this.classes = res;          }        })        .catch(() => {});    },    fetchUserOrgs() {      this.$store        .dispatch('GetUserOrgList')        .then((res) => {          if (res) {            this.myorgs = res;          }        })        .catch(() => {});    },    markdownContentUpdate(md, render) {      this.appData.introduction_html = render;    },    markdownImgAdd(pos, $file) {      // 第一步.将图片上传到服务器.      var formdata = new FormData();      formdata.append('file', $file);      axios({        url: this.api,        method: 'post',        data: formdata,        headers: this.Token      }).then((re) => {        if (re && re.data && re.data.data) {          this.$refs.md.$img2Url(pos, re.data.data);        }      });    },    handleAvatarSuccess(res, file) {      this.appDetail.logo = res.FileURL;    },    handleAvatarError(re) {      if (re.code == 10024) {        this.$message.warning(          '上传图片类型不支持,请上传以.png .jpg .jpeg 结尾的图片'        );        return;      }      this.$message.warning('上传失败!');    },    beforeAvatarUpload(file) {      const isJPG = file.type === 'image/jpeg';      const isPng = file.type === 'image/png';      const isLt2M = file.size / 1024 / 1024 < 2;       if (!isJPG && !isPng) {        this.$message.warning('上传Logo图片只能是JPG、PNG格式!');      }      if (!isLt2M) {        this.$message.warning('上传头像图片大小不能超过 2MB!');      }      return (isJPG || isPng) && isLt2M;    },    handleRemove() {      this.$confirm('是否删除logo', '提示', {        confirmButtonText: '确定',        cancelButtonText: '取消',        type: 'warning'      }).then(() => {        this.appDetail.logo = '';      });    },    handlePictureCardPreview(file) {      this.dialogImageUrl = file.url;      this.dialogVisible = true;    },    changeSelectApp_type_id(value) {      this.appData.app_type_id = value;      this.$forceUpdate();    },    changeSelectPublish_type(value) {      this.appData.publish_type = value;      this.$forceUpdate();    },    onSubmit() {      this.$refs.form.validate((valid) => {        if (valid) {          this.commitLoading = true;          this.$confirm('是否提交数据', '提示', {            confirmButtonText: '确定',            cancelButtonText: '取消',            type: 'warning'          })            .then(() => {              updateApp(this.appDetail)                .then((res) => {                  this.$message.success('应用信息更新成功');                  this.commitLoading = false;                })                .catch((err) => {                  errorHandle(err);                  this.commitLoading = false;                });            })            .catch(() => {              this.commitLoading = false;            });        } else {          return false;        }      });    }  }};</script><style lang="scss" scoped >.app_detail {  position: relative;  padding-bottom: 20px;  .save_btn {    margin-left: 80px;      }  .el-select {    width: 100%;  }}.editorStyle{  /deep/ .w-e-text-container>.w-e-scroll>div ol li{    list-style: auto ;  }  /deep/ .w-e-text-container>.w-e-scroll>div ul li{    list-style: disc ;  }  /deep/ .w-e-text-placeholder{    top:7px;  }  }.barStyle{  /deep/ .w-e-bar-item{    padding:2.5px  }    /deep/ .w-e-bar-item > button >.title{    border-left:0 !important;  }}</style><style src="@wangeditor/editor/dist/css/style.css" >.inputdesc {  font-size: 12px;  color: rgba(0, 0, 0, 0.45);  transition: color 0.3s cubic-bezier(0.215, 0.61, 0.355, 1);}.app_detail img {  width: auto;}.app_detail .ql-formats {  line-height: 22px;}</style>

关于“vue中wangEditor5编辑器如何使用”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“vue中wangEditor5编辑器如何使用”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯