可编辑div,文本编辑器

本文介绍了如何使用Vue和CSS创建一个可编辑的div,通过设置`contenteditable`属性实现div的可输入功能。同时,讨论了在编辑器中添加提示文字的方法,并探讨了表情资源和CSS的运用。还详细讲解了插入表情的操作,包括对node节点、光标对象以及range和selection对象的理解和应用,提供了相应的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.可输入div , contenteditable属性

div.inp(id=“textbox”, contenteditable, :placeholder=“placeholder”)

2.提示文字

.inp:empty:before {
content: attr(placeholder);
display: block;
color: #a9a9a9;
}

3.表情资源及css

4.插入表情
node节点的操作,光标对象,内部属性
range对象:文档的连续范围区域,如鼠标拖动选中的区域,range里的属性可以操作光标,做索引,未知的定位,输出等
selection对象:拖蓝

废话不多说,上代码

<template lang="pug">
  div
    div 文字编辑器
    div.tarea-box
      div.text-box
        div.inp-box
          div.inp(id="textbox", contenteditable, ref="textbox", :placeholder="placeholder",     @blur="saveFocus", @keyup="hang")
        div.bottom-face
          img.faceImage(:src="faceImage", @click="handleChoose")
          span.count  还可以输入{{textCount}}字
        div.expression(v-if="showFace")
          div.exp_bd
            div.exp_cont(:class="showFace? 'active':''")
              div.qq_face()
                a.face(@click="chooseQqFace('face', value, key, index)", v-for='(value, key, index) in QQFaceMap.data', v-show="index < 105", type="qq", :title="key",  :class="'qqFace'+ `${index}`") {{key}}
              div.emoji_face()
                a.face(@click="chooseQqFace('emoji', value, key, index)", v-for='(value, key, index) in EmojiFaceMap.data',  :title="key", type="emoji",  :class="'emoji'+ `${value}`") {{value}}
    div
      el-button(type="primary", @click="submit") 提交
</template>
<script>
import face from '@/assets/face.jpg'
import { QQFaceMap, EmojiFaceMap, EmojiMap, faceValueMap } from '@/util/faceMap'
export default {
  components: {},
  data () {
    return {
      textCount: 1000,
      QQFaceMap: QQFaceMap,
      EmojiFaceMap: EmojiFaceMap,
      faceValueMap: faceValueMap,
      EmojiMap: EmojiMap,
      placeholder: '请输入...',
      showFace: false,
      faceImage: face
    }
  },
  methods: {
    choseFace () {
      this.showFace = false
    },
    handleChoose () {
      this.showFace = !this.showFace
    },
    hang: (e) => {
      this.textCount = 1000 - document.getElementById('textbox').innerText.length
    },
    saveFocus () {
      this.saveRange()
    },
    saveRange () { // 保存光标位置
      var selection = window.getSelection ? window.getSelection() : document.selection
      if (!selection.rangeCount) {
        return
      }
      var range = selection.createRange ? selection.createRange() : selection.getRangeAt(0)
      window._range = range
    },
    insertHtmlAtCaret (html) { // 插入内容
      var sel
      var range = window._range
      if (window.getSelection) {
        sel = window.getSelection()
        if (sel.getRangeAt && sel.rangeCount) {
          var el = document.createElement('div')
          el.innerHTML = html
          var flag = document.createDocumentFragment()
          var node, lastNode
          while ((node = el.firstChild)) {
            lastNode = flag.appendChild(node)
          }
          range.insertNode(flag)
          if (lastNode) {
            range = range.cloneRange()
            range.setStartAfter(lastNode)
            range.collapse(true)
            sel.removeAllRanges()
            sel.addRange(range)
          }
        }
      }
    },
    chooseQqFace (type, value, key, index) { // 选择表情
      this.showFace = false
      var html
      if (type === 'face') {
        html = `<img src="http://www.u-qun.com/images/face-v2/spacer.gif" class="qqemoji qqemoji${index}" :data_name="[${key}]" />`
      } else {
        for (let ObjKey in this.EmojiMap.data) {
          if (key === ObjKey) {
            this.ObjKey = this.EmojiMap.data[key]
          }
        }
        if (this.ObjKey === '112' || this.ObjKey === '111' || this.ObjKey === '110' || this.ObjKey === '109' || this.ObjKey === '108' || this.ObjKey === '107' || this.ObjKey === '106' || this.ObjKey === '105') {
          html = `<img src="http://www.u-qun.com/images/face-v2/spacer.gif" class="qqemoji qqemoji${this.ObjKey}" :data_name="[${key}]" />`
        } else {
          for (let faceKey in this.faceValueMap) {
            if (this.ObjKey === faceKey) {
              this.faceKey = this.faceValueMap[faceKey]
            }
          }
          html = `<img src="http://www.u-qun.com/images/face-v2/spacer.gif" class="emoji emoji${this.ObjKey}" :data_name="${this.faceKey}" />`
        }
      }
      document.getElementById('textbox').focus()
      this.insertHtmlAtCaret(html)
    },
    submit () { // 提交处理数据
      var ele = document.getElementById('textbox').childNodes
      let aa = ''
      for (let i = 0; i < ele.length; i++) {
        if (ele[i].textContent) {
          aa += ele[i].textContent
        } else if (ele[i].nodeName === 'BR') {
          aa += `\n`
        } else if (ele[i].nodeName === 'IMG') {
          aa += ele[i].attributes[2].value
        }
      }
      console.log(aa)
    }
  }
}
</script>
<style lang="scss">
  @import 'src/assets/scss/expression';
  .tarea-box {
    width: 348.3px;
    height: 350px;
  }
 .text-box {
   border: solid 1px #ccc;
   color: #727171;
   position: relative;
   .inp-box {
     padding: 10px;
   }
   .inp {
     width: 100%;
     height: 285px;
     outline: none;
     overflow: scroll;
     display: inline-block;
   }
   .inp:empty:before {
     content: attr(placeholder);
     display: block;
     color: #a9a9a9;
   }
   .bottom-face {
     height: 40px;
     padding: 0 10px;
     line-height: 40px;
     position: relative;
     border-top: solid 1px #ccc;
     .faceImage {
       width: 22px;
       height: 16px;
     }
     .count {
       margin-left: 160px;
     }
   }
 }
</style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值