微信小程序富文本编辑器的纯原生实现(二)

来源:csdn博客 分类: 文章浏览史 发布时间:2020-09-01 11:53:50 最后更新:2020-09-01 浏览:459
转载声明:
本文为摘录自“csdn博客”,版权归原作者所有。
温馨提示:
为了更好的体验,请点击原文链接进行浏览
摘录时间:
2020-09-01 11:53:50


之前写了一个基于模版template的富文本,整体功能和逻辑便简单,因为项目重构,进行了升级,再分享一个基于组件的富文本,(demo在文末)

一、预期实现功能

  1. 实现富文本新增,包括图片和文字
  2. 实现富文本的编辑,能够将保存的富文本结构进行解析和展示
  3. 解决微信小程序输入框层级最高,展示不美观的问题

二、富文本结构

在这里插入图片描述
从上图可以看出来,为了处理小程序输入框原生组件层级最高,新增了一个失去焦点的文本框。

三、富文本数据结构

	[
		{
			info:"测试数据",
			type:0
		},
		{
			info:"图片url",
			type:1
		}
	]
	

四、实现逻辑

4.1 wxml代码
<view>
  <textarea wx:if="{{isEdit}}" class='input_view' maxlength='-1' auto-height='true' bindinput='_inputCon' value='{{firstCon}}' placeholder='写点什么...' focus='{{focusList[0].focus}}' bindblur="_outBlur" style='width:{{width-20}}px;' data-index='0' />
  <view wx:if="{{!isEdit}}" bindtap='_focusView' class='input_view2 text-gray' data-index='0'>{{firstCon||"写点什么..."}}</view>
  <view wx:for="{{dataList}}" wx:key="{{index}}">
    <view class='img_view' style='height:{{width/2}}px;'>
      <image src='{{item.img}}' mode='aspectFill' />
      <i bindtap='_deletedImg' data-index='{{index}}' class='iconfont aydk-icon-close text-error text-large close_img'></i>
    </view>
    <textarea wx:if="{{isEdit}}" class='input_view' maxlength='-1' auto-height='true' bindinput='_inputCon' value='{{item.info}}' placeholder='写点什么...' focus='{{focusList[index+1].focus}}' bindblur="_outBlur" style='width:{{width-20}}px;' data-index='{{index+1}}' />
    <view wx:if="{{!isEdit}}" bindtap='_focusView' class='input_view2 text-gray' data-index='{{index+1}}'>{{item.info||'写点什么...'}}</view>
  </view>
</view>
<view class='add-img'>
  <view class='circle_center_view img-s-4 bg-white hx-btn p-relative' bindtap='_addImg'>
      <i class='iconfont aydk-icon-add-img text-{{color}} text-gray text-large'></i>
  </view>
</view>
<view class='save'>
  <view class='circle_center_view img-s-4 bg-white hx-btn p-relative' bindtap='_saveRichText'>
      <i class='iconfont aydk-icon-save text-{{color}} text-gray text-large'></i>
  </view>
</view>
4.2 js代码
// components/rich_text/rich_text.js
var app = getApp();
Component({
  /**
   * 组件的属性列表
   */
  properties: {
    firstCon:{
      type:String,
      value:''
    },
    initlist:{ // 用于初始化数据,例如,编辑富文本
      type:Array,
      value:[]
    },
    save: {
      type: String,
      value:'save'
    },
    max_length:{ // 传入图片上限,默认为4
      type:Number,
      value:4
    }
  },
  options: { // 允许接受外部样式,根据个人喜好来处理
    addGlobalClass: true
  },
  /**
   * 组件的初始数据
   */
  data: {
    dataList:[],
    focusList:[{
      focus:true
    }],
    isEdit:true,
    addImgView:{},
    insertIndex:0,
    width:375
  },
  created(){
    let that = this;
    that.data.addImgView = that.selectComponent("#addimg");
  },
  attached() { // 当组件挂载到页面时,才会执行初始化
    let that = this;
    that.setData({
      width: app.globalData.systemInfo.windowWidth
    })
    that._initRichText();
  },
  /**
   * 组件的方法列表
   */
  methods: {
    /**
     * 内部方法
     * 初始化富文本方法
     */
    _initRichText(){
      let that = this;
      if (that.data.initlist && that.data.initlist.length>0){// 初始化数据不为空
        for (let i = 0; i < that.data.initlist.length;i++){
          if(i===0){
            if (that.data.initlist[i].type===0){
              that.data.firstCon = that.data.initlist[0].info; 
            }else{
              that.data.dataList.push({
                img: that.data.initlist[i].info,
                info: ''
              })
            }
          } else {
            if (that.data.initlist[i].type === 0) { // 文字
              that.data.dataList[that.data.dataList.length - 1].info = that.data.initlist[i].info;
            } else {
              that.data.dataList.push({
                img: that.data.initlist[i].info,
                info: ''
              })
            }
          }
        }
        that.setData({
          firstCon:that.data.firstCon,
          dataList:that.data.dataList
        })
      }
    },
    /**
     * 富文本文字输入监听
     */
    _inputCon(e){
      let that = this;
      let index = +e.currentTarget.dataset.index;
      if(index === 0){
        that.data.firstCon = e.detail.value;
      }else{
        that.data.dataList[index - 1].info = e.detail.value;
      }
    },
    /**
     * 文本框获取焦点监听
     */
    _focusView(e){
      let that = this;
      let index = +e.currentTarget.dataset.index;
      that.data.focusList = that.data.focusList.map(item => {
        item.focus = false;
        return item;
      });
      that.data.focusList[index].focus = true;
      that.setData({
        focusList: that.data.focusList,
        isEdit: true
      })
    },
    /**
     * 内部方法
     * 文本框失去焦点的监听事件
     * 存储失去焦点的文本框位置,为插入图片作准备
     */
    _outBlur(e){
      let that = this;
      that.data.insertIndex = +e.currentTarget.dataset.index;
      that.setData({
        firstCon:that.data.firstCon,
        dataList:that.data.dataList,
        isEdit: false
      })
    },
    /**
     * 内部方法
     * 调用添加图片事件监听
     * 此处没有做太多处理,下次添加一个上传图片的组件
     * demo存贮的是本地的临时链接,自己要自己处理哦
     */
    _addImg(){
      let that = this;
      if(that.data.dataList.length<that.data.max_length){
        wx.chooseImage({
          success: function(res) {
            that.data.dataList.splice(that.data.insertIndex, 0, {
              img: res.tempFilePaths[0],
              info: ''
            })
            that.data.focusList.splice(that.data.insertIndex + 1, 0, {
              focus: false
            })
            that.setData({
              dataList: that.data.dataList,
              focusList: that.data.focusList
            })
          },
        })
      }else{
        wx.showToast({
          title: '最多只能添加'+that.data.max_length+'张图片哦',
          mask:true,
          duration:1000
        })
      }
    },
    /**
     * 内部方法
     * 删除图片
     */
    _deletedImg(e){
      let that = this;
      let index = +e.currentTarget.dataset.index;
      if(that.data.dataList[index].info){
        if(index === 0){ // 最后一个
          that.data.firstCon = that.data.firstCon + that.data.dataList[index].info;
        }else{
          that.data.dataList[index - 1].info = that.data.dataList[index - 1].info + that.data.dataList[index].info;
        }
      }
      that.data.dataList.splice(index,1);
      that.setData({
        firstCon: that.data.firstCon,
        dataList: that.data.dataList
      })
    },
    /**
     * 暴露出来的方法
     * 返回 富文本数据list
     */
    _saveRichText(){
      console.log("保存");
      let that = this;
      let list = [];
      if(that.data.firstCon){
        list.push({
          info: that.data.firstCon,
          type: 0
        })
      }
      that.data.dataList.forEach(item => {
        if(item.img){
          list.push({
            info: item.img,
            type: 1
          })
        }
        if(item.info){
          list.push({
            info: item.info,
            type: 0
          })
        }
      })
      that.triggerEvent('getDataList', list);
    }
  }
})

较之前的代码,增加了富文本编辑器获取焦点和失去焦点的逻辑,来控制文本输入框的显示和隐藏,基本解决了原生组件层级太高的问题

最后放上体验小程序二维码
在这里插入图片描述
小程序交流群人数到了上线,只能邀请入群了,进群的话,加我微信吧
在这里插入图片描述
最后附上完整代码
完整demo

php技术微信