结果展示:
一.:准备:
数据库、eclipse动态web、两个包(分别是链接数据库的mysql-connector-java-*.jar包、以及使用jQuery的jquery-*.js包(可以使用线上的))
1. jQuery准备:
jQuery是一个优秀javaScript库,开发人员称之为javaScript框架。需要第一个包,直接建立文件夹js(在WebContent下)把包复制过去,(如果拖拽不过去。ctrl+c,ctrl+v可以)。
或者在线版本:Jquery在线包地址https://releases.jquery.com/jquery/
打开网站,复制一个jQuery地址 用在线版本替代本地的
2.链接数据库准备:
下载对应版本 mysql-connector-java-*.jar包https://repo1.maven.org/maven2/mysql/mysql-connector-java/
eclipse链接数据库就需要第二个包,放在(在WebContent的WEB-INF的lib下)复制过去。
或者导入jar包(导入jar包)
3.数据库准备:
数据库:有city(城市表)、provinc(省表),其中city(城市)表有一个pro_id外键
二.:实施:
1.创建4个包:
其中:
bean包(JavaBean):JavaBean是一个符合特定规范的Java类。通常用于封装数据,并提供公共的getter和setter方法以及其他操作方法。JavaBean用于在不同的层之间传递数据或表示业务实体。(简单理解就是定义Java类地方,其中包含这个类属性、get、set、toString、有参、无参构造方法)
dao包(Data Access Object):DAO是数据访问对象的缩写。DAO模式是一种用于数据持久化的设计模式。DAO类封装了与数据存储相关的操作方法,如增加、删除、修改和查询等。通过DAO,应用程序可以更方便地与底层数据库进行交互,并隐藏了数据库细节。(简单理解就是链接数据库、对数据库进行增删改查地方)
service包:Service层位于DAO层之上,负责处理业务逻辑。Service层通常封装了一系列的业务操作,如数据校验、事务管理和调用多个DAO方法等。它使得控制层,如Servlet,能够更专注于处理请求和响应,将业务逻辑的处理分离出来。同时,service层的存在使得信息处理的代码更加模块化和可复用,方便进行单元测试和维护、确保输入的数据是有效和可信的,以及对数据进行必要的处理和操作,满足业务需求和数据完整性的要求。(简单理解就是对数据检测、以及数据处理地方)
servlet包:Servlet是Java Web开发中处理HTTP请求和生成HTTP响应的组件。Servlet是运行在Web服务器上的Java类。它可以接收来自客户端的请求,并生成相应的响应。Servlet可以处理不同类型的请求(如GET、POST等),在服务端执行相应的业务逻辑,并与客户端进行交互。Servlet将Java代码嵌入到Web应用程序中,实现与客户端的交互和业务逻辑处。Servlet运行在服务器端,所以它可以与数据库、文件系统等后台资源进行交互,处理复杂的数据操作和业务需求。 (简单理解就是处理HTTP请求、生成动态内容并实现服务器端业务逻辑的Java组件,是构建Java Web应用程序的重要组成部分)
2.创建链接数据库BaseDAO.java
根据上面介绍、链接数据库放在dao包下
package com.dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
/**
* 数据持久化层
* @author lenovo
*/
public class BaseDAO<E> {
private static final String DRIVER="com.mysql.cj.jdbc.Driver";//针对数据库不同版本,8以上需要加.cj. 8一下就是com.mysql.jdbc.Driver无需加cj
private static final String URL="jdbc:mysql://127.0.0.1:3306/gs?useUnicode=true&characterEncoding=utf-8";//gs是我数据库,useUnicode=true:启用 Unicode 编码支持。,characterEncoding=utf-8:指定字符编码为 UTF-8,以支持多种语言和字符集。
private static final String USERNAME="root";
private static final String USERPWD="000000";//6个0是我数据库密码
private Connection conn = null; // 数据库连接对象
private Statement stmt = null; // SQL语句执行对象
protected ResultSet rs = null; // 结果集对象,用于存储查询结果
//加载驱动 在整个使用的过程中,只需要加载一次,使用使用static
static {
try {
//加载驱动
Class.forName(DRIVER);
System.out.println("===驱动加载成功===");
} catch (Exception e) {
e.printStackTrace();//捕获异常
}
}
/**
* 获取数据库连接
*/
public void getConn() {
try {
//连接数据库
//连接云端就把localhost改成地址
conn= DriverManager.getConnection(URL,USERNAME,USERPWD);
System.out.println("===连接成功===");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 创建命令执行对象
*/
public void getStmt() {
try {
//创建命令执行对象
stmt=conn.createStatement();
System.out.println("===创建命令执行对象成功===");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 释放资源,关闭ResultSet、Statement和Connection对象
*/
public void closeRes() {
try {
if(rs!=null) {
rs.close();
rs=null;
}
if(stmt!=null) {
stmt.close();
stmt=null;
}
if(conn!=null) {
conn.close();
conn=null;
}
System.out.println("===资源释放成功===");
} catch (Exception e) {
e.printStackTrace();
}
}
//通用的增删改操作
public void update(String sql) throws Exception {
//1.加载驱动2.连接数据库 连接云端就把localhost改成地址
getConn();
//3.创建命令执行对象
getStmt();
//4.执行命令
stmt.executeUpdate(sql);
//stmt.executeQuery(sql);
System.out.println("====sql===="+sql);
//5.释放资源
closeRes();
}
/**
* 执行查询操作,返回一个泛型为E的结果列表
* @param sql 要执行的SQL语句
* @return 查询结果列表
* @throws SQLException
*/
public List<E> query(String sql) throws SQLException{
getConn();
getStmt();
rs=stmt.executeQuery(sql);
List<E> list=new ArrayList<E>();
rs2list(list);
closeRes();
return list;
}
/**
* 将查询结果转换为列表,子类可以继承并重写此方法来实现自定义的结果处理逻辑
* @param list 查询结果列表
*/
public void rs2list(List<E> list) {
//子类E类会继承这个方法并且对其重写
}
/*这是一个泛型类,使用<E>表示泛型参数,可以根据需要指定具体类型。
定义了与数据库连接和操作相关的常量,如驱动、URL、用户名和密码。
getConn()方法用于获取数据库连接。
getStmt()方法用于创建命令执行对象。
closeRes()方法用于释放资源,关闭ResultSet、Statement和Connection对象。
update(String sql)方法用于执行更新操作(增删改)。
query(String sql)方法用于执行查询操作,返回一个泛型为E的结果列表。
rs2list(List<E> list)方法用于将查询结果转换为列表。子类可以继承并重写此方法来实现自定义的结果处理逻辑。
*/
}
3.创建city(市)以及province(省)类:
根据上面介绍创建对应Java类放在bean包下
City.java:
package com.bean;
public class City {
private String city_name; // 城市名称
private String city_id; // 城市ID
private String pro_id; // 省份ID
// 构造方法
public City(String city_name, String city_id, String pro_id) {
super();
this.city_name = city_name;
this.city_id = city_id;
this.pro_id = pro_id;
}
public City() {
super();
}
public City(String city_name, String city_id) {
super();
this.city_name = city_name;
this.city_id = city_id;
}
// Getter和Setter方法
public String getCity_name() {
return city_name;
}
public void setCity_name(String city_name) {
this.city_name = city_name;
}
public String getCity_id() {
return city_id;
}
public void setCity_id(String city_id) {
this.city_id = city_id;
}
public String getPro_id() {
return pro_id;
}
public void setPro_id(String pro_id) {
this.pro_id = pro_id;
}
@Override
public String toString() {
return "City [city_name=" + city_name + ", city_id=" + city_id + ", pro_id=" + pro_id + "]";
}
}
Province.java
package com.bean;
public class Province {
private String pro_name; // 省份名称
private String pro_id; // 省份ID
// 构造方法
public Province(String pro_name, String pro_id) {
super();
this.pro_name = pro_name;
this.pro_id = pro_id;
}
public Province() {
super();
}
// Getter和Setter方法
public String getPro_name() {
return pro_name;
}
public void setPro_name(String pro_name) {
this.pro_name = pro_name;
}
public String getPro_id() {
return pro_id;
}
public void setPro_id(String pro_id) {
this.pro_id = pro_id;
}
@Override
public String toString() {
return "Province [pro_name=" + pro_name + ", pro_id=" + pro_id + "]";
}
}
4.对每一个类,分别写详细数据库操作:
根据上面介绍、对数据库进行增删改查地方放在dao包下
CityDao.java
package com.dao;
import java.sql.SQLException;
import java.util.List;
import com.bean.City;
import com.bean.Province;
public class CityDao extends BaseDAO<City> {
//查询对应省下的市
public List<City> findAll(String pro_id) throws SQLException {
String sql="select * from city where pro_id='"+pro_id+"'";
System.out.println("sql========"+sql);
return super.query(sql);
}
@Override
public void rs2list(List<City> list) {
try {
while(rs.next()) {
String city_id=rs.getString("city_id");
String city_name=rs.getString("city_name");
City prov=new City(city_name, city_id);
list.add(prov);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
ProvinceDao.java
package com.dao;
import java.sql.SQLException;
import java.util.List;
import com.bean.Province;
public class ProvinceDao extends BaseDAO<Province> {
//查询全部省
public List<Province> findAll() throws SQLException {
String sql="select * from province";
return super.query(sql);
}
@Override
public void rs2list(List<Province> list) {
try {
while(rs.next()) {
String pro_id=rs.getString("pro_id");
String pro_name=rs.getString("pro_name");
Province prov=new Province(pro_name, pro_id);
list.add(prov);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
5.创建俩个类的业务逻辑层(Service):
这个小项目并没有很好体现出业务逻辑层用处
业务逻辑层,也称为业务层。在典型的三层架构中,分为展示层(Presentation Layer)、业务逻辑层(Service Layer)和数据访问层(Data Access Layer)。
Service层主要负责处理业务逻辑,与数据访问层交互并协调不同的组件来完成具体的业务需求。它起到了连接展示层和数据访问层的桥梁作用,对外提供服务接口供其他层调用。
Service层的主要职责包括:
- 实现业务逻辑和业务规则。
- 协调不同的数据访问对象进行数据访问。
- 处理事务控制。
- 提供服务接口供其他层使用。
CityService.java
package com.Service;
import java.sql.SQLException;
import java.util.List;
import com.bean.City;
import com.bean.Province;
import com.dao.CityDao;
import com.dao.ProvinceDao;
public class CityService {
public List<City> findAll(String pro_id) throws SQLException {
//测试pro_id是否传递过来
System.out.println("CityService-id="+pro_id);
List<City> list1=new CityDao().findAll(pro_id);
return list1;
}
}
ProcessService.java
package com.Service;
import java.sql.SQLException;
import java.util.List;
import com.bean.Province;
import com.dao.ProvinceDao;
public class ProcessService {
public List<Province> findAll() throws SQLException {
List<Province> list1=new ProvinceDao().findAll();
return list1;
}
}
6.创建俩个类的应用程序的展示层(Servlet):
Servlet层属于应用程序的展示层,也称为表示层或控制层。
Servlet是一种Java编写的服务器端组件,用于处理客户端(通常是Web浏览器)发送的HTTP请求并生成响应。它主要负责接收用户的请求、调用相应的业务逻辑处理、准备响应数据,并将响应返回给客户端。
Servlet作为应用程序的入口点,承担了与用户交互的任务。它负责处理用户的输入和输出,并协调其他层(如Service层)来完成具体的业务逻辑。通过Servlet层的封装和处理,可以实现用户和应用程序之间的交互,并将请求路由到不同的业务逻辑处理单元进行处理。
Servlet层的主要职责包括:
- 接收并处理客户端的请求。
- 解析请求参数和路径信息。
- 调用相应的Service层来处理业务逻辑。
- 根据业务逻辑的结果准备响应数据。
- 将响应返回给客户端。
创建的是servlet:
代码:
showCity.java
package com.Servlet;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.Service.CityService;
import com.bean.City;
/**
* Servlet implementation class showPro
*/
@WebServlet("/ShowCity.do")
public class showCity extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public showCity() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// //请求乱码 html给数据到servlet
// request.setCharacterEncoding("utf-8");
// //响应乱码 servlet给数据到浏览器显示乱码
// response.setContentType("text/html;charset=utf-8");
request.setCharacterEncoding("utf-8");//requsest 请求
response.setContentType("text/html;charset=utf-8");//response相应
List<City> list=null;
/* 使用 Java Servlet 获取名为 "prov_id" 的请求参数的值。
request 表示当前的 HTTP 请求对象,通常在 Java Servlet 中通过方法参数或成员变量进行传递。
getParameter("prov_id") 是 request 对象的方法,用于获取指定名称的请求参数的值。在这里,参数名称是 "prov_id"。
*/
String prov_id=request.getParameter("pro_id");
System.out.println("String prov_id="+prov_id);
try {
list=new CityService().findAll(prov_id);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//[{"city_id":"1001","city_name":"安徽省"},{},{}]
StringBuffer sbf=new StringBuffer();
/* StringBuffer 是 Java 中的一个类,用于动态地构建字符串。它与 String 类似,但具有更好的性能和可变性。
* 在 Java 中,String字符串是不可变的,这意味着一旦创建,就无法修改。当我们需要对字符串进行频繁的拼接或修改操作时,使用 StringBuffer 可以避免不断创建新的字符串对象和浪费内存空间。StringBuffer 允许我们在现有字符串的基础上添加、插入、修改或删除字符,而不需要创建新的字符串对象。
StringBuffer sb = new StringBuffer(); // 创建一个空的StringBuffer对象
StringBuffer sb = new StringBuffer("Hello"); // 创建一个包含初始内容的StringBuffer对象
sb.append(" World"); // 在末尾添加字符串
sb.insert(6, "Java "); // 在指定位置插入字符串
sb.replace(6, 10, "Python"); // 替换指定位置的字符串
sb.delete(6, 11); // 删除指定范围内的字符串
sb.reverse(); // 反转字符串
int length = sb.length(); // 获取字符串的长度
String str = sb.toString(); // 将StringBuffer对象转换为字符串
*/
sbf.append("[");
for (int i = 0; i < list.size(); i++) {
if(i!=0) {
sbf.append(",");
}
sbf.append("{");
sbf.append("\"city_id\"");
sbf.append(":");
sbf.append("\""+list.get(i).getCity_id()+"\"");
sbf.append(",");
sbf.append("\"city_name\"");
sbf.append(":");
sbf.append("\""+list.get(i).getCity_name()+"\"");
sbf.append("}");
}
sbf.append("]");
response.getWriter().print(sbf.toString());
/*response.getWriter().print(sbf.toString()) 是一个典型的 Java Servlet 中向客户端发送响应的代码片段。
在这个代码中,首先通过 response.getWriter() 获取一个 PrintWriter 对象,
然后使用 print() 方法将 sbf.toString() 的结果输出到客户端。
sbf.toString() 将 StringBuffer 对象 sbf 转换为字符串形式。
*/
}
}
showPro.java
package com.Servlet;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.Service.ProcessService;
import com.bean.Province;
/**
* Servlet implementation class showPro
*/
@WebServlet("/ShowProvince.do")
public class showPro extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public showPro() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// //请求乱码 html给数据到servlet
// request.setCharacterEncoding("utf-8");
// //响应乱码 servlet给数据到浏览器显示乱码
// response.setContentType("text/html;charset=utf-8");
request.setCharacterEncoding("utf-8");//requsest 请求
response.setContentType("text/html;charset=utf-8");//response相应
List<Province> list=null;
try {
list=new ProcessService().findAll();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//[{"pro_id":"1001","pro_name":"安徽省"},{},{}]
StringBuffer sbf=new StringBuffer();
/* StringBuffer 是 Java 中的一个类,用于动态地构建字符串。它与 String 类似,但具有更好的性能和可变性。
* 在 Java 中,String字符串是不可变的,这意味着一旦创建,就无法修改。当我们需要对字符串进行频繁的拼接或修改操作时,使用 StringBuffer 可以避免不断创建新的字符串对象和浪费内存空间。StringBuffer 允许我们在现有字符串的基础上添加、插入、修改或删除字符,而不需要创建新的字符串对象。
StringBuffer sb = new StringBuffer(); // 创建一个空的StringBuffer对象
StringBuffer sb = new StringBuffer("Hello"); // 创建一个包含初始内容的StringBuffer对象
sb.append(" World"); // 在末尾添加字符串
sb.insert(6, "Java "); // 在指定位置插入字符串
sb.replace(6, 10, "Python"); // 替换指定位置的字符串
sb.delete(6, 11); // 删除指定范围内的字符串
sb.reverse(); // 反转字符串
int length = sb.length(); // 获取字符串的长度
String str = sb.toString(); // 将StringBuffer对象转换为字符串
*/
sbf.append("[");
for (int i = 0; i < list.size(); i++) {
if(i!=0) {
sbf.append(",");
}
sbf.append("{");
sbf.append("\"pro_id\"");
sbf.append(":");
sbf.append("\""+list.get(i).getPro_id()+"\"");
sbf.append(",");
sbf.append("\"pro_name\"");
sbf.append(":");
sbf.append("\""+list.get(i).getPro_name()+"\"");
sbf.append("}");
}
sbf.append("]");
response.getWriter().print(sbf.toString());
/*response.getWriter().print(sbf.toString()) 是一个典型的 Java Servlet 中向客户端发送响应的代码片段。
在这个代码中,首先通过 response.getWriter() 获取一个 PrintWriter 对象,
然后使用 print() 方法将 sbf.toString() 的结果输出到客户端。
sbf.toString() 将 StringBuffer 对象 sbf 转换为字符串形式。
*/
}
}
介绍为什么需要把list集合转化成字符串:
sbf.append("[") ..... sbf.append("]") 的目的是构建一个包含省份信息的 JSON 数组
sbf.toString() 将 StringBuffer 对象 sbf 转换为字符串形式,最后在客户端(这里是下面的省市二级联动.jsp)中的eval("provice="+data) 的作用是将字符串 data 解析为 JavaScript 表达式,并将解析后的结果赋值给变量 provice
response.getWriter().print(sbf.toString()) 是一个典型的 Java Servlet 中向客户端(这里是下面的省市二级联动.jsp)发送响应的代码片段。
且在 showCity.java中会多一个请求,因为我们要根据选的省信息,确定市所以需要request.setCharacterEncoding("utf-8");//requsest 防止请求乱码
String prov_id=request.getParameter("pro_id");使用 Java Servlet 获取名为 "prov_id" 的请求参数的值。request 表示当前的 HTTP 请求对象,通常在 Java Servlet 中通过方法参数或成员变量进行传递。getParameter("prov_id") 是 request 对象的方法,用于获取指定名称的请求参数的值。在这里,参数名称是 "prov_id"。
三.:最后的客户端省市二级联动.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<!-- <script type="text/javascript" src="js/jquery.js"></script> -->
<script src="https://code.jquery.com/jquery-3.7.0.js" integrity="sha256-JlqSTELeR4TLqP0OG9dxM7yDPqX1ox/HfgiSLBj8+kM=" crossorigin="anonymous"></script>
<script type="text/javascript">
$(function(){/* 指定一个函数,在文档加载完成后被调用。 */
/* 异步请求 查询省信息 */
$.ajax({
type:"get",
url:"ShowProvince.do",
cache:false,
dataType:"text",
success:function(data) {
/* eval() 函数是 JavaScript 中的一个全局函数,它将传入的字符串data作为 JavaScript 代码进行解析和执行。
其作用是将字符串 data 解析为 JavaScript 对象,并将其赋值给变量 provice
eg:
假设 data 的值为 "[{"id":1,"name":"北京"},{"id":2,"name":"上海"}]",即包含了两个省份信息的 JSON 数组的字符串形式。
在执行 eval() 函数时,会将传入的字符串 "provice=[{"id":1,"name":"北京"},{"id":2,"name":"上海"}]" 视为 JavaScript 代码进行解析和执行。
JavaScript 解析器首先将字符串中的 "provice=" 当作一个赋值语句。然后,解析器继续解析并计算剩余的内容。
在剩余的内容中,解析器遇到了一个包含省份信息的 JSON 数组的字符串 "[{"id":1,"name":"北京"},{"id":2,"name":"上海"}]"。由于这是一个有效的 JavaScript 表达式,解析器将其视为一个值,并将该值赋给变量 provice。
最终,变量 provice 被赋值为一个包含两个省份信息的 JavaScript 数组。在后续的代码中,可以通过访问 provice 变量来获取和操作这些省份信息
*/
eval("provice="+data);
/* 生成<option value="101">安徽</option>这样的 字符串 在修改html就出现了下拉框*/
var str="<option value='-1'>==请选择省===</option>"
for(var i=0;i<provice.length;i++){
str+="<option value='"+provice[i].pro_id+"'>"+provice[i].pro_name+"</option>"
}
// 修改HTML 字符串赋值给某个具有 id 为 "prov" 的元素,以渲染出省份选择框。
$("#prov").html(str);
}
});
//使用jQuery为省下拉框绑定事件
$("#prov").on("change",function(){
var pro_id=$("#prov").val();
if(pro_id!=-1){
$.ajax({
type:"get",
url:"ShowCity.do",
cache:false,
dataType:"text",
data:{"pro_id":pro_id},
success:function(data) {
/* eval() 函数是 JavaScript 中的一个全局函数,它将传入的字符串data作为 JavaScript 代码进行解析和执行。
其作用是将字符串 data 解析为 JavaScript 对象,并将其赋值给变量 provice
eg:
假设 data 的值为 "[{"id":1,"name":"北京"},{"id":2,"name":"上海"}]",即包含了两个省份信息的 JSON 数组的字符串形式。
在执行 eval() 函数时,会将传入的字符串 "provice=[{"id":1,"name":"北京"},{"id":2,"name":"上海"}]" 视为 JavaScript 代码进行解析和执行。
JavaScript 解析器首先将字符串中的 "provice=" 当作一个赋值语句。然后,解析器继续解析并计算剩余的内容。
在剩余的内容中,解析器遇到了一个包含省份信息的 JSON 数组的字符串 "[{"id":1,"name":"北京"},{"id":2,"name":"上海"}]"。由于这是一个有效的 JavaScript 表达式,解析器将其视为一个值,并将该值赋给变量 provice。
最终,变量 provice 被赋值为一个包含两个省份信息的 JavaScript 数组。在后续的代码中,可以通过访问 provice 变量来获取和操作这些省份信息
*/
eval("provices="+data);
/* 生成<option value="101">安徽</option>这样的 字符串 在修改html就出现了下拉框*/
var str="<option value='-1'>==请选择市、县===</option>"
for(var i=0;i<provices.length;i++){
str+="<option value='"+provices[i].city_id+"'>"+provices[i].city_name+"</option>"
}
//显示市、县下拉框
$("#city").css("display","block");
// 修改HTML 字符串赋值给某个具有 id 为 "city" 的元素,以渲染出省份选择框。
$("#city").html(str);
}
});
}else{
//不显示市、县下拉框
$("#city").css("display","none");
}
});
});
</script>
</head>
<body>
<table>
<tr>
<td>
<select id="prov"> </select>
</td>
<td>
<!-- style="display: none;" 没有选省之前式默认不显示 -->
<select id="city" style="display: none;"></select>
</td>
</tr>
</table>
</body>
</html>
最后结果: