0


select三级联动选择—基于layui的select

文章目录

Select三级联动选择—基于Layui

Layui是一套开源的 Web UI 组件库。layui采用自身极简的模块化规范,并遵循原生 HTML/CSS/JS 的开发模式,极易上手,开箱即用。是前后端初学者必不可少的学习神器。(ps:对于笔者这种前端页面写的很丑的人来说简直是福音啊!)

使用的方式主要有两种,一种直接下载layui的源码使用;一种是使用在线引用(即通过非下载的方式进行使用)。笔者更喜欢通过下载源码来使用。

附上Layui的网址:https://layui.org.cn/index.html

在这里插入图片描述

一、需求

需求是这样的,自己在写一个商城项目的时候,涉及到了供应商提交的表单。表单中有个供应商地址选择运用到了select选择框。以前刚学html的时候,也写过很多次的选择框。但是选择框中的内容选项option都已经是固定的了。如下所示:

<selectname="pets"id="pet-select"><optionvalue="">--Please choose an option--</option><optionvalue="dog">Dog</option><optionvalue="cat">Cat</option><optionvalue="hamster">Hamster</option><optionvalue="parrot">Parrot</option><optionvalue="spider">Spider</option><optionvalue="goldfish">Goldfish</option></select><!--在select选择框中已经提前预写了option选项,可以直接选择。但是这种选择的方式有一个非常明显的弊端,如果待选项数目很多,挨个去写很浪费时间而且代码还很臃肿,不美观。-->

这次项目的需求是需要联动选择国内所有的省市县(区)三级,如果以最原始的写法,那无疑是灾难。因此我尝试换一种方式,即从数据库中读取选择框的内容,并且多个选择框之间是联动选择的(即如果选择了广东省,那么你将选不到杭州市,只能从广东省的所有地级市中选择)。

二、分析及前端代码

首先是需要将整个供应商需要提交的表单书写,形成一个大致的轮廓。

要从后台的数据库中读取到数据,就需要前后端交互,因此在本次项目中三级联动的实现主要依靠jQuery来实现。

笔者都将jQuery和layui的源码下载下来,之后直接附在项目中。

本文主要针对三个选择框的联动选择,因此将其他内容进行了简化。代码附上

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>供应商登记</title><scripttype="text/javascript"src="../../../static/jquery-3.6.3.min.js"></script><linkrel="stylesheet"href="../../../static/layui/css/layui.css"><scripttype="text/javascript"src="../../../static/layui/layui.js"></script><scripttype="text/javascript"src="../../../static/js/registerVendors.js"></script></head><bodyonload="load()"><divclass="layui-fluid"><divclass="layui-row"><h1style="text-align: center">供应商</h1></div><formclass="layui-form"action="/registerVendors"method="get"><divclass="layui-form-item"><labelclass="layui-form-label">注册地址</label><divclass="layui-input-block"><selectid="province"name="vendorsProvince"lay-filter="changeProvince"></select><selectid="city"name="vendorsCity"lay-filter="changeCity"></select><selectid="region"name="vendorsRegion"></select></div></div></form></div></body></html>

在这个编码中注册地址使用三个select选择框进行表示。**

lay-filter

起到类似选择器的作用。**

实现的效果是:当使用者选中了省,那么系统才会加载地级市,选择了地级市才会加载区。如果有人有意先跳过选择,那么将无法选择任何内容。这样保证了选择的正确性以及简便性。

这样的实现需要搭配js才能实现响应式加载的效果

layui.use('form',function(){
    form = layui.form;loadCities();loadRegions();})
layui.use('layer',function(){
     layer=layui.layer;})//页面开始就加载省份functionload(){$().ready(function(){
        $.ajax({type:'post',url:'/getProvince',cache:false,async:true,dataType:'json',success(data){
                console.log(data)let selectProvince= document.getElementById("province");
                selectProvince.add(newOption("请选择对应的省份","0"))let option=null;for(let i =0; i < data.length; i++){
                  option =newOption(data[i].provinceName,data[i].provinceId);

                    selectProvince.add(option)}
                console.log("添加完毕!")
                form.render('select')
                form.render();// $("#province").html(options);},error(){
                console.log("进入了error")
                layer.confirm('省份加载暂时出现了点问题!',{icon:2,btn:['好的,回主页吧','去登陆页'],title:'错误信息'},function(){
                        window.location.href ='/main'},function(){
                        window.location.href ='/login'})}})})}//选择城市functionloadCities(){
    form.on('select(changeProvince)',function(){$("#city").html('')//alert("改变方法执行了!")let provinceId =$("#province option:selected").val();//let provinceId = data.val();
        $.ajax({type:'post',url:'/getCities',cache:false,async:true,data:{"provinceId": provinceId},//  contentType:"application/json",dataType:'json',success(data){
                console.log(data)let selectCities = document.getElementById("city");
                selectCities.add(newOption("请选择对应的城市","0"));let option =null;for(let i =0; i < data.length; i++){
                    option =newOption(data[i].cityName, data[i].cityId);
                    selectCities.add(option)}
                form.render('select')
                form.render();},error(){
                console.log("进入了error")
                layer.confirm('市加载暂时出现了点问题!',{icon:2,btn:['好的,回主页吧','去登陆页'],title:'错误信息'},function(){
                        window.location.href ='/main'},function(){
                        window.location.href ='/login'})}})})}//选择地区functionloadRegions(){
    form.on('select(changeCity)',function(){$("#region").html('');let cityId=$("#city option:selected").val();
        $.ajax({type:'post',url:'/getRegions',cache:false,async:true,data:{"cityId":cityId},dataType:'json',success(data){let selectRegions = document.getElementById("region");
                selectRegions.add(newOption("请选择对应的区",0))let option=nullfor(let i=0;i<data.length;i++){
                    option=newOption(data[i].regionName,data[i].regionId);
                    selectRegions.add(option);}
                form.render('select')
                form.render();},error(){
                console.log("进入了error")
                layer.confirm('区加载暂时出现了点问题!',{icon:2,btn:['好的,回主页吧','去登陆页'],title:'错误信息'},function(){
                        window.location.href ='/main'},function(){
                        window.location.href ='/login'})}})})}

实现的方式:

  • 省份加载

首先页面一加载,通过

onload=load()

进行加载每个省的具体名称。即省份的加载伴随着页面的载入进行。加载的具体省份的内容是通过jQuery的ajax方法从后端的数据库获取的。后端返回的结果是json格式的(dataType:json)。

当后台成功返回数据的时候,就会进入success函数,data即为后端返回的实际结果。再对后端返回的json结果进行具体分析,笔者返回的格式为{xxxId:xxxName}。

最后通过option对象,加入到select选择框之中,最后需要着重注意的是 form.render(‘select’),加载完成后需要进行刷新。这是个巨坑。

  • 地级市加载

省份加载完毕之后,地级市的加载与省份的加载不同,我们需要获取到省份加载之后,使用者选取的省份的具体id并将其传到后端,后端根据省份的id选择出对应的所有地级市。

此项功能需要使用到

form.on()

函数,该函数内的第一个参数是起到类似选择器的作用,一旦省份被选中,就会立即执行第二参数,即对应的函数进行地级市的加载,仍旧是通过jQuery的ajax方法进行异步请求。返回的格式依旧是json格式,

最后通过将设置的option对象实现select选择框。

需要注意的是

 $("#city").html('')

。该项是起到初始化的作用,如果后续出现选择错了省份需要改正,则会将之前选择的内容完全清除掉,这是十分重要的。

  • 区(县)的加载

区(县)的加载与地级市的加载类似,不过其是通过对应地级市的id来获取对应地级市下所有的区(县)名。操作与地级市加载类似。

三、后端实现

在这次的项目中,笔者的后端采用的是SpringBoot框架。通过mvc模式来实现选择框具体内容的加载。

  • 实体类设计
@Entity@Data@AllArgsConstructor@NoArgsConstructorpublicclassProvince{@Column(name ="province_id")privateString provinceId;@Column(name ="province_name")privateString provinceName;}@Entity@Data@AllArgsConstructor@NoArgsConstructorpublicclassCity{@Column(name ="city_id")privateString cityId;@Column(name ="city_name")privateString cityName;}@Data@Entity@AllArgsConstructor@NoArgsConstructorpublicclassRegion{@Column(name ="region_id")privateString regionId;@Column(name ="region_name")privateString regionName;}

三者都使用了lombok进行了setter和getter方法以及构造方法的加载。

@Column

的作用是将实体类的字段与数据库表中的字段进行事先的匹配,防止后面出现不匹配报错的情况。

  • 数据库设计

本次数据库设计比较简单,只设计了一张表,并随意填充了一些数据进行测试。

CREATE TABLE IF NOT EXISTS address(
        province_id  VARCHAR(20)  NOT NULL  ,
        province_name VARCHAR(20) NOT NULL ,
        city_id VARCHAR(20) NOT NULL ,
        city_name VARCHAR(20) NOT NULL ,
        region_id VARCHAR(20) NOT NULL  PRIMARY KEY ,
        region_name VARCHAR(20) NOT NULL

    );
    
-- 手动添加一些数据
INSERT INTO address VALUES ('p1','北京','c1','北京','r1','房山区');
INSERT INTO address VALUES ('p1','北京','c1','北京','r2','通州区');
INSERT INTO address VALUES ('p1','北京','c1','北京','r3','丰台区');
INSERT INTO address VALUES ('p1','北京','c1','北京','r4','东城区');
INSERT INTO address VALUES ('p1','北京','c1','北京','r5','西城区');
INSERT INTO address VALUES ('p1','北京','c1','北京','r6','崇文区');
INSERT INTO address VALUES ('p1','北京','c1','北京','r7','朝阳区');
INSERT INTO address VALUES ('p1','北京','c1','北京','r8','海淀区');
INSERT INTO address VALUES ('p2','上海','c1','上海','p2r1','嘉定区');

INSERT INTO address VALUES ('p2','上海','p2c1','上海','p2r3','徐汇区');
INSERT INTO address VALUES ('p2','上海','p2c1','上海','p2r4','长宁区');
INSERT INTO address VALUES ('p2','上海','p2c1','上海','p2r5','静安区');
INSERT INTO address VALUES ('p2','上海','p2c1','上海','p2r6','普陀区');
INSERT INTO address VALUES ('p2','上海','p2c1','上海','p2r7','宝山区');
INSERT INTO address VALUES ('p2','上海','p2c1','上海','p2r8','青浦区');
INSERT INTO address VALUES ('p2','上海','p2c1','上海','p2r9','奉贤区');
INSERT INTO address VALUES ('p2','上海','p2c1','上海','p2r10','金山区');

INSERT INTO address VALUES ('P3','天津','p3c1','天津','p3r1','滨海新区');
INSERT INTO address VALUES ('P3','天津','p3c1','天津','p3r2','宁河区');
INSERT INTO address VALUES ('P3','天津','p3c1','天津','p3r3','和平区');
INSERT INTO address VALUES ('P3','天津','p3c1','天津','p3r4','河北区');
INSERT INTO address VALUES ('P3','天津','p3c1','天津','p3r5','河东区');
INSERT INTO address VALUES ('P3','天津','p3c1','天津','p3r6','河西区');
INSERT INTO address VALUES ('P3','天津','p3c1','天津','p3r7','南开区');
INSERT INTO address VALUES ('P3','天津','p3c1','天津','p3r8','武清区');
INSERT INTO address VALUES ('P3','天津','p3c1','天津','p3r9','静海区');
INSERT INTO address VALUES ('P3','天津','p3c1','天津','p3r10','蓟州区');

数据库中将 region_id设置为主键是因为在加载数据的时候,省和市都有可能重复,只有区名在本张表是唯一的。

  • 持久化层

java代码实现

@Mapper@RepositorypublicinterfaceLoadAddressData{/**
     * @return
     */List<Province>getProvince();/**
     *
     * @param provinceId 省份的id值
     * @return 返回对应省份id所对应的所有城市
     */List<City>getCities(@Param("provinceId")String provinceId);/**
     *
     * @param cityId 对应城市的id
     * @return 返回对应id城市的所有区
     */List<Region>getRegions(@Param("cityId")String cityId);}

三个方法返回的结果都是list形式的内容,list里的内容都是一个个对象

通过mybatis的映射文件实现

<!DOCTYPEmapperPUBLIC"-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mappernamespace="com.example.mail.dao.vendorsDao.LoadAddressData"><!--命名空间--><resultMapid="resultMapProvince"type="com.example.mail.entity.Province"><resultcolumn="province_id"property="provinceId"/><resultcolumn="province_name"property="provinceName"/></resultMap><!--resultMap的主要作用是将结果集映射到具体的数据库字段名称上去--><selectid="getProvince"resultMap="resultMapProvince"resultType="list">
        SELECT DISTINCT province_id,province_name FROM address;
    </select><!--执行查询所有省份的方法--><!--根据省份id查询所有的城市--><resultMapid="resultMapCities"type="com.example.mail.entity.City"><resultcolumn="city_id"property="cityId"/><resultcolumn="city_name"property="cityName"/><resultcolumn="province_id"property="provinceId"/></resultMap><selectid="getCities"parameterType="java.lang.String"resultType="list"resultMap="resultMapCities">
           SELECT DISTINCT city_id,city_name FROM address WHERE province_id=#{provinceId};
    </select><!--根据城市的id查询所有区(县)--><resultMapid="resultMapRegions"type="com.example.mail.entity.Region"><resultcolumn="city_id"property="cityId"/><resultcolumn="region_id"property="regionId"/><resultcolumn="region_name"property="regionName"/></resultMap><selectid="getRegions"parameterType="java.lang.String"resultType="list"resultMap="resultMapRegions">
        SELECT DISTINCT region_id,region_name FROM address WHERE city_id=#{cityId};
    </select></mapper>
  • 服务层代码实现
publicinterfaceLoadAddressDataService{/**
    *获取所有的省份
    */List<Province>getProvince();/**
    *
    * @param provinceId 省份的id值
    * @return 返回对应省份id所对应的所有城市
    */List<City>getCities(@Param("provinceId")String provinceId);/**
    *
    * @param cityId 对应城市的id
    * @return 返回对应id城市的所有区
    */List<Region>getRegions(@Param("cityId")String cityId);}
@ServicepublicclassLoadAddressDataServiceImplimplementsLoadAddressDataService{@AutowiredprivateLoadAddressData loadAddressData;/**
    *获取所有的省份
    */@OverridepublicList<Province>getProvince(){return loadAddressData.getProvince();}/**
     * @param provinceId 省份的id值
     * @return 返回对应省份id所对应的所有城市
     */@OverridepublicList<City>getCities(String provinceId){return loadAddressData.getCities(provinceId);}/**
     * @param cityId 对应城市的id
     * @return 返回对应id城市的所有区
     */@OverridepublicList<Region>getRegions(String cityId){return loadAddressData.getRegions(cityId);}}
  • 控制层实现
@ControllerpublicclassLoadAddressDataController{@AutowiredprivateLoadAddressDataService loadAddressDataService;@RequestMapping("/getProvince")@ResponseBodypublicStringgetProvince(){List<Province> provinces = loadAddressDataService.getProvince();return JSON.toJSONString(provinces);}@RequestMapping("/getCities")@ResponseBodypublicStringgetCities(String provinceId){System.out.println("获取到的省份id为"+provinceId);List<City> cities = loadAddressDataService.getCities(provinceId);return JSON.toJSONString(cities);}@RequestMapping("/getRegions")@ResponseBodypublicStringgetRegions(String cityId){System.out.println("获取到城市id为"+cityId);List<Region> regions = loadAddressDataService.getRegions(cityId);return JSON.toJSONString(regions);}}

可以看到在控制层代码中最后返回的都是json格式的字符串,这是因为前端js文件中三个ajax请求设置的

dataType

,均为json

  • 实现的效果

选择省份

在这里插入图片描述


如果绕过选择城市,则无法继续选择区县

在这里插入图片描述


最后选择区县

在这里插入图片描述

到此over!

在这里插入图片描述

标签: layui 前端 javascript

本文转载自: https://blog.csdn.net/qq_50824019/article/details/130062326
版权归原作者 Synchronized_b 所有, 如有侵权,请联系我们删除。

“select三级联动选择—基于layui的select”的评论:

还没有评论