专栏首页vue+elementvue项目使用 富文本 封装
原创

vue项目使用 富文本 封装

我又来了,今天给大家分享一个富文本框的封装,写后台管理也离不开富文本框,我就做了封装,供大家参考,

我用的富文本框是 wangedito 版本是3.1的,好了,话不多说,上代码

新建一个richText组件,把一下代码放进去

<template lang="html">  
  <div class="editor">  
    <div ref="toolbar" class="toolbar"></div>  
    <div ref="editor" class="text"></div>  
  </div>  
</template>  
  
<script>  
  import E from 'wangeditor'  
  import 'wangeditor/release/wangEditor.min.css'  
  export default {  
    name: 'editoritem',  
    data() {  
      return {  
        editor: null,  
        info_: null , 
      }  
    },  
    model: {   //v-model本质上是一个语法糖 这一步在父组件中可使用v-model
      prop: 'value',  
      event: 'change'  
    },  
    props: {  
      value: {  
        type: String,  
        default: ''  
      }, 
      disabled:{
        type: Boolean,  
        default: false  
      }
     
    },  
    watch: {  
      value: function(value) {  
      
        if(!value){      //这是为了解决输入时光标乱跳 并回显
          this.editor.txt.html(this.value);
        }
      },
      //value为编辑框输入的内容,这里我监听了一下值,当父组件调用得时候,如果给value赋值了,子组件将会显示父组件赋给的值  
    },  
    mounted() {  
      this.seteditor()  
      this.editor.txt.html(this.value)  
    },  
    methods: {  
      seteditor() {  
        this.editor = new E(this.$refs.toolbar, this.$refs.editor)  
        this.editor.customConfig.uploadImgShowBase64 = false // base 64 存储图片  
        this.editor.customConfig.uploadImgServer = ''// 填写配置服务器端地址  
        this.editor.customConfig.uploadImgHeaders = { }// 自定义 header  
        this.editor.customConfig.uploadFileName = 'file' // 后端接受上传文件的参数名  
        this.editor.customConfig.uploadImgParams = {  
            // 如果版本 <=v3.1.0 ,属性值会自动进行 encode ,此处无需 encode  
            // 如果版本 >=v3.1.1 ,属性值不会自动 encode ,如有需要自己手动 encode  
            file_type: 'img'  
        }  
        this.editor.customConfig.uploadImgMaxSize = 2 * 1024 * 1024 // 将图片大小限制为 2M  
        this.editor.customConfig.uploadImgMaxLength = 6 // 限制一次最多上传 6 张图片  
        this.editor.customConfig.uploadImgTimeout = 3 * 60 * 1000 // 设置超时时间  
        // 自定义 onchange 触发的延迟时间,默认为 200 ms  
        // this.editor.customConfig.onchangeTimeout = 1000 // 单位 ms  

        // 配置菜单  
        this.editor.customConfig.menus = [  
          'head', // 标题  
          'bold', // 粗体  
          'fontSize', // 字号  
          'fontName', // 字体  
          'italic', // 斜体  
          'underline', // 下划线  
          'strikeThrough', // 删除线  
          'foreColor', // 文字颜色  
          'backColor', // 背景颜色  
          'link', // 插入链接  
          'list', // 列表  
          'justify', // 对齐方式  
          'quote', // 引用  
          'emoticon', // 表情  
          'image', // 插入图片  
          'table', // 表格  
          'video', // 插入视频  
          'code', // 插入代码  
          'undo', // 撤销  
          'redo', // 重复  
          'fullscreen' // 全屏  
        ]  
  
        this.editor.customConfig.uploadImgHooks = {  
          fail: (xhr, editor, result) => {  
            // 插入图片失败回调  
          },  
          success: (xhr, editor, result) => {  
            // 图片上传成功回调  
          },  
          timeout: (xhr, editor) => {  
            // 网络超时的回调  
          },  
          error: (xhr, editor) => {  
            // 图片上传错误的回调  
          },  
          customInsert: (insertImg, result, editor) => {  
            // 图片上传成功,插入图片的回调  
            //result为上传图片成功的时候返回的数据,这里我打印了一下发现后台返回的是data:[{url:"路径的形式"},...]  
            // console.log(result.data[0].url)  
            //insertImg()为插入图片的函数  
             //循环插入图片  
            // for (let i = 0; i < 1; i++) {  
            if (result.code == 200) {  
                let url = result.data.image_url  
                JSON.stringify(url)  
                insertImg(url)  
            } else {  
                this.$Message.error(result.msg);  
            }  
            // }  
          }  
        }  
        this.editor.customConfig.onchange = (html) => {  
          this.info_ = html // 绑定当前逐渐地值  
          this.$emit('change', this.info_) // 将内容同步到父组件中  
        }  
        // 创建富文本编辑器  
        this.editor.create()  
      }  
    }  
  }  
</script>  
  
<style lang="scss" scoped>  
  .editor {  
    width: 80%;  
    // margin: 0 auto;  
    position: relative;  
    z-index: 0;  
  }  
  .toolbar {  
    border: 1px solid #ccc;  
  }  
  .text {  
    border: 1px solid #ccc;  
    min-height: 500px;  
  }  
</style>  

页面使用

<template>
    <div>
        <!-- 以上代码省略-->
        <richText v-model="ruleForm.tcontent"></richText>  
    </div>
</template>
<script>
import richText from '../../components/richText'  
export default {  
    components: { //注册组件
        richText,
    },  
    data () {
        return {
            dialogVisible:false,
            dialogVisible1:false,
            title:'',
            management:[],
            detailTitle:"",
            detailContent:"",
            type:'',
            form:{
                page:1,
                size:10
            },
            total:0,
            ruleForm: {
                ttitle: '',
                tcontent:''
            },
            rules: {
                ttitle: [
                    { required: true, message: '请输入标题', trigger: 'blur' },
                    { min: 1, max: 20, message: '长度在 3 到 5 个字符', trigger: 'blur' }
                ],
                tcontent: [
                    { required: true, message: '请输入内容', trigger: 'blur' },
                ],
            }
        }
    },
    created () { 
        this.managementAll()
    },
    methods: {
        async managementAll(){
            let {data:res}=await this.$http.post('affiche/findAll',this.form)
            console.log(res);
            if (res.code==200) {
                this.management=res.data.records
                this.total=res.data.total
            }
        },
        addTrator(){
            this.title="新增"
            this.type=1
            this.dialogVisible=true
        },
        handleClose(){
            this.dialogVisible=false
            this.ruleForm={}
        },
        handRedact(e){
            console.log(e);
            this.title="编辑"
            this.type=2
            this.dialogVisible=true
            this.detailPost(e)
        },
        handleClick(e){
            this.$confirm('是否删除此公告?', '提示', {
                    confirmButtonText: '确定',
                    cancelButtonText: '取消',
                }).then(async() => {
                    let {data:res}=await this.$http.post('affiche/del',{tid:e})
                        console.log(res);
                        if (res.code==200) {
                            this.$message({
                                duration:1200,
                                message:res.message,
                                type:'success'
                            })
                            this.managementAll()
                        }else{
                            this.$message({
                                duration:1200,
                                message:res.message,
                                type:'error'
                            })
                        }
                }).catch(() => {
                this.$message({
                     duration:1200,
                    type: 'info',
                    message: '已取消删除'
                });          
                });
           
        },
        async detailPost(e){
            let {data:res}=await this.$http.post('affiche/findById',{tid:e})
            console.log(res);
            if (res.code==200) {
                this.ruleForm=res.data
                this.detailContent=res.data.tcontent
                this.detailTitle=res.data.ttitle
            }
        },
        //详情按钮
        handleDetails(e){
            this.dialogVisible1=true
            this.detailPost(e)
        },
        submitForm(formName) {
            this.$refs[formName].validate(async(valid) => {
                if (valid) {
                   if (this.type=='1') {
                       console.log(this.ruleForm,"9999999999");
                        let {data:res}=await this.$http.post('affiche/add',this.ruleForm)
                        console.log(res);
                        if (res.code==200) {
                            this.dialogVisible=false
                            this.ruleForm={}
                            this.managementAll()
                        }else{
                            this.$message({
                                duration:1200,
                                message:res.message,
                                type:'error'
                            })
                        }
                   }else if(this.type=='2'){
                       console.log(this.ruleForm,"1111111");
                        let {data:res}=await this.$http.post('affiche/update',this.ruleForm)
                        console.log(res);
                        if (res.code==200) {
                            this.dialogVisible=false
                            this.ruleForm={}
                            this.managementAll()
                        }else{
                            this.$message({
                                duration:1200,
                                message:res.message,
                                type:'error'
                            })
                        }
                   }
                } else {
                    console.log('error submit!!');
                    return false;
                }
            });
        },
        resetForm(formName) {
            this.$refs[formName].resetFields();
        },
         //上一页下一页按钮
        currentChange(val) {
            this.form.page = val;
            this.managementAll();
        },
        //每页显示几条数据按钮
        sizeChange(val) {
            this.form.size = val;
            this.managementAll();
        },
       
    }
}
</script>

<style lang="scss" scoped>
.box-card{
    margin-top: 10px;
}
.el-table{
    margin-top: 10px;
}
.particulars{
    display: flex;
    flex-direction: column;
    .title{

    }
    .content{
        margin-top: 10px;
        display: flex;
        span:nth-child(1){
            display: inline-block;
            padding: 12px 0;
        }
        span:nth-child(2){
            display: inline-block;
        }
    }
}
</style>

如有不懂,请留言,写的不怎么好,其实富文本框有好多种,这只是其中一种,有大佬写的好的,还望指导。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • element ui 图片上传封装多张或单张

    最近写了一个后台管理项目,发现每个后台项目都离不开上传图片,决定把上传图片做个封装,话不多说直接上代码!

    前端小白@阿强
  • vue+element实现分页的封装

    前端小白@阿强
  • 浅谈前端响应式设计(一)

    现实世界有很多是以响应式的方式运作的,例如我们会在收到他人的提问,然后做出响应,给出相应的回答。在开发过程中我也应用了大量的响应式设计,积累了一些经验,希望能抛...

    有赞coder
  • 基础篇章:关于 React Native 之 Modal 组件的讲解

    (友情提示:RN学习,从最基础的开始,大家不要嫌弃太基础,会的同学请自行略过,希望不要耽误已经会的同学的宝贵时间) Modal是模态视图,它的作用是可以用来覆盖...

    非著名程序员
  • lottie系列文章(四):源码分析——svg渲染

    lottie为全局变量,主要有一个loadAnimation的方法,来加载和解析json,播放动画。

    IMWeb前端团队
  • .glb格式的模型怎么在three.js中展示

    3D软件中导出的格式一般有.obj 和.glb ,下面是blender 2.8.2 生成模型并在three.js中展示的流程

    tianyawhl
  • 云终端系列(一)—— 实时音视频Web端接入体验(Vue基础音视频通话篇)

    这个系列呢,主要给各位观众老爷看看目前有较大趋势的SaaS应用的SDK在各种主流Web终端的使用姿势和异常分析,如果想要纯粹了解开发的或者云原生,云开发的可以去...

    楚歌
  • threejs 场景切换 优化性能

    是实现2个场景的定时切换,由于是用在大屏系统,需要浏览器一直能正常运行,不能运行一段时间卡死

    tianyawhl
  • JavaScript this关键字

    Mirror王宇阳
  • 撩妹技能 get,教你用 canvas 画一场流星雨

    玩过 canvas 的同学,你画圆画方画线条这么 6,如果说叫你画下面这个玩意儿,你会不会觉得你用的是假 canvas?canvas 没有画一个带尾巴玩意儿的 ...

    王小婷

扫码关注云+社区

领取腾讯云代金券