textareaCenter 未完结 其实就是iview的textarea的从写一遍 需求是光标上下居中

重点1: 一但赋值内容,光标会失去,导致光标到第一位

解决方法 设置一个状态位isChange,编辑的时候不进行watch更新,因为emit会自动改变外层的值,触发watch

解决方法2 找回上一次的值进行替换

 

重点2:div可编辑  contenteditable="true"

 

重点3:div内只能是文本 不要html

-webkit-user-modify: read-write-plaintext-only;
user-modify: read-write-plaintext-only;

 

重点4: 上下高度居中(多行)

display: table-cell; vertical-align: middle;

 

重点5:移动光标

 // 光标移动到起始偏移位置(具体看上下文代码)

document.getSelection().collapse(_this.firstChild, txtAnchorOffset)

重点5:输入中文的长度计算

重点6:复制黏贴事件的处理(最大长度)光标如何恢复原始位置,超出最大长度如何处理

 

最后 fail 的地方是

1,没找到中文拼音输入多字,按空格等按键确认的文字是什么,就是没找到怎么获取

2. 没找到中文输入前的文字是什么

3. 多行的文字进行处理,我记得是个数组node

4. 没能恢复到没有输入的前的状态

 

小计:

发现iview的textarea,在这块也存在光标位置计算不准确,它是把文字删了,恢复之前的状态,但是光标位置没有恢复。

 

 

参考

-webkit-user-modify

DIV可编辑后,与限制输入及光标偏移的纠葛
https://www.cnblogs.com/echon-cw/p/9809524.html

限制可编辑div只能输入纯文本
https://www.cnblogs.com/libo0125ok/p/8143642.html

 

<!--
* @description text
!-->
<template>
  <div ref="textareaCenter" id="textareaCenter"
       @focus="isChange = false"
       @blur="isChange = true"
       class="textareaCenter" contenteditable="true" v-text="innerValue">
  </div>
</template>

<script>
// import privateZenMixins from '@/view/biz/input/components/privateZenMixins.js'
export default {
  name: 'textareaCenter',
  // mixins: [privateZenMixins],
  components: {},
  props: {
    maxlength: {
      type: Number,
      default: 0
    },
    value: {
      type: String,
      default: ''
    }
  },
  data () {
    return {
      isChange: true,
      innerValue: this.value
    }
  },
  watch: {
    value (val) {
      if (this.isChange) {
        this.innerValue = val
      }
    },
    innerValue (val) {
      console.info('innerValue', val)
    }
    // value (val) {
    //   console.info('this.$refs.textareaCenterRef.target.innerText', this.$refs.textareaCenterRef.innerText)
    //   // console.info('watch value', val)
    //   // this.$nextTick(() => {
    //   // this.valueInner = this.getMaxText(val)
    //   // })
    //
    //   // this.$emit('input', this.valueInner)
    //   // console.info('watch this.valueInner', this.valueInner)
    //   if (!this.lock) {
    //     console.info('watch lock val', val)
    //     this.valueInner = this.getMaxText(val)
    //     this.$refs.textareaCenterRef.innerText = this.getMaxText(val)
    //   }
    // }
  },
  computed: {},
  methods: {
    // oEmit (event, oldtxt, firstChild, txtAnchorOffset)
    oEmit (event) {
      if (this.$refs.textareaCenter.innerText.replace(/\n/g, 'n').length >= this.maxlength) {
        event.preventDefault()
      }
      console.info('oEmit', this.$refs.textareaCenter.innerText.replace(/\n/g, 'n').length)
      this.$emit('input', this.$refs.textareaCenter.innerText)
    },
    init () {
      let _this
      let oldDate
      let noteMax = this.maxlength
      let oThis = this
      // let that = oThis.$refs.textareaCenter.innerText
      let content = document.getElementById('textareaCenter')
      // 注册中文的输入事件,
      let isCN = false
      content.addEventListener('compositionstart', function (event) {
        oThis.oEmit(event)
        console.info('compositionstart')
        isCN = true
        console.info('kkk3', this.textContent.replace(/\n/g, 'n').length)
        // 撤销预输入内容,必须否则会替代末尾字符

        if (this.textContent.replace(/\n/g, 'n').length >= noteMax) {
          event.preventDefault()
        }
      })
      content.addEventListener('compositionend', function (event) {
        oThis.oEmit(event)
        console.info('compositionend')
        isCN = false
        console.info('oldDate', oldDate, 'event.clipboardData.getData(\'Text\').length')
        oThis.$refs.textareaCenter.innerText = oThis.$refs.textareaCenter.innerText.slice(0, noteMax)
        document.getSelection().collapse(_this.firstChild, txtAnchorOffset)
      })
      // 注册文本输入事件,获取光标的起止偏移数据,如果是非中文以及超出长度的输入,则撤销本次操作
      let txtAnchorOffset, txtFocusOffset
      content.addEventListener('textInput', function (event) {
        oThis.oEmit(event)
        console.info('textInput', oThis.innerValue, '11jj', content.textContent)
        let _sel = document.getSelection()
        txtAnchorOffset = _sel.anchorOffset
        txtFocusOffset = _sel.focusOffset

        console.info('kkk2', this.textContent.replace(/\n/g, 'n').length)
        // 必须加上isCN的判断,否则获取不到正确的光标数据
        if (!isCN && this.textContent.replace(/\n/g, 'n').length >= noteMax) {
          event.preventDefault()
        }
      })
      // 注册粘贴事件,获取粘贴数据的长度
      let pastedLength
      content.addEventListener('paste', function (event) {
        oThis.oEmit(event)
        console.info('paste')
        if (!event.clipboardData) return
        pastedLength = event.clipboardData.getData('Text').length
        let txtLength = oThis.$refs.textareaCenter.innerText.replace(/\n/g, 'n').length
        if ((pastedLength + txtLength) >= noteMax) {
          event.preventDefault()
        }
      })

      // 注册输入事件,对输入的数据进行
      content.addEventListener('input', function (event) {
        oThis.oEmit(event)
        console.info('input')
        setTimeout(function () {
          oThis.oEmit(event)
          console.info('input setTimeout')
          // oldDate
          if (!isCN) {
            _this = content
            console.info('kkk1', _this.textContent.replace('\n', '3333333n').length)
            if (_this.textContent.replace(/\n/g, 'n').length > noteMax) {
              let data = _this.textContent
              if (pastedLength > 1) {
                oldDate = data.slice(0, txtAnchorOffset) + data.slice(txtFocusOffset + pastedLength, data.length)
                // 粘贴字符串长度置为0,以免影响到下一次判断。
                pastedLength = 0
              } else {
                oldDate = data.slice(0, txtAnchorOffset) + data.slice(txtFocusOffset, data.length)
              }
              // 再次截取最大长度字符串,防止溢出
              _this.textContent = oldDate.slice(0, noteMax)
              // mThis.$emit('input', _this.textContent)
              // oThis.oEmit(event, oldDate.slice(0, noteMax), _this.firstChild, txtAnchorOffset)
              oThis.oEmit(event)
              console.info('_this.textContent', _this.textContent)
              // console.info('mThis', mThis)
              // 光标移动到起始偏移位置
              document.getSelection().collapse(_this.firstChild, txtAnchorOffset)
            }
          }
        }, 0)
      })
    }
    // getMaxText (txt) {
    //   let ret
    //   if (this.maxlength === 0) {
    //     ret = txt
    //   } else {
    //     if (txt.length > this.maxlength) {
    //       ret = txt.substr(0, this.maxlength)
    //     } else {
    //       ret = txt
    //     }
    //   }
    //   console.info('ret', ret)
    //   return ret
    // },
    // textareaCenterInput (item) {
    //   // this[attr] = api.getStrByteLen(this[attr], length)
    //   // console.info('textareaCenterInput', item)
    //   // innerText innerHTML
    //   // item.target.innerText = this.getMaxText(item.target.innerText)
    //   this.$emit('input', item.target.innerText)
    // }

  },
  created () {},
  mounted () {
    this.init()
    console.info('value', this.value)
  }
}
</script>
<style lang="less">
  /*.textareaCenterWrap {*/
    /*display: table;*/
    /*width: 100%;*/
  /*}*/
  .textareaCenter {
    background-color: #CCCCCC;
    -webkit-user-modify: read-write-plaintext-only;
    user-modify: read-write-plaintext-only;
    width: 100%;
    height: 100%;
    margin: 0;
    /*!*display: inline-block;*!*/
    display: table-cell;
    text-align: left;
    padding: 10px;
    /*!*padding-left: 10px;*!*/
    vertical-align: middle;
    white-space: pre-wrap;
    font-size: 0.14rem;
    font-family: "微软雅黑 regular";
    &:focus {
      outline: #d5e8fc auto 0px !important;
    }
  }

</style>

 

posted @ 2019-11-06 14:48  彭成刚  阅读(456)  评论(0编辑  收藏  举报