IOS H5页面input长按退格键时光标错乱问题解决

在iOS中,H5页面里的input输入特别长的内容,长按退格键,会有莫名奇妙的内容会选中

上图就明白


IOS H5页面input长按退格键时光标错乱问题解决_第1张图片
快速删除bug

input里内容已经删除完了,但是莫名其面选中了placeholder,如果没有placeholder,还会选中空白区域

关键这个bug出现的概率还挺高

我开始的解决方法是 在删除文字以后 对input进行一些操作 比如模拟click 让它失去焦点 获取焦点等等

不但不起作用,bug还更严重了。。。


IOS H5页面input长按退格键时光标错乱问题解决_第2张图片
更严重的bug

出现了两个莫名其妙被选中的区域

然后我找了找大厂的页面,也都有这个bug,唯有淘宝没有问题

然后就开始看淘宝的代码,也没什么收获,但是突然想到一个办法

阻止键盘的默认事件

就是按下退格键的时候阻止默认事件,然后自己手动去操作input里面的字符串

相当于自己手动实现了删除文字的功能

直接上代码吧

因为我们是vue的项目,所以我使用vue写的,但是很容易就可以把这个功能抽出来

写了一个directive

```

import Vue from 'vue'

import getDeviceInfo from '../common/deviceInfo'

Vue.directive('inputDelete', {

    inserted: function (el, bind) {

        if (getDeviceInfo().isIOS) {

            el.addEventListener('keydown', (e) => {

                if (e.keyCode === 8) {

                    e.preventDefault()

                    let text = el.value

                    if (text.length) {

                        const start = el.selectionStart

                        const end = el.selectionEnd

                        const length = text.length

                        if (end === length) {

                            if (start !== end) {

                                text = text.slice(0, start)

                            } else {

                                text = text.slice(0, start - 1)

                            }

                        } else {

                            if (end === 0) {

                                return

                            }

                            let p1

                            let p2

                            if (start !== end) {

                                if (start === 0) {

                                    text = text.slice(end)

                                    Vue.prototype.$nextTick(() => {

                                        el.setSelectionRange(0, 0)

                                    })

                                } else {

                                    p1 = text.slice(0, start)

                                    p2 = text.slice(end)

                                    text = p1 + p2

                                    Vue.prototype.$nextTick(() => {

                                        el.setSelectionRange(start, start)

                                    })

                                }

                            } else {

                                p1 = text.slice(0, start - 1)

                                p2 = text.slice(end)

                                text = p1 + p2

                                Vue.prototype.$nextTick(() => {

                                    el.setSelectionRange(start - 1, start - 1)

                                })

                            }

                        }

                    }

                    el.value = text

                    bind.value.target[bind.value.name] = text

                }

            })

        }

    }

})

```

使用方式如下

```

```

实现步骤如下

1.阻止默认的删除事件

2.获取光标的位置或者光标所选中的范围,以确定要去掉的字符是哪些

3.分割字符串,把要留下的字符取出来,拼接在一起

4.根据之前光标的位置重新设置光标的位置(这里如果不设置光标的位置,光标就会自动跳到最后)

5.更改input里的值

6.因为是在vue里,只修改input的值是不行的,还要更改data里的值,所以在指令里传了参数过来

问题暂时这样解决了,目前通过测试了

经过简单更改可以用到textarea上等,可以简单更改适用于第三方UI框架上

然而

因为屏蔽了默认行为,导致了一些其他bug

然后我又继续找解决办法

最后用一个莫名其妙的方式解决了

```

import Vue from 'vue'

import getDeviceInfo from '../common/deviceInfo'

Vue.directive('inputDelete', {

    inserted: function (el, bind) {

        if (getDeviceInfo().isIOS) {

            el.addEventListener('keydown', (e) => {

                if (e.keyCode === 8) {

                    window.requestAnimationFrame(() => {

                    })

                }

            })

        }

    }

})

```

就是在删除的时候调用了一下requestAnimationFrame,然后什么也没做,就不会触发ios的快速删除了

真是奇葩

使用也更方便了

```

```

完结

你可能感兴趣的:(IOS H5页面input长按退格键时光标错乱问题解决)