基于react-vant实现弹窗搜索功能

学习一下项目中的代码

弹出层的顶部用到了Search组件

1. action

Search组件中需要自定义右侧的按钮,可以使用showAction(默认文字为取消)+ actionText自定义按钮文字;也可以使用action自定义右边部分操作区域

官网文档使用方法1:

jsx 复制代码
<Search
  showAction
  label="地址"
  actionText={<div onClick={() => Toast.info(value)}>搜索</div>}
  value={value}
  onChange={setValue}
  placeholder="请输入搜索关键词"
/>

2. value

value 用于控制搜索框中的文字

value绑定的变量,通过onChange更新即可

3.点击进行搜索

jsx 复制代码
// 搜索关键词
const onSearchClinic = async () => {
    // 前置校验
    if (!searchName) {
      Toast('请输入名称关键字再进行搜索')
      return
    }
    // 开始搜索
    try {
      setSearchLoading('loading')
      const {
        data: { rows },
      } = await triggerClinicList()
      const _rows = [...rows].map((item) => ({
        ...item,
        value: item.code,
        text: item.name,
      }))
      setClinicList(_rows)
      setSearchLoading('sucess')
    } catch (error) {
      setSearchLoading('sucess')
    }
}

数据列表 - List 组件

List 组件滚动到底部时,会触发 onLoad 事件,此时可以发起异步操作并更新数据,若数据已全部加载完毕,则直接将 finished 设置成 true 即可。

react-vant - List 内部包含了防止并发的重复请求的逻辑,使用中不需要额外处理

如果有分页,则可以使用onLoad事件,项目中为全量返回,所以不需要这个。

选择则某个诊所之后进行反显

搜索的字段和外层最终反显的字段分为两个记录,关闭的时候或者每次打开的时候要清除内部的字段(看业务要求)

jsx 复制代码
const [clinicName, setClinicName] = useState('') // 外层业务字段
  const [searchName, setSearchName] = useState('') // 弹窗记录搜索的关键字
// 点击cell,进行选择
const setClinicHandle = (v: any) => {
    // 更新外层输入框名称
    // 关闭弹窗
    onCloseClinicPop()
}

占位组件 - Empty

占位组件的图片有两个状态:1.图片显示 2. loading显示

占位组件的文案有两个状态:1.初始化时的搜索提醒 2. 搜索结果为空时的提醒

jsx 复制代码
  // loading -- 加载中,wait -- 初始化, sucess -- 搜索完成(不论结果如何)
  const [searchLoading, setSearchLoading] = useState<'wait' | 'loading' | 'sucess'>('wait')

其他小细节:

  1. 点击外层按钮,唤起弹窗时自动聚焦到搜索输入框
jsx 复制代码
const searchRef = useRef<SearchInstance | any>(null)
// 显示
const onShowClinicPop = () => {
    // do something 点击前校验,清空搜索关键词 onClearClinic
    setShowClinicPop(true) // 弹窗
    setTimeout(() => {
      if (searchRef && searchRef.current) {
        searchRef.current?.focus() // 设置焦点
      }
    }, 0)
 }
// 关闭弹窗
const onCloseClinicPop = () => {
    if (searchRef && searchRef.current) {
      searchRef.current?.blur() // 设置焦点
    }
    setShowClinicPop(false)
}

部分代码如下:

jsx 复制代码
<Popup
position="bottom"
round={true}
visible={showClinicPop}
onClose={onCloseClinicPop}
style={{ height: '60vh' }}
>
    <div className="popup-header">
      <VantButton
        style={{
          border: 'none',
          boxShadow: 'none',
          backgroundColor: 'transparent',
          color: 'inherit',
        }}
        icon={<Cross />}
        onClick={onCloseClinicPop}
      />
    </div>
    <Search
      action={
        <div
          className="search-text"
          onClick={onSearchClinic}
        >
          搜索
        </div>
      }
      value={searchName}
      onChange={(v) => {
        setSearchName(v)
      }}
      placeholder="输入名称关键字"
      onSearch={onSearchClinic}
      onClear={onClearClinic}
      ref={searchRef}
    />
    <div style={{ height: 'calc(60vh - 98px)', overflowY: 'auto' }}>
      {clinicList?.length > 0 ? (
        <List
          onLoad={() => new Promise(() => {})}
          finished={true}
        >
          {clinicList.map((item, index) => (
            <Cell
              key={index}
              value={item.text}
              isLink
              arrowDirection="right"
              valueClass="text-[#323232]"
              onClick={() => {
                setClinicHandle(item.code)
              }}
            />
          ))}
        </List>
      ) : (
        <Empty
          image={
            searchLoading === 'loading' ? (
              <div className="empty-loading">
                <Loading type="ball" />
              </div>
            ) : (
              'search'
            )
          }
          description={
            searchLoading === 'sucess'
              ? '搜索列表为空'
              : searchLoading === 'wait'
                ? '点击搜索查找您的诊所'
                : ''
          }
        />
      )}
    </div>
</Popup>
相关推荐
gongzemin11 分钟前
React 和 Vue3 在事件传递的区别
前端·vue.js·react.js
Apifox23 分钟前
如何在 Apifox 中通过 Runner 运行包含云端数据库连接配置的测试场景
前端·后端·ci/cd
树上有只程序猿1 小时前
后端思维之高并发处理方案
前端
庸俗今天不摸鱼1 小时前
【万字总结】前端全方位性能优化指南(十)——自适应优化系统、遗传算法调参、Service Worker智能降级方案
前端·性能优化·webassembly
黄毛火烧雪下2 小时前
React Context API 用于在组件树中共享全局状态
前端·javascript·react.js
Apifox2 小时前
如何在 Apifox 中通过 CLI 运行包含云端数据库连接配置的测试场景
前端·后端·程序员
一张假钞2 小时前
Firefox默认在新标签页打开收藏栏链接
前端·firefox
高达可以过山车不行2 小时前
Firefox账号同步书签不一致(火狐浏览器书签同步不一致)
前端·firefox
m0_593758102 小时前
firefox 136.0.4版本离线安装MarkDown插件
前端·firefox
掘金一周2 小时前
金石焕新程 >> 瓜分万元现金大奖征文活动即将回归 | 掘金一周 4.3
前端·人工智能·后端