【React】从零搭建一个纯前端起始页浏览器插件(二):搜索框关键词推荐(搜索建议)

系列文章目录

【React】从零搭建一个纯前端起始页浏览器插件(一):介绍

【React】从零搭建一个纯前端起始页浏览器插件(二):搜索框关键词推荐(搜索建议)


目录

系列文章目录

前言

一、搜索建议是如何生成的?

1.记录当前值

2.获取搜索建议

二、关键问题

总结


前言

作为一个起始页,最重要的地功能那就是搜索,一个完整搜索功能就包括以下几个小点:输入关键词智能推荐搜索建议、键盘选择回车搜索、历史记录以及搜索引擎切换,其中最难的点就是输入关键词反馈搜索建议,这也是今天分享讲解的内容。


一、搜索建议是如何生成的?

        当我们在使用百度等搜索引擎时,在输入框输入任意字符,它就会在搜索框下方生成搜索建议,那么这其实是随着你输入,网页根据你输入的当前值向服务器动态的请求建议形成的结果。也就是说这其实就是一个记录当前输入值再不断地发送请求地过程。

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" />
    )
}

        可以看到,这里通过valueonChange与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就可以解决。很可惜,在这个项目当中,我并没有实现它。


总结

        本文主要和大家分享讲解了如何获取搜索建议,以及其中的一些关键性的问题,可能我这并不是最优解(估计一定不是,毕竟我才学一会>_<),欢迎大家在评论区里批评指正^ ^


版权声明:本文为Howie_Why原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。