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

前言

最近接到一个需求,要实现一个能输入带颜色的文字的输入框,可以渲染html字符串。立刻就想到了HTML的contenteditable属性。在HTML中,任何元素都可以编辑,只要将元素的contenteditable属性设置为true。

环境

  • vue2.5
  • webpack3.6

分析需要的功能

  • 提供快捷键
  • 提供input、change、focus、blur事件
  • v-model指令可以绑定该组件
  • 禁用功能
  • 清空输入的内容

代码如下

EventUtil是封装的跨浏览器的事件对象。

<!--BaseEditDiv.vue-->
<template>
  <div
    class="base-edit-div"
    :style="{'-webkit-user-modify': disabled ? 'read-only' : '', '-moz-user-modify': disabled ? 'read-only' : '', 'overflow-x': disabled ? 'hidden' : '', 'height' : disabled && !text ? '35px' : '100%'}"
    contenteditable="true"
    @focus="$emit('focus', $event)"
    @click="$emit('click')"
    @blur="$emit('blur', $event)"
    @keydown="$emit('keydown', $event)"
    @keyup="$emit('keyup', $event)"
    @input="domInput"
  ></div>
</template>

<script>
import EventUtil from './EventUtil.js'
export default {
  props: {
    // 默认值
    text: {
      type: String,
      default: ''
    },
    disabled: {
      type: Boolean,
      default: false
    }
  },
  mounted () {
    // 组件初始化,对innerHTML赋值
    this.$el.innerHTML = this.text
    // 一旦div的dom发生插入值的操作,调用domChange()方法传递值至父组件
    EventUtil.addHandler(this.$el, 'DOMNodeInserted', this.domChange)
  },
  beforeDestroy () {
    // 销毁
    EventUtil.removeHandler(this.$el, 'DOMNodeInserted', this.domChange)
  },
  methods: {
    domChange (event) {
      this.$emit('input', this.$el.innerHTML, this.$el.dataset.index, event)
    },
    emptyInnerHTML () {
      this.$el.innerHTML = ''
      this.$emit('input', this.$el.innerHTML, this.$el.dataset.index, event)
    },
    domInput (event) {
      this.$emit('input', this.$el.innerHTML, this.$el.dataset.index, event)
    }
  }
}
</script>

<style lang="less" scoped>
.base-edit-div{
  position: relative;
  outline: none;
  border: 1px solid #EAECF1;
  padding: 5px 26px 5px 12px;
  border-radius: 2px;
  box-sizing: border-box;
  width: 100%;
  height: 100%;
  overflow: auto;
  word-break: break-all;
  user-select: text;
  text-align: left;
}
</style>

使用

<!--HelloWorld.vue-->
<template>
  <div class="content">
    <base-edit-div
      class="beautiful"
      :text="checkHtml"
      v-model="checkHtml"
    >
    </base-edit-div>
  </div>
</template>

<script>
import BaseEditDiv from './BaseEditDiv'
export default {
  components: {
    BaseEditDiv
  },
  data () {
    return {
      checkHtml: '<b style="color:red;font-weight:normal" contenteditable="false">[噪音]</b>\r'
    }
  }
}
</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>

效果如下

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值