查询组件:
import React, { useState, useEffect } from 'react' import Taro from '@tarojs/taro' import classnames from 'classnames' import { map, includes } from 'lodash' import { View, Text, Input, RichText, ScrollView } from '@tarojs/components' import api from '@services/api' import app from '@services/request' import { keywordcolorful } from '@utils/index' import storage from '@utils/storage' import useNavData from '@hooks/useNavData' import NavBar from '@components/navbar/index' import './index.scss' export interface ISearchOption { type: string name: string } interface ISearchProps { searchTitle: string searchOption: any[] searchRemark?: string searchUrl: string onItemClick: (any, ISearchOption) => void } const Search = (props: ISearchProps) => { const isMultiply = props.searchOption.length > 1 const INIT_OPTION = props.searchOption[0] const INIT_HISTORIES = storage.getItem('histories', `search_${INIT_OPTION.name}`) || [] const { contentHeight } = useNavData() const [clear, setClear] = useState(false) const [hotList, setHotList] = useState([]) const [matcheList, setMatcheList] = useState([]) const [searchValue, setSearchValue] = useState("") const [searchHistories, setSearchHistories] = useState(INIT_HISTORIES) const [option, setOption] = useState<ISearchOption>(INIT_OPTION) const [showOption, setShowOption] = useState<boolean>(false) useEffect(() => { app.request({ url: api.getSearchHotList }, { isMock: true, loading: false }) .then((result: any) => { setHotList(result || []) }) }, []) Taro.setNavigationBarColor({ frontColor: '#000000', backgroundColor: '#f7f7f7', animation: { duration: 400, timingFunc: 'easeIn' } }) const handleItemClick = (item: any) => { let ids = map(searchHistories, 'id') if (!includes(ids, item.id)) { searchHistories.push(item) } storage.setItem('histories', searchHistories, `search_${option.name}`) props.onItemClick(item, option) } const handleInput = (event) => { let keyValue = event.currentTarget.value if (keyValue) { setClear(true) } else { setClear(false) } setSearchValue(keyValue) updateKeyList(keyValue) } const updateKeyList = (keyValue) => { app.request({ url: props.searchUrl, data: { kw: keyValue } }, { isMock: true, loading: false }) .then((result: any) => { setMatcheList(result || []) }) } const clearSearchValue = () => { setClear(false) setSearchValue("") } const handleCancel = () => { Taro.navigateBack() } const handleClearClick = () => { storage.clear(`search_${option.name}`) setSearchHistories([]) } const handleSwitchOption = (item: ISearchOption) => { if (item.type === option.type) { return } setOption(item) setShowOption(false) setSearchHistories(storage.getItem('histories', `search_${item.name}`) || []) } const renderSearchKeys = (title, className, keyList, allowClear = false) => { if (keyList && keyList.length > 0) { return ( <View className={classnames("search-record", className)}> <View className="search-header clearfix"> <Text className="title">{title}</Text> {allowClear && <Text className="iconfont iconclear1" onClick={handleClearClick}></Text>} </View> <View className="search-list clearfix"> {keyList.map((item: any) => { return <Text key={item.id} className="item" onClick={() => handleItemClick(item)} >{item.name} </Text> })} </View> </View> ) } } const renderSearOption = () => { return props.searchOption.map((item: ISearchOption, index: number) => ( <View key={index} className={classnames('options-item', option.type === item.type && 'actived')} onClick={() => handleSwitchOption(item)} >{item.name} </View> )) } return ( <View className="search"> <NavBar title={props.searchTitle} back={true} backgroundColor="#f7f7f7" color="#000" /> <View className="search-wrapper clearfix"> <View className="search-content"> <View className="search-label" onClick={() => setShowOption(!showOption)}> <Text className="search-label-text">{option.name}</Text> <Text className={classnames('iconfont', isMultiply ? 'iconarrow-down-bold' : 'iconsearch')}></Text> </View> <Input className="search-input" placeholder={props.searchRemark} onInput={handleInput} value={searchValue} autoFocus></Input> {clear && <Text className="iconfont iconclear" onClick={clearSearchValue}></Text>} {showOption && <View className="search-options"> <View className="triangle-up"> <Text className="cover"></Text> </View> {renderSearOption()} </View> } </View> <Text className="search-cancel" onClick={handleCancel}>取消</Text> </View> <ScrollView scrollY style={{ maxHeight: contentHeight - 50 }}> {searchValue ? <View className="search-matches"> { matcheList.map((item: any, index: number) => { return ( <View className="match-item" key={index} onClick={() => handleItemClick(item)}> <RichText nodes={keywordcolorful(item.name, searchValue)} /> <View className="address">{item.address}</View> </View> ) }) } </View> : <View className="search-category"> {renderSearchKeys('搜索历史', 'search-history', searchHistories, true)} {renderSearchKeys('热门搜索', 'search-hot', hotList)} </View> } </ScrollView> </View> ) } export default Search
使用:
import React from 'react' import Taro from '@tarojs/taro' import { View } from '@tarojs/components' import api from '@services/api' import Search, { ISearchOption } from '@components/search' import './index.scss' const HouseSearch = () => { const searchOption: ISearchOption[] = [ { type: "newhouse", name: "新房" }, { type: "esf", name: "二手房" } ] const handleItemClick = (item: any, option: ISearchOption) => { Taro.navigateTo({ url: `/pages/${option.type}/index?id=${item.id}&name=${item.name}` }) } return ( <View className="house-search"> <Search searchTitle="搜索" searchOption={searchOption} onItemClick={handleItemClick} searchRemark="请输入楼盘名称或地址" searchUrl={api.getSearchKeyList} ></Search> </View> ) } export default HouseSearch