搜索框中实现走马灯效果【组件】

在data.d.ts中

interface RevolvingProps {
  getValues: (val) => void // 传给父组件 搜索框中的值
  list // 父组件传入走马灯的数据
  values?: string // 父组件传过来的值 (搜索框中)
  urlSearch?: string // 父组件传过来的搜索面板路由地址
  width?: number // 宽度
}
export type { RevolvingProps }

在index.tsx中渲染

import React, { useEffect, useRef, useState } from 'react'
import type { RevolvingProps } from './data'
import { ContentArea } from './styled'
import { useDebounce, useUpdateEffect } from 'ahooks'
import { SearchBar } from 'antd-mobile'
import { useNavigate } from 'react-router-dom'
const RevolvingDoor: React.FC<RevolvingProps> = (props) => {
  const navigate = useNavigate()

  const { getValues, list, values, urlSearch, width } = props
  const [value, setValue] = useState(undefined) as any
  const debouncedValue = useDebounce(value, { wait: 1000 }) // 用来处理防抖值的 Hook。
  const [status, setStatus] = useState(false)

  useEffect(() => {
    if (values) {
      setValue(values)
    }
  }, [values])
  
  let timer: any = null
  const contentBox = useRef<any>()
  const parent = useRef<any>()
  const parentTwo = useRef<any>()

  const handleSearch = (val: any) => {
    setValue(val)
  }
  useUpdateEffect(() => {
    getValues(debouncedValue) // 返回给父组件的值
  }, [debouncedValue])

  useEffect(() => {
    if (
      list?.length &&
      contentBox.current &&
      parent.current &&
      parentTwo.current
    ) {
      parentTwo.current.innerHTML = parent.current.innerHTML
      const autoScrollLine = () => {
        if (!contentBox.current) {
          return
        }
        /*判断滚动内容是否已经滚完,滚完了则滚动的值重新设置到0
      否则就每隔30毫秒向上滚动1px*/
        if (contentBox.current.scrollTop >= parent.current.offsetHeight) {
          contentBox.current.scrollTop = 0
        } else {
          contentBox.current.scrollTop++
        }
        /*判断滚动的距离刚好为一条公告的高度时停掉定时器,
        隔1s之后重新启动定时器即可实现公告滚动停留效果 */
        if (
          contentBox.current.scrollTop % contentBox.current.offsetHeight ===
          0
        ) {
          clearInterval(timer)
          setTimeout(() => {
            timer = setInterval(autoScrollLine, 30)
          }, 1000)
        }
      }
      timer = setInterval(autoScrollLine, 30)
    }
    return () => {
      timer = null
    }
  }, [list])
  const handlerClear = () => {
    setValue('')
  }

  return (
    <ContentArea value={status}>
      <SearchBar
        style={{
          width: width ? width : '100%',
          borderRadius: '6px',
          backgroundColor: '#fafafa',
        }}
        placeholder={list && list.length > 0 ? '' : '搜索菜单'}
        value={value}
        onChange={handleSearch}
        clearOnCancel
        onClear={handlerClear}
        onFocus={() => {
          setStatus(true)
          navigate(`${urlSearch}`)
        }}
        onBlur={() => {
          setStatus(false)
        }}
      />
      <div className="scroll-box" ref={contentBox}>
        <div ref={parent}>
          {list &&
            list.map((item: { menu_name: string }) => (
              <span key={item.menu_name}>{item.menu_name}</span>
            ))}
        </div>
        <div ref={parentTwo} />
      </div>
    </ContentArea>
  )
}

export default React.memo(RevolvingDoor)

在styled.ts中

import styled from 'styled-components'

const ContentArea = styled.div<{
  value: boolean
}>`
  .ant-search-input-icon {
    color: rgba(0, 0, 0, 0.85);
  }
  position: relative;
  flex: 1;
  .scroll-box {
    position: absolute;
    top: 0px;
    left: 30px;
    z-index: ${(p: { value: boolean }) => (p.value ? -1 : 2)};
    width: 204px;
    height: 32px;
    overflow: hidden;
    line-height: 32px;
    pointer-events: none;
    div {
      margin: 0;
      span {
        display: block;
        color: #bfbfbf;
        font-size: 14px;
      }
    }
  }
`
export { ContentArea }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值