android开发分享用Rax开发一个联想搜索输入框,内附封装后的npm组件

来淘系实习已经一个半月了,在这里接触了一个之前未了解过的开发框架:Rax。从最开始拿到需求看着Rax一脸蒙蔽,到现在渐渐熟悉用Rax做开发,这个过程中也让我遇到了Rax的大大小小的问题。下面就来分享一下如何用Rax开发一个联想搜索输入框。需求——开篇我们拿到手的需求是这样的:有一个输入框,它支持联想搜索,当输入框里有输入时,右侧会出现一个清空的icon,点击这个icon可以可以去清空这个输入框,可能会配“热搜词”,点击“热搜词”将该“热搜词”补全到输入框内。下面是手淘主搜的例子:尝试——碰壁这.


来淘系实习已经一个半月了,在这里接触了一个之前未了解过的开发框架:Rax。从最开始拿到需求看着Rax一脸蒙蔽,到现在渐渐熟悉用Rax做开发,这个过程中也让我遇到了Rax的大大小小的问题。下面就来分享一下如何用Rax开发一个联想搜索输入框。

需求——开篇

我们拿到手的需求是这样的:有一个输入框,它支持联想搜索,当输入框里有输入时,右侧会出现一个清空的icon,点击这个icon可以可以去清空这个输入框,可能会配“热搜词”,点击“热搜词”将该“热搜词”补全到输入框内。下面是手淘主搜的例子:

用Rax开发一个联想搜索输入框,内附封装后的npm组件

尝试——碰壁

这里我们考虑用Rax提供的TextInput组件去实现这个需求,该组件主要有下面这些属性(这里只放了部分属性,并非该组件的完整属性)

用Rax开发一个联想搜索输入框,内附封装后的npm组件

当我们看到点击icon清空输入框这个功能时,首先想到用受控组件去做,当点击icon时去改变value属性的值。(虽然TextInput有自带的clear方法,可以用来清空输入框,但是考虑到我们可能还要有赋值的场景,不考虑用clear方法)

import { createElement, useState, Fragment } from 'rax'; import View from 'rax-view'; import Text from 'rax-text'; import TextInput from 'rax-textinput'; import { EventObject } from 'rax-textinput/lib/types';  import './index.css';  function SearchInput() {   const [value, setValue] = useState<string>('');    const onInput = (e: EventObject) => {     setValue(e.value);      // 发起请求     // ...   }    return (     <Fragment>       <View className="container">         <TextInput className="input"                    value={value}                    onInput={onInput}/>         {           value           && (             <Text onClick={() => setValue('')}>               清空             </Text>           )         }       </View>       <Text>         value: {value}       </Text>     </Fragment>   ); }  export default SearchInput; 

因为我们的项目需要用到web端和weex端,看一下在两个容器中的效果。

web端看上去是没问题的,符合我们预期的效果。

用Rax开发一个联想搜索输入框,内附封装后的npm组件
weex端,发现当输入框里已经有中文的时候,我们无法在后面继续输入中文。这就不符合我们的预期,如果把这样一个输入框放在我们的项目里会非常影响用户体验的。

用Rax开发一个联想搜索输入框,内附封装后的npm组件

思考——解决

大胆猜测在weex端不能连续输入中文的原因:我们使用的受控组件,用户使用ios系统在输入中文时,会自动在两个字的拼音中间加入空格,而我们在onInput事件中给value赋值导致了拼音输入中断。
考虑换用非受控组件来完成我们这个需求。分析一下,输入框的值可以被两种方式改变:

(1)通过输入框输入

(2)点击“清空”,清空输入框。或者点击“热搜词”,将其赋值到输入框

对这两种赋值方式做处理:

import { createElement, useState, Fragment } from 'rax'; import View from 'rax-view'; import Text from 'rax-text'; import TextInput from 'rax-textinput'; import { EventObject } from 'rax-textinput/lib/types';  import './index.css';  function SearchInput() {   const [value, setValue] = useState<string>('');   const [defaultValue, setDefaultValue] = useState<string>('');   const [inputKey, setInputKey] = useState<number>(0);    // (1)输入框输入事件   const onInput = (value: string) => {     setValue(value);      // 发起请求     // ...   }    // (2)设置输入框的值(非输入事件)   const setInputValue = (text: string) => {     // 重新渲染输入框,并将要设的值赋给defaultValue     setInputKey(inputKey + 1);     setDefaultValue(text);     /*         可以考虑延迟重新渲染,优先触发输入事件         setTimeout(() => {           setInputKey(inputKey + 1);           setDefaultValue(text);         }, 20);     */      // 触发输入事件     onInput(text);   }    return (     <Fragment>       <View className="container">         <TextInput className="input"                    key={inputKey}                    defaultValue={defaultValue}                    onInput={(e: EventObject) => onInput(e.value)}/>         {           value           && (             <Text onClick={() => setInputValue('')}>               清空             </Text>           )         }       </View>       <Text>         value: {value}       </Text>     </Fragment>   ); }  export default SearchInput; 

我们看下效果

web端:

用Rax开发一个联想搜索输入框,内附封装后的npm组件
weex端:

用Rax开发一个联想搜索输入框,内附封装后的npm组件
可以看到,在两种容器里都达到了我们预期的效果。

封装——复用

当我们实现这个功能后考虑到以后复用,决定在Rax的TextInput组件上封装一下,重写它的onInput事件,并加上常用的函数防抖逻辑。

npm包:debounce-text-input

源码:debounce-text-input

使用参考:

import { createElement, useState, Fragment } from 'rax'; import View from 'rax-view'; import Text from 'rax-text'; import DebounceTextInput from 'debounce-text-input'; import { EventObject } from 'rax-textinput/lib/types';  import './index.css'; function SearchInput() {   const [value, setValue] = useState<string>('');    const onInput = (text: string) => {     setValue(text);          // 网络请求     // ...   }    return (     <Fragment>       <View className="container">         <DebounceTextInput className="input"                            value={value}                            debounceInterval={600}                            onInput={(e: EventObject) => onInput(e.value)}/>         {           value           && (             <Text onClick={() => onInput('')}>               清空             </Text>           )         }       </View>       <Text>         debounceInterval: 600       </Text>       <Text>         value: {value}       </Text>       <Text onClick={() => onInput('felix')}>         set: felix       </Text>     </Fragment>   ); }  export default SearchInput; 

web端:

用Rax开发一个联想搜索输入框,内附封装后的npm组件

weex端:

用Rax开发一个联想搜索输入框,内附封装后的npm组件

效果——结尾

最终我们这个需求顺利完成,效果如下:

用Rax开发一个联想搜索输入框,内附封装后的npm组件

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/addevelopment/897793.html

(0)
上一篇 2021年10月22日
下一篇 2021年10月22日

精彩推荐