系列文章目录
【React】从零搭建一个纯前端起始页浏览器插件(一):介绍
【React】从零搭建一个纯前端起始页浏览器插件(二):搜索框关键词推荐(搜索建议)
目录
前言
作为一个起始页,最重要的地功能那就是搜索,一个完整搜索功能就包括以下几个小点:输入关键词智能推荐搜索建议、键盘选择回车搜索、历史记录以及搜索引擎切换,其中最难的点就是输入关键词反馈搜索建议,这也是今天分享讲解的内容。
一、搜索建议是如何生成的?
当我们在使用百度等搜索引擎时,在输入框输入任意字符,它就会在搜索框下方生成搜索建议,那么这其实是随着你输入,网页根据你输入的当前值向服务器动态的请求建议形成的结果。也就是说这其实就是一个记录当前输入值再不断地发送请求地过程。
1.记录当前值
要想时时地记录当前输入框地值,我们就需要利用到受控组件,我们这里利用react当中的函数组件+hook的形式来实现受控组件,具体代码如下:
function SearchNav(){
const [searchInputValue, setSearchInputValue] = useState('') //hook初始值为''
function searchInputValueChange (e) {
setSearchInputValue(e.target.value)
}
return(
<input className="Search-Input"
value={searchInputValue} //绑定hook
onChange={searchInputValueChange} //绑定change函数
type="text" />
)
}可以看到,这里通过value、onChange与hook绑定形成了一个受控组件,此时输入框内的值将与searchInputValue同步。
2.获取搜索建议
当我们有了值,下一步就是获取搜索建议了。我们在前面提到过,要想获取建议,就得与各个搜索引擎的服务器通信才能够获取(当然,如果你自己有联想词库,那就省去了这些麻烦)。这里我们首先给出一个链接,点击他就可以初步尝试以下搜索词的获取。结果如下:

这是从百度获取到的关于1的搜索建议。
由于涉及到跨域的问题,我们这里统一采取了JSONP的方式去获取数据,在实现上简单来说,就是通过在DOM中插入script标签来获取数据,这种方式适用于百度以及Bing搜索。具体代码如下:
import { makeAutoObservable, runInAction } from 'mobx'
import { v4 as uuid } from 'uuid'
class SearchNavStore {
constructor() {
makeAutoObservable(this)
window.howie.searchsug = { //JSONP结果临时存放位置初始化
res: [],
sugbaidu: function (json) {
this.res = []
this.res = json.s
},
sugbing: function (json) {
this.res = []
json.AS.Results.map(item => {
item.Suggests.map(item => {
this.res.push(item.Txt)
return 0
})
return 0
})
}
}
}
//搜索建议
suggest_search_prompt = []
//获取搜索建议
getSuggestSearchPrompt (value, engine) {
if (value === '') { //判断输入框是否为空
}
else {
if (engine === 'baidu') { //判断当前搜索引擎
let searchScript = document.createElement("script") //JSONP获取
searchScript.src = `https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=${value}&cb=window.howie.searchsug.sugbaidu`
document.body.appendChild(searchScript)
document.body.removeChild(searchScript)
}
else if (engine === 'bing' | engine === 'google') { //判断当前搜索引擎
let searchScript = document.createElement("script") JSONP获取
searchScript.src = `https://api.bing.com/qsonhs.aspx?type=cb&q=${value}&cb=window.howie.searchsug.sugbing`
document.body.appendChild(searchScript)
document.body.removeChild(searchScript)
}
setTimeout(() => { //延时处理结果
runInAction(() => {
this.suggest_search_prompt = []
window.howie.searchsug.res.map(item => {
let result = {
id: uuid(),
value: item
}
this.suggest_search_prompt.push(result)
return 0
})
})
}, 500)
}
}
二、关键问题
以上都是写在mobx当中的代码,其中关键部分有以下几个:
a. 由于JSONP的script标签是插入在DOM当中,那么处理函数也应当定义在全局,这样才可以被获取,也就是说,在获取JSONP之前,我们需要在window当中初始化一个处理函数以及数据存放点,此时JSONP的url就会为:
https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=搜索值&cb=window.函数b.延时转存数据,当你使用JSONP后立即将存放在window当中的数据取出时你会发现,数据并不存在。这是因为,网络请求数据是需要时间的,而且者远比代码执行速度要慢,所以这里我选择了延时500ms来读取数据做下一步处理;
c.跨域问题,由于之前打算直接做成网页,所以就产生了跨域问题,导致无法使用普通的请求方式获取搜索建议,这也是为什么代码当中google的搜索建议使用的是bing的建议,就是因为google的请求是不能通过JSONP绕过跨域问题的。但是,如果我们是开发插件,那么就可以利用背景网页,在背景网页当中发送请求,就不会再有跨域的限制,也不需要延时处理结果,只需要利用await就可以解决。很可惜,在这个项目当中,我并没有实现它。
总结
本文主要和大家分享讲解了如何获取搜索建议,以及其中的一些关键性的问题,可能我这并不是最优解(估计一定不是,毕竟我才学一会>_<),欢迎大家在评论区里批评指正^ ^