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>
生活的意义就是你自己知道你要做什么,明确目标。没有目标,后面都是瞎扯!
https://pengchenggang.gitee.io/navigator/
SMART原则:
目标必须是具体的(Specific)
目标必须是可以衡量的(Measurable)
目标必须是可以达到的(Attainable)
目标必须和其他目标具有相关性(Relevant)
目标必须具有明确的截止期限(Time-based)