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

可编辑div组件

    • 前言
    • 环境
    • 分析需要的功能
    • 代码如下
    • 使用
    • 效果如下

前言

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

环境

  • vue2.5
  • webpack3.6

分析需要的功能

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

代码如下

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


<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>

使用


<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: '[噪音]\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>

效果如下

你可能感兴趣的:(vuejs)