搜索栏实现联想功能

南山隐士 2022年06月25日 20 0

==代码仅供参考,您可以直接看小提示有大概思路就好了!==

今天遇到关于搜索栏的需求,主要有以下几个需求:

  1. 页面渲染完毕的时候,需要显示热搜
  2. 如果有搜过的记录,需要展示出来
  3. 在输入栏中搜索对应的文本,然后联想出对应的内容以便搜索
  4. 当搜索了东西,都要进行保存,下次需要显示出来
  5. 如果没有输入对应的搜索内容,默认搜索热门内容
  6. 可以对历史记录进行消除

以下是效果图

search.gif

首先,我们需要明确我们需要改变的数据

state = {
	data: {}, // 这里就是热搜数据
	history: [], // 历史数据
	datalist: [], // 这是联想到的数据
	searchName: ''// 搜索输入的内容
};

:::tip 小提示
明确有哪些数据需要获取和改变的
:::

首先,页面渲染完毕,我们需要发送ajax请求,来获得热搜相应数据,在对其进行遍历

async componentDidMount() {
	//得到存储的历史记录
	const history = getItem();
	//历史记录是否存在
	if (Array.isArray(history)) {
		this.setState({ history });
	}
	//请求热搜数据
	const result = await reqSearchInit();
	if (result && result.code === '200') {
		this.setState({ data: result.data });
	}
}

:::tip 小提示
我们要想到,当页面加载完毕的时候,我们要显示的是,热搜的内容要显示出来,所以我们要请求热搜的相应数据,还有历史记录的读取,所以就要读取我浏览器的cookie或者storage等,具体看您怎么设置
:::

联想内容的实现

给我的input标签绑定onInput事件,一旦我的搜索栏发生了变化,我就发送ajax请求,然后提取联想到的内容

封装一个防抖函数在一个index文件中

export const debounce = function (fn, time) {
  let timer = null;
  console.log(1)
  return () => {
    if (timer) clearTimeout(timer);
    timer = setTimeout(() => {
      fn()
      timer = null;
    }, time)
  }
}

当页面加载完毕的时候,在componentDidMount中执行我的防抖函数,并且赋值到实例的fn中

this.fn = debounce(async () => {
	const result = await reqSearchAutoComplete(this.state.searchName);
	if (result.code === '200') {
		console.log(result)
		this.setState({
			datalist: result.data
		});
	}
}, 200)

当我的表单发生改变的时候,我就会触发这个函数来发送请求

// 监视输入框内容的
handleChange = e => {
	// console.log(e.target)
	// e.persist()
	let searchName = e.target.value.trim()
	this.setState({ searchName });
	this.fn() // 这个函数就是我防抖函数返回的回调函数
}

:::tip 小提示
需要实现联想,就是监听我的input事件,发生改变的话,把我对应的value值做为参,发送请求,请求联想的对应数据,然后对其进行遍历展示,当然我们需要通过防抖或者节流来对其进行优化,减少发送请求的次数
:::

保存我的历史记录

创建storage对应事件,封装到一个文件中

const HISTORY_KEY = 'HISTORY_KEY';
const HISTORY_TIME = 'HISTORY_TIME';
// 过期时间
const EXPIRES_IN = 1000 * 3600 * 24 * 3;
export const setItem = function (data) {
  // 储存历史记录第一次创建历史纪律的时间
  localStorage.setItem(HISTORY_TIME, Date.now());
  // 储存历史记录
  localStorage.setItem(HISTORY_KEY, JSON.stringify(data));
};
export const getItem = function () {
  const startTime = localStorage.getItem(HISTORY_TIME);
  if (Date.now() - startTime > EXPIRES_IN) {
    // 过期了~ 清除用户信息
    removeItem();
    return [];
  }
  // 没有过期
  return JSON.parse(localStorage.getItem(HISTORY_KEY))
}
export const removeItem = function () {
  localStorage.removeItem(HISTORY_KEY);
  localStorage.removeItem(HISTORY_TIME);
};

关于storage的使用,请移步至

判定我是否有输入对应的内容,没有的话就以默认的placeholader为准

searchProduct = async e => {
	if (e.keyCode === 13) {
		const { searchName, data: { defaultKeyword: { keyword, schemeUrl } } } = this.state;
		let data = {};
		//名字存在则搜名字
		//名字不存在则搜索热搜默认项
		if (!searchName) {
			data = {
				keyword,
				schemeUrl,
				title: 'userhand'
			};
		} else {
			data = {
				keyword: searchName,
				schemeUrl: null,
				title: 'userhand'
			};
		}
		this.setHistory(data);
	}
};

//设置历史记录,
	setHistory = data => {
		const { history } = this.state;
		//找出history里重复的值删除
		// const newHistory = [{ ...data, title: 'history' }, ...history];
		const newHistory = this.removeReapeat([{ ...data, title: 'history' }, ...history]).slice(0, 5);
		setItem(newHistory);
		this.setState({
			history: newHistory,
			searchName: '',
			datalist: []
		});
		//	this.gotoPage(data.schemeUrl, data.keyword, data.title)();
	};

//数组去重
	removeReapeat = arr => {
		const result = arr.reduce(
			(prev, curr) => {
				if (prev.findIndex(item => item.keyword === curr.keyword) === -1) return [...prev, curr];
				else return prev;
			},
			[arr[0]]
		);
		return result;
	};

==当我按下回车的时候,我需要拿到我的value值,然后拿到对应都是数据,一般数据有url,value,然后保存到我的历史记录中,而保存历史记录的时候,需要限制只能保存多少个值,不能一直保存,并且最新的值,放到最前面,可以通过在一个数组中添加一个值,然后后面就遍历展示之前的值,然后截取前几个值即可,如果在输入的时候,发现输入的值,跟后一个值是一样的话,可以使用findIndex来查找,并且最后reduce展示==

==我们可以看到效果图,有历史记录,有热门搜索,我们可以定义一个变量,来确定是热门还是历史记录,然后定义一个方法通过这个变量来遍历展示不同的内容==

Last Updated: 2022/06/25 19:17:20
Ant Design自定义组件样式 你需要知道的Redux知识