挺好用的可编辑div组件(二)

前言

上一篇封装了可编辑div组件–挺好用的可编辑div组件(一),这一篇将讲解应用可编辑div的注意事项。

环境

  • vue2.5
  • webpack3.6
  • element-ui2.4.6

事件和快捷键

下面代码中添加了inputblurfocus事件和键盘快捷键,可以实时的监听 checkHtml 的改变。

<!--HelloWorld.vue-->
<template>
  <div class="content">
    <div>
      <button @click="onChangeVal">改变可编辑div的值</button>
      <base-edit-div
      	ref="editDiv"
        class="beautiful"
        :text="checkHtml"
        v-model="checkHtml"
        @input="changeText"
        @blur="onBlur"
        @focus="onFocus"
        @keydownTab="onKeydownTab"
      >
      </base-edit-div>
    </div>
    <el-popover
      ref="popover"
      placement="top-start"
      trigger="manual"
      width="200"
      v-model="visible">
      <el-button type="info" size="mini" stle="margin-left:0;" @click="onAddNoise">[噪音]</el-button>
    </el-popover>
  </div>
</template>

<script>
import BaseEditDiv from './BaseEditDiv'
const NOISE = '<b style="color:red;font-weight:normal" contenteditable="false">[噪音]</b>\r'
export default {
  components: {
    BaseEditDiv
  },
  data () {
    return {
      checkHtml: '<b style="color:red;font-weight:normal" contenteditable="false">[噪音]</b>\r',
      visible: false
    }
  },
  methods: {
    onChangeVal () {
      this.checkHtml = '<b style="color:red;font-weight:normal" contenteditable="false">[噪音]</b>\r改变值'
    },
    onAddNoise () {
      this.insertHtmlAtCaret(NOISE)
    },
    onKeydownTab (e) {
      console.log('tab快捷点', e)
    },
    onFocus (e) {
      this.visible = true
      const target = e.target
      let left = target.offsetLeft + 70
      let top = target.offsetTop - 50
      this.$refs.popover.$el.querySelector('.el-popper').style.cssText = `left:${left}px;top:${top}px`
      console.log('获取焦点', e)
    },
    onBlur (e) {
      this.visible = false
      console.log('失去焦点', e)
    },
    changeText (innerHTML, index) {
      console.log('input事件', innerHTML)
    },
    insertHtmlAtCaret (html) {
      let sel, range
      if (window.getSelection) {
        sel = window.getSelection()
        if (sel.getRangeAt && sel.rangeCount) {
          range = sel.getRangeAt(0)
          range.deleteContents()
          let el = document.createElement('div')
          el.innerHTML = html
          let frag = document.createDocumentFragment()
          let node
          let lastNode
          while ((node = el.firstChild)) {
            lastNode = frag.appendChild(node)
          }
          range.insertNode(frag)
          if (lastNode) {
            range = range.cloneRange()
            range.setStartAfter(lastNode)
            range.collapse(true)
            sel.removeAllRanges()
            sel.addRange(range)
          }
        }
      } else if (document.selection && document.selection.type !== 'Control') {
        // IE < 9
        document.selection.createRange().pasteHTML(html)
      }
    }
  }
}
</script>

<style lang="less" scoped>
  .content{
    margin: 50px auto;
    .beautiful{
      width: 300px;
      box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
      border-radius: 4px;
      border: 1px solid #ebeef5;
      background-color: #fff;
      overflow: hidden;
      color: #303133;
      transition: .3s;
    }
  }
</style>

效果如下:
在这里插入图片描述
checkHtml 的值都是我们手动输入改变的,那么如果我需要点击按钮后才改变 checkHtml 的值呢?通过操作,点击 改变可编辑div的值 按钮,依然没有变化。有两种解决办法:

  1. 操作可编辑div的innerHTML
onChangeVal () {
	this.$refs.editDiv.$el.innerHTML =  '<b style="color:red;font-weight:normal" contenteditable="false">[噪音]</b>\r改变值'
}

操作可编辑div组件的innerHTML会触发input事件,进而将改变了可编辑div组件的value值,并且v-model绑定的可编辑div组件正是获取的value值,故能实现改变可编辑div组件的值。

  1. 使用v-if
 <base-edit-div
   v-if="!loading"
   ref="editDiv"
   class="beautiful"
   :text="checkHtml"
   v-model="checkHtml"
   @input="changeText"
   @blur="onBlur"
   @focus="onFocus"
   @keydownTab="onKeydownTab"
 >
 </base-edit-div>
 data () {
    return {
      checkHtml: '<b style="color:red;font-weight:normal" contenteditable="false">[噪音]</b>\r',
      visible: false,
      loading: false
    }
  },
  methods: {
    onChangeVal () {
      // 方式一:操作可编辑div的innerHTML
      // this.$refs.editDiv.$el.innerHTML = '<b style="color:red;font-weight:normal" contenteditable="false">[噪音]</b>\r改变值'
      // 方式二:使用v-if
      this.loading = true
      this.checkHtml = '<b style="color:red;font-weight:normal" contenteditable="false">[噪音]</b>\r改变值'
      setTimeout(() => {
        this.loading = false
      }, 0)
    }
  }
}

在这里插入图片描述
最后的代码如下:

<!-- HelloWorld.vue -->
<template>
  <div class="content">
    <div>
      <button @click="onChangeVal">改变可编辑div的值</button>
      <base-edit-div
        v-if="!loading"
        ref="editDiv"
        class="beautiful"
        :text="checkHtml"
        v-model="checkHtml"
        @input="changeText"
        @blur="onBlur"
        @focus="onFocus"
        @keydownTab="onKeydownTab"
      >
      </base-edit-div>
    </div>
    <el-popover
      ref="popover"
      placement="top-start"
      trigger="manual"
      width="200"
      v-model="visible">
      <el-button type="info" size="mini" stle="margin-left:0;" @click="onAddNoise">[噪音]</el-button>
    </el-popover>
  </div>
</template>

<script>
import BaseEditDiv from './BaseEditDiv'
const NOISE = '<b style="color:red;font-weight:normal" contenteditable="false">[噪音]</b>\r'
export default {
  components: {
    BaseEditDiv
  },
  data () {
    return {
      checkHtml: '<b style="color:red;font-weight:normal" contenteditable="false">[噪音]</b>\r',
      visible: false,
      loading: false
    }
  },
  methods: {
    onChangeVal () {
      // 方式一:操作可编辑div的innerHTML
      // this.$refs.editDiv.$el.innerHTML = '<b style="color:red;font-weight:normal" contenteditable="false">[噪音]</b>\r改变值'
      // 方式二:使用v-if
      this.loading = true
      this.checkHtml = '<b style="color:red;font-weight:normal" contenteditable="false">[噪音]</b>\r改变值'
      setTimeout(() => {
        this.loading = false
      }, 0)
    },
    onAddNoise () {
      this.insertHtmlAtCaret(NOISE)
    },
    onKeydownTab (e) {
      console.log('tab快捷点', e)
    },
    onFocus (e) {
      this.visible = true
      const target = e.target
      let left = target.offsetLeft + 70
      let top = target.offsetTop - 50
      this.$refs.popover.$el.querySelector('.el-popper').style.cssText = `left:${left}px;top:${top}px`
      console.log('获取焦点', e)
    },
    onBlur (e) {
      this.visible = false
      console.log('失去焦点', e)
    },
    changeText (innerHTML, index) {
      console.log('input事件', innerHTML)
    },
    insertHtmlAtCaret (html) {
      let sel, range
      if (window.getSelection) {
        sel = window.getSelection()
        if (sel.getRangeAt && sel.rangeCount) {
          range = sel.getRangeAt(0)
          range.deleteContents()
          let el = document.createElement('div')
          el.innerHTML = html
          let frag = document.createDocumentFragment()
          let node
          let lastNode
          while ((node = el.firstChild)) {
            lastNode = frag.appendChild(node)
          }
          range.insertNode(frag)
          if (lastNode) {
            range = range.cloneRange()
            range.setStartAfter(lastNode)
            range.collapse(true)
            sel.removeAllRanges()
            sel.addRange(range)
          }
        }
      } else if (document.selection && document.selection.type !== 'Control') {
        // IE < 9
        document.selection.createRange().pasteHTML(html)
      }
    }
  }
}
</script>

<style lang="less" scoped>
  .content{
    margin: 50px auto;
    .beautiful{
      width: 300px;
      box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
      border-radius: 4px;
      border: 1px solid #ebeef5;
      background-color: #fff;
      overflow: hidden;
      color: #303133;
      transition: .3s;
    }
  }
</style>
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值