联动选择下拉菜单是我们在开发中经常遇到的问题,一般来讲,三级联动是最为常见的。具体实现方式有很多种:比如每一次下拉选择change的时候发一次ajax请求调数据库加载,或者全部加载信息使用dom方式控制菜单。从性能上来说,第二种实现方式优于第一种,减少了数据库调用次数,并且也能很好地控制菜单显示速度。本文将使用第二种实现方式:
1表设计和准备数据:建立以下数据表并插入示例数据,用于反映学院、专业、班级的三个层级关系,使用lvl和parcode来表示层次关系。
create table grade_tab(
code varchar2(20) primary key,
codenm varchar2(40),
parcode varchar2(20),
lvl varchar2(1)
);
--lvl1 data
insert into grade_tab
(code, codenm, parcode, lvl)
values
('ETC', 'Electric', '', '1');
insert into grade_tab
(code, codenm, parcode, lvl)
values
('ECO', 'Economics', '', '1');
insert into grade_tab
(code, codenm, parcode, lvl)
values
('STW', 'softwa', '', '1');
--lvl2 data
insert into grade_tab
(code, codenm, parcode, lvl)
values
('ETC01', 'Electric automatic', 'ETC', '2');
insert into grade_tab
(code, codenm, parcode, lvl)
values
('ETC02', 'Electric machintic', 'ETC', '2');
insert into grade_tab
(code, codenm, parcode, lvl)
values
('ETC03', 'Electric emmbed', 'ETC', '2');
insert into grade_tab
(code, codenm, parcode, lvl)
values
('ECO01', 'E-commerce', 'ECO', '2');
insert into grade_tab
(code, codenm, parcode, lvl)
values
('ECO02', 'National trade', 'ECO', '2');
insert into grade_tab
(code, codenm, parcode, lvl)
values
('SE', 'Software erginerring', 'STW', '2');
--lvl3 data
insert into grade_tab
(code, codenm, parcode, lvl)
values
('ETCC1', '011007', 'ETC01', '3');
insert into grade_tab
(code, codenm, parcode, lvl)
values
('ETCC2', '011008', 'ETC01', '3');
insert into grade_tab
(code, codenm, parcode, lvl)
values
('ETCC3', '011009', 'ETC02', '3');
insert into grade_tab
(code, codenm, parcode, lvl)
values
('ETCC4', '011010', 'ETC02', '3');
insert into grade_tab
(code, codenm, parcode, lvl)
values
('ETCC5', '011011', 'ETC03', '3');
insert into grade_tab
(code, codenm, parcode, lvl)
values
('ETCC6', '011012', 'ETC03', '3');
insert into grade_tab
(code, codenm, parcode, lvl)
values
('ETCC7', '011014', 'ETC03', '3');
insert into grade_tab
(code, codenm, parcode, lvl)
values
('STWC1', '011201', 'SE', '3');
insert into grade_tab
(code, codenm, parcode, lvl)
values
('STWC2', '011202', 'SE', '3');
insert into grade_tab
(code, codenm, parcode, lvl)
values
('STWC3', '011203', 'SE', '3');
insert into grade_tab
(code, codenm, parcode, lvl)
values
('STWC4', '011204', 'SE', '3');
2前端页面:
页面将使用ajax作为请求处理技术,同时使用json作为数据传输格式,使用JQuery作为dom操作的主要工具,具体代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>choose</title>
<c:set var="root" value="${pageContext.request.contextPath}"></c:set>
<script src="js/jquery-1.9.0.min.js"></script>
<script>
var lvl1;
var lvl2;
var lvl3;
$(function(){
$.ajax({
type : "POST",
url : "${root}/GradeServ",
dataType : "json",
//data : "method=init",
success : function(data){
lvl1 = data.lvl1;
lvl2 = data.lvl2;
lvl3 = data.lvl3;
var cell1 = $("#lvl1");
for(var i = 0;i<lvl1.length;i++){
var school = lvl1[i];
cell1.append("<option value="+school.code+">"+school.codenm+"</option>");
}
cell1.change(function(){
nextVal("2");
nextVal("3");
})
var cell2 = $("#lvl2");
cell2.change(function(){
nextVal("3");
})
}
})
});
function nextVal(level){
var now_node = $("#lvl"+level);
now_node.empty();
var parcode = $("#lvl"+(level-1)).val();
console.log(parcode);
var list = null;
if(level==2){
list = lvl2;
} else {
list = lvl3;
}
for(var i =0;i<list.length;i++){
var node = list[i];
if(node.parcode==parcode && level==node.lvl){
now_node.append("<option value="+node.code+">"+node.codenm+"</option>");
}
}
if(now_node.find("option").length==0){
now_node.append("<option value='0'>--Choose--</option>");
}
}
</script>
</head>
<body>
<select name='lvl1' id='lvl1'>
<option value='0'>--Choose--</option>
</select>
<select name='lvl2' id='lvl2'>
<option value='0'>--Choose--</option>
</select>
<select name='lvl3' id='lvl3'>
<option value='0'>--Choose--</option>
</select>
</body>
</html>
页面在加载时即发送请求到服务程序,加载所有的层级信息,并将这些信息使用Array形式进行存放。
3.服务端代码
Bean类:
package com.any.grade;
/**
* @ClassName: GradeBean
* @author Helen
*/
public class GradeBean {
private String code;
private String codenm;
private String parcode;
private String lvl;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getCodenm() {
return codenm;
}
public void setCodenm(String codenm) {
this.codenm = codenm;
}
public String getParcode() {
return parcode;
}
public void setParcode(String parcode) {
this.parcode = parcode;
}
public String getLvl() {
return lvl;
}
public void setLvl(String lvl) {
this.lvl = lvl;
}
public GradeBean(String code, String codenm, String parcode, String lvl) {
super();
this.code = code;
this.codenm = codenm;
this.parcode = parcode;
this.lvl = lvl;
}
public GradeBean(){}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((code == null) ? 0 : code.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
GradeBean other = (GradeBean) obj;
if (code == null) {
if (other.code != null)
return false;
} else if (!code.equals(other.code))
return false;
return true;
}
}
使用Servlet作为数据准备程序,用于处理请求并将数据发送给前端页面:
package com.any.grade;
import java.io.IOException;
import java.util.List;
import java.util.Map;
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 net.sf.json.JSONArray;
/**
* Servlet implementation class GradeServ
*/
@WebServlet("/GradeServ")
public class GradeServ extends HttpServlet {
private static final long serialVersionUID = 1L;
private GradeDao gd = new GradeDao();
public GradeServ() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Map<String, List<GradeBean>> data = gd.loadData();
List<GradeBean> lvl1 = data.get("lvl1");
List<GradeBean> lvl2 = data.get("lvl2");
List<GradeBean> lvl3 = data.get("lvl3");
JSONArray j_lvl1 = JSONArray.fromObject(lvl1);
JSONArray j_lvl2 = JSONArray.fromObject(lvl2);
JSONArray j_lvl3 = JSONArray.fromObject(lvl3);
String json = "{\"lvl1\":"+j_lvl1.toString()+",\"lvl2\":"+j_lvl2.toString()+",\"lvl3\":"+j_lvl3.toString()+"}";
response.setContentType("text/json");
response.setCharacterEncoding("UTF-8");
response.getWriter().println(json);
}
}
Dao类,查询数据库并将数据通过bean传递:
package com.any.grade;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.any.servlet.DbUtil;
/**
* @ClassName: GradeDao
* @author Helen
*/
public class GradeDao {
private List<GradeBean> getPriGrade(String lvl){
String sql = "select code,codenm,parcode,lvl from grade_tab "
+ "where lvl=? "
+ "and codenm is not null ";
ResultSet rs = DbUtil.executeQuery(sql, lvl);
List<GradeBean> list = new ArrayList<GradeBean>();
try {
while(rs.next()){
list.add(new GradeBean(rs.getString("code"),
rs.getString("codenm"),
rs.getString("parcode"),
rs.getString("lvl")));
}
return list;
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
public Map<String, List<GradeBean>> loadData(){
Map<String, List<GradeBean>> data = new HashMap<String, List<GradeBean>>();
List<GradeBean> lvl1 = getPriGrade("1");
List<GradeBean> lvl2 = getPriGrade("2");
List<GradeBean> lvl3 = getPriGrade("3");
data.put("lvl1", lvl1);
data.put("lvl2", lvl2);
data.put("lvl3", lvl3);
return data;
}
}
数据库工具类,用于连接数据库并执行SQL,返回对应的结果:
package com.any.servlet;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class DbUtil {
private static String url="jdbc:oracle:thin:@localhost:1521:orcl";
private static String user="scott";
private static String password="tiger";
private static Connection conn;
private static Connection getConnection(){
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
conn=DriverManager.getConnection(url, user, password);
return conn;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
public static int executeUpdate(String sql,Object... params){
PreparedStatement pmst = null;
try {
pmst = getConnection().prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
pmst.setObject(i+1, params[i]);
}
return pmst.executeUpdate();
} catch (SQLException e) {
try {conn.rollback();} catch (SQLException e1) {e1.printStackTrace();}
e.printStackTrace();
}
return -1;
}
public static ResultSet executeQuery(String sql,Object... params){
PreparedStatement pmst = null;
try {
pmst = getConnection().prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
pmst.setObject(i+1, params[i]);
}
return pmst.executeQuery();
} catch (SQLException e) {
try {conn.rollback();} catch (SQLException e1) {e1.printStackTrace();}
e.printStackTrace();
}
return null;
}
public static void closeConnection(){
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
经过以上步骤,就初步完成了三级联动选择菜单的制作。在页面加载时,必须首先选择第一层级下拉选项,从而进行后续选项的选择。