5

表单文本框的使用(二) 输入过滤(合成事件)

 1 year ago
source link: https://www.clzczh.top/2022/07/05/%E8%A1%A8%E5%8D%95%E6%96%87%E6%9C%AC%E6%A1%86%E7%9A%84%E4%BD%BF%E7%94%A8-2-%E8%BE%93%E5%85%A5%E8%BF%87%E6%BB%A4-%E5%90%88%E6%88%90%E4%BA%8B%E4%BB%B6/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

表单文本框的使用(二) 输入过滤(合成事件)

情景:输入框需要限制出现的字符,比如只能是数字。

输入框本身是没有这个功能的,但是我们可以通过JavaScript来实现。
我们能实现向输入框中输入字符,依靠的是键盘事件,所以可以通过添加键盘事件,然后根据事件对象的信息来判断符不符合条件,不符合条件,就通过event.preventDefault阻止默认事件,即阻止输入。

<body>
    <div class="input-box">
        <input type="text" size="10" maxlength="10">
    </div>

    <script>
        const ipt = document.getElementsByTagName('input')[0]

        ipt.addEventListener('keypress', (e) => {
            console.log(e.key)

            if (!/^\d/.test(e.key)) {
                e.preventDefault()
            }
        })
    </script>
</body>

上面我们添加的键盘事件是keypress,因为keyup是键盘抬起事件,这个时候已经输入到输入框里了,没有作用;而keydown会识别功能键,所以使用时还得考虑让功能键通过,不然就没法删除输入的内容了。另外,keypress支持区分大小写。

filter
filter

处理剪切板

上面我们已经实现只能输入数字了,但是如果我们从外部复制了非数字的数据,粘贴到文本框里就会突破我们的输入过滤。

filter
filter

这时候就需要通过剪切板事件来加强我们的输入过滤了(HTML5增加了剪切板事件)

  • copy:复制操作发生时触发
  • cut:剪切操作发生时触发
  • paste:粘贴操作发生时触发

这三个事件都有添加前缀before的操作发生前触发版本,但是不常用,也不知道有什么具体使用情境。阻止事件也只能在发生时触发的三个事件中阻止。

怎么获取剪切板的数据呢?
可以通过event对象上的clipboardData对象来获取,为防止未经授权访问剪切板,只能在剪切板事件期间访问clipboardData对象。

clipboardData对象上有3个方法:getDatesetDataclearData

const ipt = document.getElementsByTagName('input')[0]

ipt.addEventListener('keypress', (e) => {
    console.log(e.key)

    if (!/^\d/.test(e.key)) {
        e.preventDefault()
    }
})

ipt.addEventListener('copy', (e) => {
    // e.clipboardData.setData第一个参数是格式,第二个参数是复制的内容
    e.clipboardData.setData('text/plain', '复制了假数据')

    // 屏蔽掉默认事件,实现复制假数据
    e.preventDefault()
})

ipt.addEventListener('paste', (e) => {
    // 读取剪切板的数据
    const text = e.clipboardData.getData('text/plain')

    // 不满足条件不让粘贴
    if (!/^\d/.test(text)) {
        e.preventDefault()
    }
})

这样子,就能实现即使是粘贴的数据也要是数字才能输入到输入框了。

filter
filter

处理中文、日语等输入法

filter
filter

当我们使用输入法时,还是会绕过了我们的只能输入数字的限制。

这里引入一个比较有意思的知识点合成事件

中文这种是需要同时按下多个键才能输入一个字符的。合成事件就是用来检测和控制这种输入,输入的字符在事件对象的data中。

  • compositionstart:表示输入即将开始,此时data为空串
  • compositionupdate:新字符插入时触发,此时data为输入的字符
  • compositionend:表示即将恢复正常的键盘输入,此时data为要输入到输入框的文本
const ipt = document.getElementsByTagName('input')[0]

ipt.addEventListener('compositionstart', (e) => {
    console.log('%c%s', 'color: red;font-size: 16px;', 'conpositionstart')
    console.log(e.data)
})

ipt.addEventListener('compositionupdate', (e) => {

    console.log('%c%s', 'color: blue;font-size: 16px;', 'compositionupdate')
    console.log(e.data)


})

ipt.addEventListener('compositionend', (e) => {
    console.log('%c%s', 'color: purple;font-size: 16px;', 'compositionend')

})
filter
filter

所以说我们可以在合成事件结束的时候,即compositionend的事件处理函数中,把输入的中文给去掉,就能够不允许把汉字输进去。

const ipt = document.getElementsByTagName('input')[0]

ipt.addEventListener('compositionend', (e) => {
    // 去掉后几位
    e.target.value = e.target.value.slice(0, -e.data.length)
})
filter
filter
<body>
    <div class="input-box">
        <input type="text" size="10" maxlength="10">
    </div>

    <script>
        const ipt = document.getElementsByTagName('input')[0]

        ipt.addEventListener('keypress', (e) => {
            console.log(e.key)

            if (!/^\d/.test(e.key)) {
                e.preventDefault()
            }
        })

        ipt.addEventListener('paste', (e) => {
            // 读取剪切板的数据
            const text = e.clipboardData.getData('text/plain')

            // 不满足条件不让粘贴
            if (!/^\d/.test(text)) {
                e.preventDefault()
            }
        })

        ipt.addEventListener('compositionend', (e) => {
            // 去掉后几位
            e.target.value = e.target.value.slice(0, -e.data.length)
        })
    </script>
</body>

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK