手搭手Ajax实现搜索地址自动补全功能

输入单词后,自动提示出要搜索的信息,点击某个内容后,自动补全至搜索框。

比如:

如何实现搜索自动补全功能

  1. 键盘事件:keyup按键弹起事件
  2. 发送ajax请求,请求中提交用户输入的搜索内容,后端接收内容后,模糊查询,返回结果list<*>,
  3. 查询结果封装json格式的字符串后,将json字符串响应到前端,
  4. 前端接收,动态展示

环境介绍

|--------------|-------------------------------|
| 技术栈 | springboot+mybatis-plus+mysql |
| 软件 | 版本 |
| mysql | 8 |
| IDEA | IntelliJ IDEA 2022.2.1 |
| JDK | 1.8 |
| Spring Boot | 2.7.13 |
| mybatis-plus | 3.5.3.2 |

pom.xml

复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.15</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>ajaxDemo01</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>ajaxDemo01</name>
    <description>ajaxDemo01</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>2.0.32</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.3.2</version>
        </dependency>
        <dependency>
            <groupId>p6spy</groupId>
            <artifactId>p6spy</artifactId>
            <version>3.9.1</version>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.15</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
            <version>3.5.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

application.yml配置文件

复制代码
spring:
  datasource:
#    username: root
#    password: 111111
#    url: jdbc:p6spy:mysql://xxx.xxx.xxx.136:3306/sys?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8
#    driver-class-name: com.p6spy.engine.spy.P6SpyDriver
    dynamic:
      primary: sys #设置默认的数据源或者数据源组,默认值即为master
      strict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
      datasource:
        sys:
          username: root
          password: 111111
          url: jdbc:p6spy:mysql://xxx.xxx.xxx.136:3306/sys?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8
          driver-class-name: com.p6spy.engine.spy.P6SpyDriver
#          driver-class-name: com.mysql.jdbc.Driver
        wms:
          url: jdbc:p6spy:mysql://xxx.xxx.xxx.136:3306/Wms?useUnicode=true&characterEncoding=UTF-8
          username: root
          password: 111111
          driver-class-name: com.p6spy.engine.spy.P6SpyDriver
#          driver-class-name: com.mysql.jdbc.Driver
        sys2:
          username: root
          password: 111111
          url: jdbc:p6spy:mysql://127.0.0.1:3306/sys?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8
          driver-class-name: com.p6spy.engine.spy.P6SpyDriver

server:
  port: 8083

mybatis-plus:
  configuration:
    #输出日志
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    #配置映射规则
    map-underscore-to-camel-case: true #表示支持下划线到驼蜂的映射
    #隐藏mybatis图标
  global-config:
    banner: false
    db-config:
      logic-delete-field: status
      logic-not-delete-value: 1
      logic-delete-value: 0
#
#mybatis:
#  mapper-locations=classpath: com/example/dao/*.xml

数据库表

前端页面

复制代码
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>实现搜索地址自动补全功能</title>
    <style>
        .userInput{
            width: 300px;
            height: 25px;
            font-size: 20px;
            padding-left: 8px;
        }
        .mouse_color{
            background-color: antiquewhite;
        }
        .showData{
            width: 383px;
            font-size: 20px;
            border: 1px solid lightgray;
        /*    隐藏*/
            display: none;

        }
        .showData p {
            margin-top: 0px;
        }
        /*移动到上面改变背景颜色,并且变成小手*/
        .showData p:hover {
            cursor: pointer;
            background-color: antiquewhite;
            border: 1px  solid lightgray ;
        }

    </style>
</head>
<body>
<script type="text/javascript" src="../js/jquery-3.4.1.js"></script>
搜索地址: <input type="text" class="userInput" id="InputEnter">
<div class="showData" id="addressData">
<!--    <p>广州市增城区东湖路增城东湖公园</p>
        <p>广州市增城区广汕公路江山时代花园</p>
        <p>广州市花都区王子山路</p>
        <p>广东省广州市从化江埔街锦二村</p>
        <p>广东省深圳市莲花山</p>
        <p>广东省深圳市罗湖口岸</p>
        <p>广东省深圳市深圳机场</p>
        <p>广州市增城区东湖路增城东湖公园</p>
        <p>广西壮族自治区桂林市象山区</p>
        <p>广西壮族自治区南宁市上林县</p>
        <p>广西壮族自治区南宁市横县</p>
        <p>广西壮族自治区南宁市青秀区</p>
        <p>海南省三亚市南山文化旅游区</p>
        <p>海南省海口市美兰区</p>
        <p>海南省藏族自治州</p>
        <p>海南省三亚市崖州区</p>-->
</div>

<script type="text/javascript">
    window.onload = function () {
        document.getElementById("InputEnter").onkeyup = function () {
            // console.log(this.value)
            if (this.value!=null &&  this.value!=""){
                document.getElementById("addressData").style.display= "none";
            }
                $.ajax({
                    url: "/"+this.value+"/Address",
                    type: "GET",
                    dataType: "JSON",
                    success: function (json){
                        //清空原来的数据
                        $("#addressData").empty();
                        let list = json;
                        let html="";
                        for (let i = 0; i < list.length; i++){
                            console.log(list[i].address)
                            html +="<p onclick='SetInputValue(\""+list[i].address+"\")'>"+list[i].address+"</p>"
                        }
                        document.getElementById("addressData").innerHTML = html;
                        document.getElementById("addressData").style.display= "block";
                    },
                    error: function (xhr){
                        document.getElementById("addressData").innerHTML = "没有搜索到该地址";
                    }
                });
        }
    }
    //被点击后将内容设置到搜索框
    function SetInputValue(address) {
        document.getElementById("InputEnter").value = address
        document.getElementById("addressData").style.display= "none"
    }
</script>
</body>
</html>

后端实现

实体类

复制代码
@TableName(value ="t_address")
@Data
public class TAddress implements Serializable {
    /**
     * 
     */
    @TableId(type = IdType.AUTO)
    private Integer id;

    /**
     * 
     */
    private String address;

    @TableField(exist = false)
    private static final long serialVersionUID = 1L;
}

mapper(dao层)

复制代码
@Mapper
public interface TAddressMapper extends BaseMapper<TAddress> {
    List<TAddress> getByAddresses(@Param("Data") String data);
}

service

复制代码
public interface TAddressService extends IService<TAddress> {
    List<TAddress> getAddresses(String data);
}

serviceimpl

复制代码
@Service
@DS("sys2")
public class TAddressServiceImpl extends ServiceImpl<TAddressMapper, TAddress>
    implements TAddressService{

    @Autowired
    private TAddressMapper tAddressMapper;

    @Override
    public List<TAddress> getAddresses(String data) {
        return tAddressMapper.getByAddresses(data);
    }
}

controller

复制代码
@Autowired
    private TAddressServiceImpl tAddressService;

@RequestMapping("/{Data}/Address")
@ResponseBody
public List<TAddress> Address(@PathVariable("Data") String data) {

    List<TAddress> allProvince = tAddressService.getAddresses(data);
    return allProvince;
}

测试类

复制代码
@Autowired
private TAddressServiceImpl tAddressService;
@Test
void addressTest(){
    List<TAddress> address = tAddressService.list();
    for (TAddress tAddress : address) {
        System.out.println(tAddress.toString());
    }
}

效果

原理基础,可略

Ajax即Asynchronous Javascript And XML(异步JavaScript和XML)在 2005年被Jesse James Garrett提出的新术语,用来描述一种使用现有技术集合的'新'方法,包括: HTML 或 XHTML, CSS, JavaScript, DOM, XML, XSLT, 以及最重要的XMLHttpRequest。使用Ajax技术网页应用能够快速地将增量更新呈现在用户界面上,而不需要重载(刷新)整个页面,这使得程序能够更快地回应用户的操作。

ajax基础

Xmlhttprequest对象是AJAX的核心对象,发送请求以及接收服务器数据的返回。

Xmlhttprequest对象,现代浏览器都是支持的,都内置了该对象。直接用即可。

XmlHttpRequest对象基本方法:

abort():停止发送当前请求

getAllResponseHeader():获取服务器的全部响应头

getResponseHeader("headerLabel"):根据响应头的名字,获取对应的响应头

open("method","URL","[,asycFlag[,"userName"[,password]]]"):建立与服务器URL的连接,并设置请求的方法,以及是否使用异步请求。如果远程服务需要用户名、密 码,则 提供对应的信息。

send(content):发送请求。其中content是请求参数

setRequestHeader("label","value"):在发送请求之前,先设置请求头

XMLHttpRequest对象的简单的属性:

onreadystatechange:该属性用于指定XMLHttpRequest对象状态改变时的事件处理函数。

readyState:该属性用于获取XMLHttpRequest对象处理状态

responseText:该属性用于获取服务器响应的XML文档对象

status:该属性是服务器返回的状态码,只有当服务器的响应已经完成时,才会有该状态码

statusText:该属性是服务器返回的状态文本信息,只有当服务器的响应已经完成时,才会有该状态文本信息。

XMLHttpRequest对象的readyState属性对应的状态值

0:请求未初始化

1:服务器连接已建立

2:请求已收到

3:正在处理请求

4:请求已完成且响应已就绪

复制代码
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="mydiv"></div>
<input type="button" value="hello ajax" id="helloAjax">
<script type="text/javascript">
  window.onload = function (){
    document.getElementById("helloAjax").onclick =function (){
        // console.log("发送ajax请求")
        //1、创建ajax黑心对象XMLHttpRequest
        var xhr =new XMLHttpRequest();
        //2、注册回调函数
        //该函数在XMLHttpRequestState状态值发生改变时被调用
        xhr.onreadystatechange = function () {
            //readyState是Ajax状态码
            /**
             * XMLHttpRequest对象的readyState属性对应的状态值
             * 0:请求未初始化
             * 1:服务器连接已建立
             * 2:请求已收到
             * 3:正在处理请求
             * 4:请求已完成且响应已就绪
             */
 
            console.log(xhr.readyState)
            // if (this.readyState == 4){
            //     console.log("响应结束")
            // }
            //status是http协议状态码
            console.log("http响应状态码"+this.status)
            if (this.status==404){
                alert("访问资源不存在")
            }
 
            if (this.status ==200){
                //将响应信息放到div图层中,渲染
                //innerHTML是javascript的元素属性,和ajax的XMLHttpRequest对象无关,innerText也是javascript的元素属性
                //innerHTML可以设置元素内部的HTML代码。
                document.getElementById("mydiv").innerHTML =this.responseText;
                document.getElementById("mydiv").innerText =this.responseText;
            }
 
        }
 
        //3、开启通道
        //open(method,url,async,user,psw)
        //method:请求方式,get,post
        //url:请求路径
        //async:true或false,true表示异步请求,false表示同步请求
        //user用户名
        //psw密码
 
        xhr.open("GET","/test01",true)
        //4、
 
        xhr.send()
    }
  }
 
</script>
</body>
</html>
相关推荐
passerby606138 分钟前
完成前端时间处理的另一块版图
前端·github·web components
掘了1 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅1 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅1 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅2 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment2 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅2 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊2 小时前
jwt介绍
前端
爱敲代码的小鱼2 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax
Cobyte2 小时前
AI全栈实战:使用 Python+LangChain+Vue3 构建一个 LLM 聊天应用
前端·后端·aigc