来淘系实习已经一个半月了,在这里接触了一个之前未了解过的开发框架:Rax。从最开始拿到需求看着Rax一脸蒙蔽,到现在渐渐熟悉用Rax做开发,这个过程中也让我遇到了Rax的大大小小的问题。下面就来分享一下如何用Rax开发一个联想搜索输入框。
需求——开篇
我们拿到手的需求是这样的:有一个输入框,它支持联想搜索,当输入框里有输入时,右侧会出现一个清空的icon,点击这个icon可以可以去清空这个输入框,可能会配“热搜词”,点击“热搜词”将该“热搜词”补全到输入框内。下面是手淘主搜的例子:
尝试——碰壁
这里我们考虑用Rax提供的TextInput组件去实现这个需求,该组件主要有下面这些属性(这里只放了部分属性,并非该组件的完整属性)
当我们看到点击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端看上去是没问题的,符合我们预期的效果。
weex端,发现当输入框里已经有中文的时候,我们无法在后面继续输入中文。这就不符合我们的预期,如果把这样一个输入框放在我们的项目里会非常影响用户体验的。
思考——解决
大胆猜测在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端:
weex端:
可以看到,在两种容器里都达到了我们预期的效果。
封装——复用
当我们实现这个功能后考虑到以后复用,决定在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端:
weex端:
效果——结尾
最终我们这个需求顺利完成,效果如下:
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/addevelopment/897793.html