vue开发中使用span替代input输入,兼容IE

2021-06-10  本文已影响0人  有你有团

以前开发中涉及到用户输入,一般使用input,textarea等html元素,当然这是最方便,最快捷的,偶然的一次项目中发现这两者不太好用,查了很多资料,结果还是不尽如人意,直到某次在度娘查到了一个html属性contenteditable

contenteditable 属性指定元素内容是否可编辑。
注意: 当元素中没有设置 contenteditable 属性时,元素将从父元素继承。

也就是说当元素设置 contenteditable 为true 那么当前元素可编辑

<p contenteditable="true">这是一个段落。是可编辑的。尝试修改文本。</p>

注意:此时该元素获取焦点时,该元素就可以进行编辑,和输入框一样的效果,但是它的值不是value而是innerText/innerHtml

说一下使用场景

在canvas上绘制文字时,我们需要实时绘制当前输入内容,刚开始使用场景是利用动态创建input元素,input获取焦点输入文字,当input失去焦点时绘制当前input的内容,功能可以实现,唯一不足就是我们需要输入框的大小按照输入内容的长度改变,使用input明显不太方便,可以使用动态改变size属性,如果输入的字母,数字,符合可以实现,当时如输入汉字的就会有问题,我们知道span等行内元素可以根据文字长度改变元素大小,所以,我们使用动态创建span标签,设置contenteditable="true",然后设置相应的样式,就可以模仿input输入框的效果

let span = document.createElement('span')
span.contenteditable=true
// 如果要创建完成后获取焦点需要使用setTimeout
setTimeout(function(){
  span.focus()
},0)

vue组件封装

<template>
  <span class="span-edit" :style="styleObj" :contenteditable="contenteditable" v-html="innerText" @focus="isFocus = true" @blur="isFocus = false" @keyup="inputHandle"></span>
</template>

<script>
export default {
  name: 'EditInput',
  props: {
    value: {
      type: String,
      default: ''
    },
    contenteditable: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      isFocus: false,
      innerText: this.value
    }
  },
  computed: {
    styleObj() {
      return {
        'border-bottom': this.value ? 'none' : '1px solid #696969'
      }
    }
  },
  watch: {
    value() {
      // 解决光标跳动BUG
      if (!this.isFocus) {
        this.innerText = this.value
      }
    }
  },
  methods: {
    // 如果使用元素input事件不兼容ie,无法获取到值,可以使用keyup代替,如果使用keydown ie浏览器会记录每一次按键(输入中文的时候)
    inputHandle(e) {
      let innerText = e.target.innerText
      this.$emit('input', innerText)
    }
  }
}
</script>

<style lang="scss" scoped>
.span-edit {
  outline: none;
  // ie文字换行没有下划线
  // border-bottom: 1px solid #000;
  min-width: 25px;
  display: inline-block;
  font-size: 16px;
  line-height: 20px;
  word-break: break-all;
  // 兼容ie写法
  text-decoration: underline;
  text-decoration-color: #696969;
}
</style>
上一篇 下一篇

猜你喜欢

热点阅读