react实现虚拟键盘支持Ant design Input和普通input Dom元素

背景:点击虚拟键盘上,值在输入框(Ant Design Input、或Dom inpu)中响应对应的值,支持在光标位置进行输入字符和删除等 操作,支持响应input onchange事件等功能。

实现思路:本想考虑通过物理键盘的方案进行适配,但是发现怎么都不能和物理键盘一样进行直接输入,如果有更好的方案请指教。

最后通过自定义事件来实现,实现不住如下:

1.点击虚拟键盘,发送点击按下按键的指令;

2.在项目公共地方响应指令:keyCode=6000, 6001, ..., 6009等,6000代表数字0, 以此类推6009代表数字9;

3.使用window Selection对象获取获取焦点输入框光标对象信息,从而获取:当前输入框的值,光标开始位置和结束位置等信息。根据value,selectionStart, selectionEnd, 输入值=>计算输入结果。

例如: 输入框值value=123|456,光标在3和4之间,selectionStart = 3, selectionEnd=3; 点击虚拟按键6009,即输入9。

计算公式:newValue = value.substr(0, selectionStart) +  inputValue + value.substring(selectionEnd, value.length); 

var newValue = '123' + 9 + '456' = '1239456'

4.值通过事件发布到当前获取焦点输入框,并触发input onChange事件:

核心:把计算结果和光标信息通过自定义事件发布到当前获取焦点的input

// 事件发布到组件中input
    const evt = new UIEvent('inputchange', {
      bubbles: false,
      cancelable: false,
    });
    const keyName = 'data';
    evt[keyName] = {
      value: newValue,
      selectionStart: selectionStart + inputValue.toString().length,
      selectionEnd: selectionStart + inputValue.toString().length,
    };

5.项目中封装公共的Input, 在组件中监听自定义事件,输入框在自定义事件中响应推送的值。


  const inputRef = useRef<InputRef & HTMLInputElement>(null);
  const inputChangeCallBack = useCallback((event: any) => {
    const target = event.target;
    const data = event.data;
    console.info('数字键盘推送的数据', data);
    if (target) {
      const selectionStart = data.selectionStart || 0;
      const selectionEnd = data.selectionEnd || 0;
      target.value = data.value;
      /**
       * 响应onChange事件:解决Input, input Dom元素value值修改,在react Input获取焦点、失去焦点获取的event.target.value值是旧的,
       * 原因:react input value有自己的state状态,直接修改input值,不会改变ract input中的状态。
       */
      handleChange?.(event);
      // 光标移动到到原来的位置加上新内容的长度
      target.setSelectionRange(selectionStart, selectionEnd);
    }
  }, []);
  /**
   * 控台数字键盘-输入处理
   */
  const focusInput = () => {
    if (inputRef.current && inputRef.current.input) {
      // react input元素
      const inputNode = inputRef.current.input;
      // 移除事件
      inputNode.removeEventListener('inputchange', inputChangeCallBack);
      // 添加添加虚拟键盘按下事件监听器
      inputNode.addEventListener('inputchange', inputChangeCallBack);
      // 添加添加虚拟键盘Enter监听器
      inputNode.addEventListener('enter', enterCallback);
    }
  };
  /**
   * 控台数字键盘-输入处理
   */
  const blurInput = () => {
    if (inputRef?.current?.input) {
      const inputNode = inputRef.current.input;
      // 移除事件
      inputNode.removeEventListener('inputchange', inputChangeCallBack);
      // 移除事件
      inputNode.removeEventListener('enter', enterCallback);
    }
  };

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您提供一些代码示例和解释。 首先,我们需要安装 `antd` 和 `react-router-dom` 依赖。 ```bash npm install antd react-router-dom ``` 然后,我们可以创建一个 `Login` 组件,作为登录界面。在这个组件中,我们可以使用 `antd` 的 `Form` , `Input` 和 `Button` 组件来创建一个登录表单。 ```jsx import React from 'react'; import { Form, Input, Button } from 'antd'; const Login = () => { const onFinish = (values) => { console.log('Success:', values); }; const onFinishFailed = (errorInfo) => { console.log('Failed:', errorInfo); }; return ( <Form name="basic" initialValues={{ remember: true, }} onFinish={onFinish} onFinishFailed={onFinishFailed} > <Form.Item label="Username" name="username" rules={[ { required: true, message: 'Please input your username!', }, ]} > <Input /> </Form.Item> <Form.Item label="Password" name="password" rules={[ { required: true, message: 'Please input your password!', }, ]} > <Input.Password /> </Form.Item> <Form.Item> <Button type="primary" htmlType="submit"> Submit </Button> </Form.Item> </Form> ); }; export default Login; ``` 接下来,我们可以创建一个简单的应用程序,在其中使用 `react-router-dom` 来切换登录页面和其他页面。 ```jsx import React from 'react'; import { BrowserRouter as Router, Switch, Route, Link } from 'react-router-dom'; import Login from './Login'; const App = () => { return ( <Router> <div> <nav> <ul> <li> <Link to="/">Home</Link> </li> <li> <Link to="/login">Login</Link> </li> </ul> </nav> <Switch> <Route path="/login"> <Login /> </Route> <Route path="/"> <h1>Welcome to the homepage!</h1> </Route> </Switch> </div> </Router> ); }; export default App; ``` 最后,我们可以将应用程序渲染到页面上。 ```jsx import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; ReactDOM.render( <React.StrictMode> <App /> </React.StrictMode>, document.getElementById('root') ); ``` 这是一个简单的 React + Ant Design 登录界面和应用程序的示例。希望能对您有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值