Ajax实现三级联动下拉菜单省市区(PHP+JavaScript)原生代码

由于最近开发的一个小项目需要用实现“Ajax三级联动下拉菜单+省市县”,我看网上有些人是直接把省市县直接放在一个JS文件的,直接用JS来调用的;还有一种是把省市县地区存在数据库中。

 

我选择用了“Ajax省市区三级联动+数据库”这种功能了,毕竟可以“添加、修改、删除”地区。最终的效果如下:

Ajax实现三级联动下拉菜单省市区

 

前提是你已经理解了:PHP + JavaScript AJAX 请求(原生)教程

 

一、数据库 建表

由于我用的是Mysql数据库,我就只写Mysql SQL语句了,其它的数据库按照此原理走即可!

简单说关明一下:为什么表需要有一个 level 字段?

这是因为方便好查询数据以及程序开发中所有的逻辑。如果是查询某个省下有多少市?某个市下有多少县?这个可以用 parent_id。如果想查询所有的市或所有的县?如果没有 level 字段就不好查询了。

 

area表

--
-- 表的结构 `area`
--
CREATE TABLE `area` (
  `id` bigint(20) NOT NULL PRIMARY KEY AUTO_INCREMENT,
  `name` varchar(28) NOT NULL COMMENT '地区名称,北京',
  `alias` varchar(28) NOT NULL COMMENT '地区别名,beijing',
  `parent_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '地区父ID',
  `level` bigint(20) NOT NULL COMMENT '层级,省=1,市=2,县=3'
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='地区表';

 

二、代码

这里代码包括原生:PHP代码、JavaScript代码(Ajax代码)

 

index.php

大家必须先懂一种思维,一般正常业务逻辑情况下,省份地区是我们第一时间打开界面的时候,就必须要先查询出来的,省份地区 这里肯定不需要ajax请求。

我这里就是先查询出所有的省级行政地区,可以用 level = 1 或 parent_id = 0 都可以。

$select_option = $sql->select($mysqli); //先查出省份的数据level = 1
        foreach ($select_option as $k => $v){
            $province .=  "<option value='".$v['id']."'>".$v['name']."</option>";
        }

        require_once ABSPATH . '/view.php';

 

view.php

这主要是模板代码,重点看JavaScript代码部份,那里是:原生的Ajax代码。

触发Ajax我用的是onchange事件,你可以根据自己的情况来。肯定不能用Ajax轮询,每隔1秒请求一次,有点太毕浪费资源了,毕竟需要查询数据库。

由于项目要求,因此我的 select 标签 用的是 disabled=disabled,有需要隐藏的可以加上 hidden=hidden。

  <div class="col-md-12">
            <form class="form-horizontal" action="" method="post" enctype="multipart/form-data" autocomplete="on">
                <div class="input-group  mb-4">
                    <div class="input-group-prepend">
                        <span class="input-group-text" >名称</span>
                        <span class="input-group-text" style="color: red;background-color: white;">*</span>
                    </div>

                    <input id="name" autofocus="autofocus"  type="text" required="required" name="name"  maxlength="20"  class="form-control" placeholder="这将是它在站点上显示的名字。">
                    <div class="col-md-12">
                        <p style="color: #757575">注意:名称是唯一的,请勿重复,否则数据库会插入数据失败!</p>
                    </div>
                </div>

                <div class="input-group  mb-4">
                    <div class="input-group-prepend">

                        <span class="input-group-text" >别名</span>
                        <span class="input-group-text" style="color: red;background-color: white;">*</span>
                    </div>
                    <input id="alias" type="text" class="form-control" required="required" name="alias" maxlength="20" pattern="[a-z0-9_-]+" title="匹配规则未通过!" placeholder="‘别名’是在URL中使用的别称,它可以令URL更美观。通常使用小写,只能包含字母,数字,下划线(_)和连字符(-)。">
                    <div class="col-md-12">
                        <p style="color: #757575">注意:别名是唯一的,请勿重复,否则数据库会插入数据失败!</p>
                    </div>
                </div>

                <div class="input-group  mb-4">
                    <div class="input-group-prepend">
                        <span class="input-group-text" >地区列表</span>
                    </div>
                    <select onchange="Loadprovince()"  class="form-control" name="province" id="province">
                        <option value ="province">省</option>
                        <?php echo $province; ?>
                    </select>
                    <select onchange="Loadcity()" class="form-control" name="city" id="city" disabled="disabled">
                        <option value ="city">市</option>

                    </select>
                    <select class="form-control" name="county" id="county" disabled="disabled">
                        <option value ="county">县</option>
                    </select>

                </div>
                <div class="col-md-12">
                    <p style="color: #757575">一级省级行政区 包括:省、自治区、直辖市、特别行政区。</p>
                    <p style="color: #757575">二级市级行政区 包括:地级市、地区、自治州、盟。</p>
                    <p style="color: #757575">三级县级行政区 包括:市辖区、县级市、县、自治县、旗、自治旗、林区、特区。</p>
                    <p style="color: #757575">四级乡级行政区 包括:街道、镇、乡、民族乡、苏木、民族苏木、县辖区。</p>
                </div>
                <?php if($AJAX === 1){ ?>
                    <script>
                        function Loadprovince() {
                            var xhttp = new XMLHttpRequest();
                            xhttp.onreadystatechange = function() {
                                if (this.readyState == 4 && this.status == 200) {
                                    if(document.getElementById("city").getAttribute("disabled")){
                                        document.getElementById("city").removeAttribute("disabled");
                                    }else{
                                        //document.getElementById("city").setAttribute("hidden","hidden");
                                        document.getElementById("county").innerHTML = '<option value="county">县</option>';
                                        document.getElementById("county").setAttribute("disabled","disabled");
                                    }
                                    document.getElementById("city").innerHTML = this.responseText;
                                }
                            };
                            //获取省地区的ID并ajax传送到服务端,例如:四川省id=5
                            var data = "province=" + document.getElementById("province").value + "&type=<?php echo $type;?>";
                            //console.log(data);
                            xhttp.open("POST", "/ajax.php", true);
                            xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
                            xhttp.send(data);
                        }
                        function Loadcity() {
                            var xhttp = new XMLHttpRequest();
                            xhttp.onreadystatechange = function() {
                                if (this.readyState == 4 && this.status == 200) {
                                    if(document.getElementById("county").getAttribute("disabled")){
                                        document.getElementById("county").removeAttribute("disabled");
                                    }
                                    document.getElementById("county").innerHTML = this.responseText;

                                }
                            };
                            var data = "city=" + document.getElementById("city").value + "&type=<?php echo $type;?>";
                           //console.log(data);
                            xhttp.open("POST", "/ajax.php", true);
                            xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
                            xhttp.send(data);
                        }
                    </script>

                <?php } ?>
                <input type="hidden" name="token" value="<?php echo $get_token; ?>"/>

                <button type="submit" class="btn btn-primary">提交</button>
                <button type="reset" class="btn btn-primary">重置</button>


            </form>
        </div>

 

ajax.php

这里就是从前端接收到ajax请求后,服务端需要返回什么数据?

我这里就是直接数据库查询某个省下面有多少市的数据?某个市下面有多少县的数据?依次类推,还可以查询某个县有多少乡或镇的 数据,由于只做三级,因此就不再继续往下查询了。

由于项目加急,代码写得比较简单,先让业务先在线上跑起来再说,先保证功能正常吧!其它的后期再搞。

    $ajax_province = htmlspecialchars($_POST['province'],ENT_QUOTES); //得到某个省的ID
    $ajax_city = htmlspecialchars($_POST['city'],ENT_QUOTES);//得到某个市的ID
    //echo $ajax_province;

    if($ajax_province){
        if($ajax_province === "province"){
            //说明未选择任何的省,不做数据库查询
            echo $city =  '<option value="city">市</option>';
            exit;
        }else{
            //数据库查询某一个省有多少市的数据pid = 省的主键id
            $sql = "SELECT `id`,`name` FROM `area` WHERE `parent_id` = ?";
            $stmt = $mysqli->prepare($sql);
            $stmt->bind_param("i",$ajax_province);
            $stmt->execute();
            $stmt->bind_result($id,$name);
            $arr =[];
            $arr2 =[];
            while ( $stmt -> fetch ()) {
                $arr['id'] = $id;
                $arr['name'] = $name;
                $arr2[] = $arr;
            }
            if($arr2){ //判断是否查出来的有数据?
                $city =  '<option value="city">不限</option>';
                foreach ($arr2 as $k => $v){
                    $city .=  "<option value='".$v['id']."'>".$v['name']."</option>";
                }
                echo $city;
                exit;
            }else{
                echo $city =  '<option value="city">不限</option>';
                exit;
            }

        }
    }elseif($ajax_city){
        if($ajax_city === "city"){
            //说明未选择任何的市,不做数据库查询
            echo $city =  '<option value="county">县</option>';
        }else{
            //数据库查询某一个市有多少县的数据 pid = 市的主键id
            $sql = "SELECT `id`,`name` FROM `area` WHERE `parent_id` = ?";
            $stmt = $mysqli->prepare($sql);
            $stmt->bind_param("i",$ajax_city);
            $stmt->execute();
            $stmt->bind_result($id,$name);
            $arr =[];
            $arr2 =[];
            while ( $stmt -> fetch ()) {
                $arr['id'] = $id;
                $arr['name'] = $name;
                $arr2[] = $arr;
            }
            if($arr2){ //判断是否查出来的有数据?
                    $city =  '<option value="county">不限</option>';
                foreach ($arr2 as $k => $v){
                    $city .=  "<option value='".$v['id']."'>".$v['name']."</option>";
                }
                echo $city;
                exit;
            }else{
                echo $city =  '<option value="county">不限</option>';
                exit;
            }
        }
    }else{
        echo '<option value="error">出错啦!</option>';
    }

 

总结:

我在网上看了还有一种 js原生Ajax实现三级联动下拉菜单省市区代码,我个人感觉那种不是很好,因为他每次Ajax请求都会直接把所有的“省、市、区”全部查询出来;然后,后面再做一个判断是返回省,还是省+市,还是省+市+区。

    A+
发布日期:2021年01月09日 11:57:03  所属分类:Ajax
最后更新时间:2021-07-03 16:01:24
付杰
  • ¥ 79.0元
  • 市场价:99.0元
  • ¥ 298.0元
  • 市场价:498.0元
  • ¥ 99.0元
  • 市场价:199.0元
  • ¥ 198.0元
  • 市场价:398.0元

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: