基于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>
相关推荐
拉不动的猪14 分钟前
前端自做埋点,我们应该要注意的几个问题
前端·javascript·面试
王景程23 分钟前
如何测试短信接口
java·服务器·前端
安冬的码畜日常1 小时前
【AI 加持下的 Python 编程实战 2_10】DIY 拓展:从扫雷小游戏开发再探问题分解与 AI 代码调试能力(中)
开发语言·前端·人工智能·ai·扫雷游戏·ai辅助编程·辅助编程
小杨升级打怪中1 小时前
前端面经-JS篇(三)--事件、性能优化、防抖与节流
前端·javascript·xss
清风细雨_林木木1 小时前
Vue开发网站会有“#”原因是前端路由使用了 Hash 模式
前端·vue.js·哈希算法
鸿蒙布道师1 小时前
OpenAI为何觊觎Chrome?AI时代浏览器争夺战背后的深层逻辑
前端·人工智能·chrome·深度学习·opencv·自然语言处理·chatgpt
袈裟和尚1 小时前
如何在安卓平板上下载安装Google Chrome【轻松安装】
前端·chrome·电脑
曹牧1 小时前
HTML字符实体和转义字符串
前端·html
小希爸爸2 小时前
2、中医基础入门和养生
前端·后端
局外人LZ2 小时前
前端项目搭建集锦:vite、vue、react、antd、vant、ts、sass、eslint、prettier、浏览器扩展,开箱即用,附带项目搭建教程
前端·vue.js·react.js