zoukankan      html  css  js  c++  java
  • Ajax-ajax实例4-多级联动菜单

    项目结构:

    项目运行:

    技术要点:

    1.4.1 技术要点
    在分析具体的实现代码之前,先介绍一下本例的几个技术要点。
    1 .选项的动态创建与删除
    document 对象的 createElement 方法可以用来创建一个 HTML 元素。创建好的元素可以通过
    setAttribute 方法设置其属性。基于以上两点,创建一个选项可以封装的方法如下:
    function createOption(value, text) {
    var opt = document.createElement("option");  //创建一个 option 节点
    opt.setAttribute("value", value); //设置 value
    opt.appendChild(document.createTextNode(text)); //给节点加入文本信息
    return opt;
    }
    当清除一个 select 列表的选项时,只需要重新设置选项的 length 属性为合适的值即可。本例中保留
    列表的第 1 个选项,因此将传入的列表对象 length 属性赋值为 1。
    function clearOptions(selNode) {
    selNode.length = 1; //设置列表长度为 1,仅保留默认选项
    selNode.options[0].selected = true; //选中默认选项
    }
    2 .修改上级列表时重新初始化所有下级列表
    当多级菜单全部选定后,如果用户重新选择了第一级列表,需要将其所有的下级列表全部初始化。
    为了实现这个需求,本例创建了一个全局变量 selArray,以数组形式由上到下存放各级菜单的 id。在需
    要初始化某级列表的下级时,对数组进行遍历即可确认下级列表的 id。
    3 .使用 JSON  格式传递选项数据
    JSON(JavaScript Object Notation)是一种用 JavaScript 对象符号格式化文本的简单方法。由于其
    方便人们阅读,易于机器解析和生成,所以主要被当作一种轻量级的数据交换格式来使用。JSON 主
    要支持两种类型的数据结构:“名称/值”对集合和有序值列表。下面详细介绍一下 JSON 支持的数据
    元素。
    -- 值:可以是双引号引起来的字符串(string)、数字(number)、布尔值、对象、数组等。示
    例如下:
    "Hello"
    2006
    true
    -- 名称/值对:名称是一个字符串,后面跟一个“:”,接着就应是这个名称对应的值,每个“名
    称/值”对以一个“,”分隔。示例如下:
    图 1.10 实例运行效果

    "Hello":"你好",
    "Year":2006,
    "isRight":true
    -- 对象:以“{”开始,“}”结束,是一个无序的“名称/值”对集合。示例如下:
    {
    "Hello":"你好",
    "Year":2006,
    "isRight":true
    }
    -- 数组:以“[”开始,“]”结束,是值的有序集合,数组中的值以“,”分隔。示例如下:
    [
    "item1",
    "item2",
    "item3"
    ]
    根据上面的介绍,发现利用“名称/值对”的形式可以方便地表示每一个 option 的内容。示例如下:
    -- option 原始格式
    <select>
    <option value="B11">列表 B 选项 11</option>
    <option value="B12">列表 B 选项 12</option>
    <option value="B13">列表 B 选项 13</option>
    </select>
    -- JSON 格式
    {
    'B11':'列表 B 选项 11',
    'B12':'列表 B 选项 12',
    'B13':'列表 B 选项 13'
    }
    可以看到,使用 JSON 格式表示选项数据简洁明了,容易理解,非常适合用来进行数据交换。

    数据库:

    /*
    SQLyog Ultimate v12.09 (64 bit)
    MySQL - 5.5.53 : Database - ajaxexample_4
    *********************************************************************
    */
    
    
    /*!40101 SET NAMES utf8 */;
    
    /*!40101 SET SQL_MODE=''*/;
    
    /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
    /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
    /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
    /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
    CREATE DATABASE /*!32312 IF NOT EXISTS*/`ajaxexample_4` /*!40100 DEFAULT CHARACTER SET utf8 */;
    
    USE `ajaxexample_4`;
    
    /*Table structure for table `menu` */
    
    DROP TABLE IF EXISTS `menu`;
    
    CREATE TABLE `menu` (
      `id` varchar(255) NOT NULL COMMENT '主键',
      `text` varchar(255) NOT NULL COMMENT '显示内容',
      `pid` varchar(255) NOT NULL DEFAULT '0' COMMENT '父id',
      `sort` int(11) NOT NULL DEFAULT '0' COMMENT '排序',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    /*Data for the table `menu` */
    
    insert  into `menu`(`id`,`text`,`pid`,`sort`) values ('A1','A1','0',0),('A2','A2','0',0),('A3','A3','0',0),('B1','B1','A1',0),('B2','B2','A1',0),('B3','B3','A1',0),('B4','B4','A2',0),('B5','B5','A2',0),('B6','B6','A2',0),('B7','B7','A3',0),('B8','B8','A3',0),('C1','C1','B1',0),('C2','C2','B1',0),('C3','C3','B2',0),('C4','C4','B3',0),('C5','C5','B4',0),('C6','C6','B4',0);
    
    /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
    /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
    /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
    /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
    

     

    GetOptionServlet.java:

    package com.gordon.servlet;
    
    import java.io.IOException;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    import javax.servlet.Servlet;
    import javax.servlet.ServletConfig;
    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.gordon.util.DBUtils;
    
    /**
     * Servlet implementation class GetOptionsServlet
     */
    @WebServlet("/GetOptionsServlet")
    public class GetOptionsServlet extends HttpServlet {
    	private static final long serialVersionUID = 1L;
    
    	/**
    	 * @see HttpServlet#HttpServlet()
    	 */
    	public GetOptionsServlet() {
    		super();
    		// TODO Auto-generated constructor stub
    	}
    
    	/**
    	 * @see Servlet#init(ServletConfig)
    	 */
    	public void init(ServletConfig config) throws ServletException {
    		// TODO Auto-generated method stub
    	}
    
    	/**
    	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
    	 *      response)
    	 */
    	protected void doGet(HttpServletRequest request, HttpServletResponse response)
    			throws ServletException, IOException {
    		
    		request.setCharacterEncoding("UTF-8");
    		response.setContentType("text/text; charset=UTF-8;");
    		
    		String selectedId = request.getParameter("selectedId"); // 获取 selectedId
    																// 参数
    		int counter = 0; // 计数器
    		StringBuffer opts = new StringBuffer("{"); // 保存选项信息
    		// 定义查询数据库的 SQL 语句
    
    		String sql = "select * from menu where pid = ? order by sort asc";
    		Connection conn = null; // 声明 Connection 对象
    		PreparedStatement pstmt = null; // 声明 PreparedStatement 对象
    		ResultSet rs = null; // 声明 ResultSet 对象
    		try {
    			conn = DBUtils.getConnection(); // 获取数据库连接
    			pstmt = conn.prepareStatement(sql); // 根据 sql 创建 PreparedStatement
    			pstmt.setString(1, selectedId); // 设置参数
    			rs = pstmt.executeQuery(); // 执行查询,返回结果集
    			while (rs.next()) { // 遍历结果集
    				// 如果不是第一项,追加一个“,”用于分隔选项
    				if (counter > 0) {
    					opts.append(",");
    				}
    				opts.append("'");
    				opts.append(rs.getString("id"));
    
    				opts.append("':'");
    				opts.append(rs.getString("text"));
    				opts.append("'");
    				counter++; // 计数器加 1
    			}
    		} catch (SQLException e) {
    			System.out.println(e.toString());
    		} catch (ClassNotFoundException cnfe) {
    			System.out.println(cnfe.toString());
    		}
    
    		try {
    			rs.close(); // 关闭结果集
    			pstmt.close(); // 关闭 PreparedStatement
    			conn.close(); // 关闭连接
    		} catch (Exception e) {
    			System.out.println(e.getMessage());
    		}
    
    		opts.append("}");
    
    		response.getWriter().print(opts.toString());
    
    	}
    
    	/**
    	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
    	 *      response)
    	 */
    	protected void doPost(HttpServletRequest request, HttpServletResponse response)
    			throws ServletException, IOException {
    		// TODO Auto-generated method stub
    		doGet(request, response);
    	}
    
    }
    

    DBUtils.java

    package com.gordon.util;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    
    public class DBUtils {
    	private static final String URL = "jdbc:mysql://localhost:3306/ajaxexample_4";
    	private static final String DRIVER = "com.mysql.jdbc.Driver";
    	private static final String USERNAME = "root";
    	private static final String PASSWORD = "root";
    
    	public static Connection getConnection() throws ClassNotFoundException, SQLException {
    		Class.forName(DRIVER);
    		return DriverManager.getConnection(URL, USERNAME, PASSWORD);
    	}
    }
    

    select.js

    var xmlHttp; // 用于保存 XMLHttpRequest 对象的全局变量
    var targetSelId; // 用于保存要更新选项的列表 id
    var selArray; // 用于保存级联菜单 id 的数组
    
    //初始化列表数组(按等级)
    function initSelArray() {
    	selArray = arguments; // arguments 对象包含了传入的所有参数
    }
    
    // 用于创建 XMLHttpRequest 对象
    function createXmlHttp() {
    	// 根据 window.XMLHttpRequest 对象是否存在使用不同的创建方式
    	if (window.XMLHttpRequest) {
    		xmlHttp = new XMLHttpRequest(); // FireFox、Opera 等浏览器支持的创建方式
    	} else {
    		xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); // IE 浏览器支持的创建方式
    	}
    }
    
    // 获取列表选项的调用函数
    function buildSelect(selectedId, targetId) {
    	if (selectedId == "") { // selectedId 为空串表示选中了默认项
    		clearSubSel(targetId); // 清除目标列表及下级列表中的选项
    		return; // 直接结束调用,不必向服务器请求信息
    	}
    	targetSelId = targetId; // 将传入的目标列表 id 赋值给 targetSelId 变量
    	createXmlHttp(); // 创建 XmlHttpRequest 对象
    	xmlHttp.onreadystatechange = buildSelectCallBack; // 设置回调函数
    	xmlHttp.open("GET", "GetOptionsServlet?selectedId=" + selectedId, true);
    	xmlHttp.send(null);
    }
    
    //根据传入的 value 和 text 创建选项
    function createOption(value, text) {
    	var opt = document.createElement("option"); // 创建一个 option 节点
    	opt.setAttribute("value", value); // 设置 value
    	opt.appendChild(document.createTextNode(text)); // 给节点加入文本信息
    	return opt;
    }
    
    // 获取列表选项的回调函数
    function buildSelectCallBack() {
    	if (xmlHttp.readyState == 4) {
    		// 将从服务器获得的文本转为对象直接量
    		var optionsInfo = eval("(" + xmlHttp.responseText + ")");
    		var targetSelNode = document.getElementById(targetSelId);
    		clearSubSel(targetSelId); // 清除目标列表及下级列表中的选项
    		// 遍历对象直接量中的成员
    		for ( var o in optionsInfo) {
    			// 在目标列表追加新的选项
    			targetSelNode.appendChild(createOption(o, optionsInfo[o]));
    		}
    	}
    }
    
    //清除传入的列表节点内所有选项
    function clearOptions(selNode) {
    	selNode.length = 1; // 设置列表长度为 1,仅保留默认选项
    	selNode.options[0].selected = true; // 选中默认选项
    }
    
    // 清除下级子列表选项
    function clearSubSel(targetId) {
    	var canClear = false; // 设置清除开关,初始值为假
    	for (var i = 0; i < selArray.length; i++) { // 遍历列表数组
    		if (selArray[i] == targetId) { // 当遍历至目标列表时,打开清除开关
    			canClear = true;
    		}
    		if (canClear) { // 从目标列表开始到最下级列表结束,开关始终保持打开
    			clearOptions(document.getElementById(selArray[i])); // 清除该级列表选项
    		}
    	}
    }
    

    index.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
    <head>
    <meta http-equiv="Content-type" content="text/html; charset=utf-8">
    <title>多级联动菜单</title>
    <script type="text/javascript" src="js/select.js"></script>
    </head>
    <!-- 页面加载完毕做两件事:1.初始化列表数组 2.为第 1 个列表赋值 -->
    <body onload="initSelArray('selA','selB','selC');buildSelect('0', 'selA')">
    	<h1>多级联动菜单</h1>
    	<table>
    		<tr>
    			<td>列表 A</td>
    			<td><select name="selA" id="selA" onchange="buildSelect(this.value, 'selB')">
    					<option value="" selected>------请选择------</option>
    			</select></td>
    		</tr>
    		<tr>
    			<td>列表 B</td>
    			<td><select name="selB" id="selB" onchange="buildSelect(this.value, 'selC')">
    					<option value="" selected>------请选择------</option>
    			</select></td>
    		</tr>
    		<tr>
    			<td>列表 C</td>
    			<td><select name="selC" id="selC">
    					<option value="" selected>------请选择------</option>
    			</select></td>
    		</tr>
    	</table>
    </body>
    </html>
    

    +++++++++++++++++++++++++++

    参考:ajax实用案例大全-1动态加载数据  https://wenku.baidu.com/view/c7897bf4700abb68a982fb91.html

  • 相关阅读:
    Force.com微信开发系列(二)用户消息处理
    Force.com微信开发系列(一) 后台配置
    【Android开发】之Fragment与Acitvity通信
    【Android开发】之Fragment重要函数讲解
    【Android开发】之Fragment生命周期
    【Android开发】之Fragment开发1
    【Android开发】之MediaPlayer的错误分析
    【Andorid开发框架学习】之Mina开发之服务器开发
    【Andorid开发框架学习】之Mina开发之客户端开发
    【Andorid开发框架学习】之Mina开发之Mina简介
  • 原文地址:https://www.cnblogs.com/hfultrastrong/p/7289641.html
Copyright © 2011-2022 走看看