標籤:src prim lex 計數器 簡潔 host 清除 varchar menu
項目結構:
項目運行:
技術要點:
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 @[email protected]@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;/*!40014 SET @[email protected]@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;/*!40101 SET @[email protected]@SQL_MODE, SQL_MODE=‘NO_AUTO_VALUE_ON_ZERO‘ */;/*!40111 SET @[email protected]@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 [email protected]_SQL_MODE */;/*!40014 SET [email protected]_FOREIGN_KEY_CHECKS */;/*!40014 SET [email protected]_UNIQUE_CHECKS */;/*!40111 SET [email protected]_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 建立 PreparedStatementpstmt.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(); // 關閉 PreparedStatementconn.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 stubdoGet(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; // 用於儲存要更新選項的列表 idvar 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); // 設定 valueopt.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
Ajax-ajax執行個體4-多級聯動菜單