实现在中文输入法下输入“【】”自动替换为“〔〕”

809 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第六天,点击查看活动详情

1.jpg

记录一次不常见需求实现
祝愿看到文章的朋友身体健康;如果可以麻烦一键三连

需求:

在勾选了六角符号时,中文输入法下输入左中括号自动替换为“〔〕”,因为中文输入左中括号就是“【】”两个括号;输入右中括号替换为“〕”;兼容谷歌和IE

image.png

思路:

监听键盘抬起事件(keyup),如果六角符号是选中状态,并且按下的是“【”或者“】”开始做替换处理

代码:

<template>
  <div id="app">
      <input type="text" class="fd-input-box" v-model="nameString" @keyup="nameKeyUp">
      <input type="checkbox" v-model="checked">六角符号
  </div>
</template>
<script>
export default {
    name: 'App',
    data() {
        return {
            nameString:'',
            checked:false
        };
    },
    methods:{
        nameKeyUp(ent) {
            const index = ent.srcElement.selectionStart;
            const rightText = '〕';
            const text = '〔〕';
            const name = this.nameString;
            // 表示用户按下中文方阔好 【】
            if (this.checked && (name.indexOf('】') !== -1)) {
                if (ent.key === '[' || ent.key === 'ArrowLeft') {
                    this.nameString = name.slice(0, index - 1) + text + name.slice(index + 1);
                }
                if (ent.key === ']') {
                    this.nameString = name.slice(0, index - 1) + rightText + name.slice(index);
                }
            }
            this.$nextTick(() => {
                ent.srcElement.focus();
                ent.srcElement.selectionStart = index;
                ent.srcElement.selectionEnd = index;
            });
        }
    }
};
</script>

问题(bug):

  1. 先输入左中括号接着马上输入右中括号是输不上的;所以在代码中只判断了是否有右中括号是不对的(这里只判断是否有右中括号的原因是输入左中括号也有右中括号,成对出现)

    a. 如果在没有勾选六角符号的情况下输入右中括号,再勾选六角符号,再输入左中括号接着输入右中括号会将前面那个字替换为右六角符号(因为此时是输入不了右中括号的)

  2. 在不同的输入法下面,输入左中括号替换不正确,因为光标位置可能是在【】的中间,也可能是在【】的右边

解决方法:

  1. 针对第一个问题,需要判断一下输入的当前位置前一个是否是右中括号(不能完全解决)
  2. 针对第二个问题,判断光标的左边是】还是右边是】
<template>
  <div id="app">
      <input type="text" class="fd-input-box" v-model="nameString" @keyup="nameKeyUp">
      <input type="checkbox" v-model="checked">六角符号
  </div>
</template>


<script>
export default {
    name: 'App',
    data() {
        return {
            nameString:'',
            checked:false
        };
    },
    methods:{
        nameKeyUp(ent) {
            // 表示用户按下中文方阔好 【】
            if (this.checked) {
                const index = ent.srcElement.selectionStart;
                const rightText = '〕';
                const text = '〔〕';
                const name = this.nameString;
                if (ent.key === '[' || ent.key === 'ArrowLeft') {
                    if (name.slice(index, index + 1) === '】') {
                        this.nameString = name.slice(0, index - 1) + text + name.slice(index + 1);
                    } else if (name.slice(index - 1, index) === '】') {
                        this.nameString = name.slice(0, index - 2) + text + name.slice(index);
                    }
                }
                if (ent.key === ']' && name.slice(index - 1, index) === '】') {
                    this.nameString = name.slice(0, index - 1) + rightText + name.slice(index);
                }
                this.$nextTick(() => {
                    ent.srcElement.focus();
                    ent.srcElement.selectionStart = index;
                    ent.srcElement.selectionEnd = index;
                });
            }
        }
    }
};
</script>

注意的点:

1、输左中括号成对出现,所以keyup事件会执行两次,如果使用keydown事件不兼容IE

2、输入左中括号后立即输入右中括号不能输入

3、判断ent.key === '[' || ent.key === 'ArrowLeft'是为了兼容IE和谷歌,他们获取的key不同

4、如果在没有勾选六角符号的情况下输入右中括号,再勾选六角符号,再输入左中括号接着输入右中括号会将前面那个字替换为右六角符号的问题没有完全解决,当光标前面刚好是】时还是会被替换

如果有更好的方法请留言~~~