微信小程序开发之富文本编辑器
发布于 3 年前 作者 xiaqiu 1070 次浏览 来自 分享

微信小程序开发之富文本编辑器

考研党,闲来无趣,忙里偷闲,团队在参加 ”中国大学生计算机大赛” 需要用到富文本编辑器。写文来给那些需要用到的人一个指示!如果您感觉很好用,很实用,也请大家给点一个赞!

前言:富文本在Web开发上的地位大家可想而知,很多地方都需要用到富文本编辑器,比如开发类似新闻管理小程序、商品简介等。微信小程序在基础库2.7.0之后上线了一个editor富文本编辑器组件,这个组件是本次要讲的内容。组件相关的内容大家可以去看官方文档的内容,这里我们就不进行讲解。而我们要做的就是将官方的富文本组件进行二次开发达到一个好用而又实用的地步:https://developers.weixin.qq.com/miniprogram/dev/component/editor.html

先看效果图(以下只是一个基础的实用):

代码方案:

1、在components中创建一个editor的组件,然后将以下wxml、wxss、js、json文件复制进去

JSON文件:

{
  "component"true,
  "usingComponents": {}
}

WXML文件:

<view class="editor-box">
  <view class="editor-box-header" wx:if="{{showTabBar}}">
    <view class="operate-box" data-uploadImageURL="{{uploadImageURL}}" bind:tap="_addImage">
      <text class="iconfont icon-image"></text>
    </view>
    <view class="operate-box" bind:tap="_addItalic">
      <text class="iconfont icon-italic"></text>
    </view>
    <view class="operate-box" bind:tap="_addBold">
      <text class="iconfont icon-bold"></text>
    </view>
    <view class="operate-box" data-header="h1" bind:tap="_addHeader">
      <text class="iconfont icon-h1"></text>
    </view>
    <view class="operate-box" data-header="h2" bind:tap="_addHeader">
      <text class="iconfont icon-h2"></text>
    </view>
    <view class="operate-box" data-header="h3" bind:tap="_addHeader">
      <text class="iconfont icon-h3"></text>
    </view>
    <view class="operate-box" data-align="left" bind:tap="_addAlign">
      <text class="iconfont icon-alignLeft"></text>
    </view>
    <view class="operate-box" data-align="right" bind:tap="_addAlign">
      <text class="iconfont icon-alignRight"></text>
    </view>
    <view class="operate-box" data-list="ordered" bind:tap="_addList">
      <text class="iconfont icon-orderedList"></text>
    </view>
    <view class="operate-box" data-list="bullet" bind:tap="_addList">
      <text class="iconfont icon-unorderedList"></text>
    </view>
    <view class="operate-box" bind:tap="_undo">
      <text class="iconfont icon-undo"></text>
    </view>
  </view>
  <view class="editor-box-content">
    <editor id="editor" name="{{name}}" placeholder="{{placeholder}}" bind:ready="_onEditorReady"
      bind:input="_onInputting" show-img-resize="{{true}}"></editor>
  </view>
</view>

WXSS文件

[@import](/user/import) "iconfont.wxss";

.editor-box {
  width100%;
  padding0;
  box-sizing: border-box;
  background-color#fff;
  border:2px solid #f6f6f6;
}

.editor-box-header,
.editor-box-content {
  width100%;
}

.editor-box-header {
  display: flex;
  flex-flow: row nowrap;
  align-items: center;
  justify-content:flex-start;
  padding20rpx 20rpx;
  box-sizing: border-box;
  border-bottom2rpx solid #f6f6f6;
  background-color#f6f6f6;
}

.editor-box-header>.operate-box {
  margin-right20rpx;
  width40rpx;
  height40rpx;
  overflow: hidden;
  color:gray;
}

.editor-box-content{
  padding:20rpx;
  box-sizing: border-box;
}

iconfont.WXSS文件:(注意上面import文件的位置,如果你有变动,请修改import后的 src)

[@font-face](/user/font-face) {
  font-family'iconfont';  /* Project id 2549449 */
  srcurl('//at.alicdn.com/t/font_2549449_hxmflg4qsr6.woff2?t=1621002720450'format('woff2'),
       url('//at.alicdn.com/t/font_2549449_hxmflg4qsr6.woff?t=1621002720450'format('woff'),
       url('//at.alicdn.com/t/font_2549449_hxmflg4qsr6.ttf?t=1621002720450'format('truetype');
}

.iconfont {
  font-family"iconfont" !important;
  font-size38rpx;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.icon-undo:before {
  content"\e609";
}

.icon-hr:before {
  content"\e60a";
}

.icon-h3:before {
  content"\e60b";
}

.icon-quote:before {
  content"\e60c";
}

.icon-bold:before {
  content"\e60e";
}

.icon-orderedList:before {
  content"\e612";
}

.icon-h2:before {
  content"\e61a";
}

.icon-italic:before {
  content"\e61c";
}

.icon-unorderedList:before {
  content"\e620";
}

.icon-alignLeft:before {
  content"\e621";
}

.icon-alignRight:before {
  content"\e622";
}

.icon-h1:before {
  content"\e623";
}

.icon-image:before {
  content"\e629";
}

JS文件:

/**
 * 未经允许,请不要擅自改动,如果使用,请在最后说明出处
 */

Component({
  /**
   * 组件的属性列表
   */
  properties: {
    /**是否显示工具栏 */
    showTabBar: {
      type'Boolean',
      valuetrue
    },
    placeholder: {
      type'String',
      value'请输入相关内容'
    },
    name: {
      type'String',
      value''
    },
    uploadImageURL: {
      type'String',
      value''
    }
  },

  /**
   * 组件的初始数据
   */
  data: {

  },

  /**
   * 组件的方法列表
   */
  methods: {
    _onEditorReadyfunction () {
      const that = this;
      that.createSelectorQuery().select('#editor').context(function (res{
        that.editorCtx = res.context
      }).exec()
    },
    //插入图片
    _addImagefunction (event{
      let _this = this;
      wx.chooseImage({
        count1,
        sizeType: ['compressed'],
        sourceType: ['album'],
        successfunction (res{
          wx.showLoading({
            title'上传中',
            masktrue
          });
          _this._uploadImage(res.tempFilePaths[0], event.currentTarget.dataset.uploadimageurl);
        }
      });
    },
    _uploadImagefunction (tempFilePath, uploadImageURL{
      let _this = this;
      wx.uploadFile({
        filePath: tempFilePath,
        name'image',
        url: uploadImageURL,
        successfunction (res{
          res = JSON.parse(res.data);
          wx.hideLoading({
            success() => {
              if (res.code === 200) {
                _this.editorCtx.insertImage({
                  src: res.data
                });
              } else {
                wx.showToast({
                  icon'error',
                  title'服务器错误,稍后重试!',
                  masktrue
                })
              }
            },
          });
        }
      });
    },
    //设置斜体
    _addItalicfunction () {
      this.editorCtx.format("italic")
    },
    //添加粗体样式
    _addBoldfunction () {
      this.editorCtx.format("bold")
    },
    //设置标题
    _addHeaderfunction (e{
      let headerType = e.currentTarget.dataset.header;
      this.editorCtx.format("header", headerType)
    },
    //设置文字的排列方式
    _addAlignfunction (e{
      let alignType = e.currentTarget.dataset.align;
      this.editorCtx.format("align", alignType);
    },
    //设置列表
    _addListfunction (e{
      let listType = e.currentTarget.dataset.list;
      console.log(listType)
      this.editorCtx.format("list", listType);
    },
    //撤销
    _undofunction () {
      this.editorCtx.undo();
    },
    //监控输入
    _onInputtingfunction (e{
      let html = e.detail.html;
      let text = e.detail.text;
      this.triggerEvent("input", { html: html, text: text }, {});
    }
  }
})

2、在你需要的使用的页面的JSON文件中引入该组件,引入方法(我创建的组件名称是“hg-editor”,你根据你的定义去修改,切勿乱用)

 "usingComponents": {
    "hg-editor":"../../../components/hg-editor/hg-editor"
  }

3、在wxml文件中使用,使用案例如下,可选参数有四个

  

参数详解:

__ __

  1. showTabBar :是否显示工具栏(默认为true,显示,如果改为false则为不显示)
  2. placeholder:文本框提示文字,默认为“请输入相关内容”
  3. name:是编辑器的name属性,默认为空
  4. uploadImageURL:图片的上传地址,默认为空

使用属性案例测试:

<hg-editor uploadImageURL="http://localhost:8080/uploadImage" class="hg-editor" name="referenceAnswer" placeholder="请输入参考范文"
showTabBar="{{true}}" bind:input="onInputtingDesc"></hg-editor>

bind:input可以获得用户输入的内容:

  onInputtingDesc: function (e{
    let html = e.detail.html;   //相关的html代码
    let originText = e.detail.text;  //text,不含有任何的html标签
    this.setData({
      ['topic.text']: html,
      ['topic.originText']: originText
    });
  }

使用案例:

您的想法有多大,组件拓展的无限可能就有多大,欢迎各位留言,欢迎各位使用!

如果好用,麻烦转载的时候带上原文标签,带上文章出初,最后写者不易,肯定各位点个赞!

(文章预告:使用递归调用,实现多级评论显示的功能)

1 回复

您好,这个组件如何回显内容

回到顶部