jQuery实现级联下拉框实战(5)


Posted in Javascript onFebruary 08, 2017

今天来完成jQuery实战的级联下拉框效果。效果功能如下:

jQuery实现级联下拉框实战(5)

页面默认只提供汽车厂商,当选择了具体的某品牌汽车,汽车类型下拉框就会动态的显示出来,选择对应的类型,然后出来该汽车类型对应的轮胎类型下拉框显示出来,选中轮胎类型,页面的正中间会显示出汽车的图片。
思路分析如图:

jQuery实现级联下拉框实战(5)

建立我们的html页面,程序清单如下:

代码清单1.1: chainSelect.jsp

<body>
 <div class="loading">
 <p><img src="../image/data-loading.gif" alt="数据装载中" /></p>
 <p>数据装载中......</p>
 </div> 
 <div class="car">
 <span class="carname"> 
 汽车厂商:
 <select>
 <option value="" selected="selected">请选择汽车厂商</option>
 <option value="BMW">宝马</option>
 <option value="Audi">奥迪</option>
 <option value="VW">大众</option>
 </select>
 <img src="../image/pfeil.gif" alt="有数据">
 </span>
 <span class="cartype">
 汽车类型:
 <select>
 <option selected="selected">默认选项</option>
 <option>Test1</option>
 </select>
 <img alt="有数据" src="../image/pfeil.gif">
 </span>
 <span class="wheeltype">
 车轮类型:
 <select>
 <option selected="selected">默认选项</option>
 <option>Test1</option>
 </select>
 </span>
 </div>
 <div class="carimage">
 <p><img src="../image/img-loading.gif" alt="图片装载中" class="carloading"></p>
 <p><img src="" alt="汽车图片" class="carimg"></p>
 </div>
</body>

body体里面囊括了3个div,第一个div的作用是显示“数据正在装载中…”的图片和文字。第二个div显示级联下拉效果。第三个div显示车辆图片。

css代码如下:

代码清单1.2:chainSelect.css

.loading {
 width: 400px;
 margin: 0 auto;
/* visibility: hidden; */
}
.loading p {
 text-align: center;
}
p {
 margin: 0;
}
.car {
 text-align: center;
}
.carimage {
 text-align: center;
}
.cartype, .wheeltype, .carloading, .carimg, .car img {
 display: none;
}

代码清单1.3:chainSelect.js

$(document).ready(function(){
 //找到三个下拉框
 var carnameSelect = $(".carname").children("select");
 var cartypeSelect = $(".cartype").children("select");
 var wheeltypeSelect = $(".wheeltype").children("select");

 carnameSelect.change(function(){
 console.log("汽车厂商触发onChange事件");
 });
 cartypeSelect.change(function(){
 console.log("汽车类型触发onChange事件");
 });
 wheeltypeSelect.change(function(){
 console.log("车轮触发onChange事件");
 });
});

首先用jQuery的class选择器选择出三个下拉的框,当它们的值改变时触发对应的jQuery函数,对jQuery函数的处理才是重点的内容。
首先说到jQuery中的ajax交互。前一篇我们用到get()的请求方式,今天来用以用post()方法的请求方式。

jQuery.post(url, [data], [callback], [type])

概述:

通过远程 HTTP POST 请求载入信息.这是一个简单的 POST 请求功
能以取代复杂ajax() 。请求成功时可调>用回调函数。如果需要在出错时执行函数,请使用 $.ajax。

参数含义:

url:发送请求地址。
data:待发送 Key/value 参数。
callback:发送成功时回调函数。
type:返回内容格式,xml, html, script, json, text, _default。

案例如下:

代码清单1.4:demo.js

$(document).ready(function(){
 //发起ajax请求
 $.post("../chainSelect", {name: "John", time: "2pm"}, function(data){
 console.log("name : " + data.name);
 console.log("type : " + data.type);
 }, "json");
});

后台Serlvet处理如下(当然你可以使用java框架,也可以使用其他后台语言)。

代码清单1.5:demo.java

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ChainSelect extends HttpServlet {
 private static final long serialVersionUID = 1L;

 protected void doGet(HttpServletRequest request, HttpServletResponse response)
 throws ServletException, IOException {
 System.out.println("name = " + request.getParameter("name"));
 System.out.println("time = " + request.getParameter("time"));

 response.setCharacterEncoding("UTF-8");
 response.setContentType("application/json; charset=utf-8");
 String jsonStr = "{\"name\":\"fly\",\"type\":\"虫子\"}";
 PrintWriter out = null;
 try {
 out = response.getWriter();
 out.write(jsonStr);
 } catch (IOException e) {
 e.printStackTrace();
 } finally {
 if (out != null) {
 out.close();
 }
 }

 }

 protected void doPost(HttpServletRequest request, HttpServletResponse response)
 throws ServletException, IOException {
 doGet(request, response);
 }
}

别忘了纯Serlvet部属要在你的web.xml做配置。我的Serlvet的完整路进地址是:http://localhost:8080/JqueryStudy/chainSelect ,两句System.out.println()输出ajax传递过来的参数name和time。response.setCharacterEncoding(“UTF-8”)的作用是告诉浏览器字符串为utf-8的编码,防止中文乱码问题。response.setContentType(“application/json; charset=utf-8”)将返回的字符串以json格式形式返回。out对象是输出流,如果返回的是数组,格式应该如下:[“test1”, “test2”, “test3”],如果是json类,则格式如下:{“name”:”fly”,”type”:”虫子”}。

上诉案例返回的是json对象,后台控制台输出:

name = John
time = 2pm

前端浏览器的控制台输出:

name : fly
type : 虫子

Servlet返回数组的案例如下:

代码清单1.6:demo.java

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ChainSelect extends HttpServlet {
 private static final long serialVersionUID = 1L;

 protected void doGet(HttpServletRequest request, HttpServletResponse response)
 throws ServletException, IOException {
 System.out.println("name = " + request.getParameter("name"));
 System.out.println("time = " + request.getParameter("time"));

 response.setCharacterEncoding("UTF-8");
 response.setContentType("application/json; charset=utf-8");
 String jsonStr = "[\"test1\", \"test2\", \"test3\"]";
 PrintWriter out = null;
 try {
 out = response.getWriter();
 out.write(jsonStr);
 } catch (IOException e) {
 e.printStackTrace();
 } finally {
 if (out != null) {
 out.close();
 }
 }

 }

 protected void doPost(HttpServletRequest request, HttpServletResponse response)
 throws ServletException, IOException {
 doGet(request, response);
 }
}

前端jQuery代码:

$(document).ready(function(){
 //发起ajax请求
 $.post("../chainSelect", {name: "John", time: "2pm"}, function(data){
 for(var i = 0; i < data.length; i++) {
 console.log((i+1) + " : " + data[i]);
 }
 }, "json");
});

后台之需要给jsonStr赋值为数组格式而已,而前端jQuery代码由于接收到的字符串数组,所以这里需要用遍历数组的形式来遍历。

本案例的Servlet代码清单:

代码清单1.7:ChainSelect.java

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ChainSelect extends HttpServlet {
 private static final long serialVersionUID = 1L;

 protected void doGet(HttpServletRequest request, HttpServletResponse response)
 throws ServletException, IOException {
 response.setCharacterEncoding("UTF-8");
 response.setContentType("application/json; charset=utf-8");
 String jsonStr = this.getStr(request.getParameter("keyword"), request.getParameter("type"));
 PrintWriter out = null;
 try {
 out = response.getWriter();
 out.write(jsonStr);
 } catch (IOException e) {
 e.printStackTrace();
 } finally {
 if (out != null) {
 out.close();
 }
 }

 }

 private String getStr(String keyword, String type) {
 String jsonStr = "";
 if("top".equals(type)) {
 if("BMW".equals(keyword)) {
 jsonStr = "[\"316ti\", \"6ercupe\"]";
 } else if("Audi".equals(keyword)) {
 jsonStr = "[\"tt\"]";
 } else if("VW".equals(keyword)) {
 jsonStr = "[\"Golf4\"]";
 }
 } else if("sub".equals(type)) {
 if("tt".equals(keyword)) {
 jsonStr = "[\"rha\", \"rhb\", \"rhc\"]";
 } else if("316ti".equals(keyword)) {
 jsonStr = "[\"rha\", \"rhb\"]";
 } else if("6ercupe".equals(keyword)) {
 jsonStr = "[\"rha\", \"rhb\", \"rhc\"]";
 } else if("Golf4".equals(keyword)) {
 jsonStr = "[\"rha\", \"rhb\"]";
 }
 }
 return jsonStr;
 }
 protected void doPost(HttpServletRequest request, HttpServletResponse response)
 throws ServletException, IOException {
 doGet(request, response);
 }
}

代码清单1.7与清单1.6的区别是,后者多了getStr()的方法,该方法用于判断前端传递过来的是一级(top)下拉框的值,还是二级(sub)下拉框的值,并根据传递的keyword返回需要的字符串。与本后台交互的是程序清单1.8所示的代码。

程序清单1.8:chainSelect.js

/**
 * 级联下拉框效果
 */

$(document).ready(function(){
 //找到三个下拉框
 var carnameSelect = $(".carname").children("select");
 var cartypeSelect = $(".cartype").children("select");
 var wheeltypeSelect = $(".wheeltype").children("select");

 carnameSelect.change(function(){
 var carname = carnameSelect.val();
 if(carname != "") {
 //汽车厂商不为空发起ajax请求
 $.post("../chainSelect", {keyword: carname, type : "top"}, function(data){
 if(data != null && data.length != 0) {
  //清除上一次change的内容
  cartypeSelect.html("");
  $("<option value=''>请选择汽车类型</option>").appendTo(cartypeSelect);
  for(var i = 0; i < data.length; i++) {
  $("<option value='"+data[i]+"'>"+data[i]+"</option>").appendTo(cartypeSelect);
  }
  $(".cartype").show();
  carnameSelect.next("img").show();
 }
 }, "json");
 } else {
 //3.如果值为空,那么第二个下拉框所在span要隐藏起来,第一个下拉框后面的指示图片也要隐藏
 $(".cartype").hide();
 $(".wheeltype").hide();
 $(".carimage").hide();
 $(this).next("img").hide();
 }
 });

 cartypeSelect.change(function(){
 var cartype = cartypeSelect.val();
 if(cartype != "") {
 //汽车类型不为空发起ajax请求
 $.post("../chainSelect", {keyword: cartype, type : "sub"}, function(data){
 if(data != null && data.length != 0) {
  //清除上一次change的内容
  wheeltypeSelect.html("");
  $("<option value=''>请选择车轮类型</option>").appendTo(wheeltypeSelect);
  for(var i = 0; i < data.length; i++) {
  $("<option value='"+data[i]+"'>"+data[i]+"</option>").appendTo(wheeltypeSelect);
  }
  $(".wheeltype").show();
  cartypeSelect.next("img").show();
 }
 }, "json");
 } else {
 //汽车类型为空
 $(".wheeltype").hide();
 $(".carimage").hide();
 $(this).next("img").hide();
 } 
 });

 wheeltypeSelect.change(function(){
 //选中的车轮类型
 var wheeltype = wheeltypeSelect.val();

 if(wheeltype != "") {
 //选中的车辆厂商
 var carname = carnameSelect.val();
 //选中的车辆类型
 var cartype = cartypeSelect.val();

 //图片的名称
 var carimgName = carname + "_" + cartype + "_" + wheeltype + ".jpg";
 console.log("carimgName : " + carimgName);

 $(".carimage").show();

 $(".carimg").attr("src", "../image/" + carimgName).load(function(){
 //隐藏loading图片
 $(".carloading").hide("slow");
 });
 $(".carimage p img").show("slow");
 } else {
// alert("内容为空");
// $("img").hide();
 $(".carimage").hide();
 }
 });

 //给数据装载中的节点定义ajax事件,实现动画提示效果
 $(".loading").ajaxStart(function(){
 $(this).css("visibility", "visible");
 $(this).animate({
 opacity: 1
 },0);
 }).ajaxStop(function(){
 $(this).animate({
 opacity: 0
 },500);
 });
});

jQuery代码的思路是,用class选择器选择出三个下拉框,赋值给变量carnameSelect,cartypeSelect,wheeltypeSelect,默认carnameSelect下拉框是显示的,其他下拉框是隐藏。然后给他们三者注册change()事件,当用户选择下拉框的值的时候执行事件函数体里面的内容。这里我以第一级下拉框为例来讲解处理的过程。如果用户选择了第一级下拉框”汽车厂商”的”宝马”,则执行如下代码:

carnameSelect.change(function(){
 var carname = carnameSelect.val();
 if(carname != "") {
 //汽车厂商不为空发起ajax请求
 $.post("../chainSelect", {keyword: carname, type : "top"}, function(data){
 if(data != null && data.length != 0) {
  //清除上一次change的内容
  cartypeSelect.html("");
  $("<option value=''>请选择汽车类型</option>").appendTo(cartypeSelect);
  for(var i = 0; i < data.length; i++) {
  $("<option value='"+data[i]+"'>"+data[i]+"</option>").appendTo(cartypeSelect);
  }
  $(".cartype").show();
  carnameSelect.next("img").show();
 }
 }, "json");
 } else {
 //3.如果值为空,那么第二个下拉框所在span要隐藏起来,第一个下拉框后面的指示图片也要隐藏
 $(".cartype").hide();
 $(".wheeltype").hide();
 $(".carimage").hide();
 $(this).next("img").hide();
 }
 });

先将第一级下拉框内容取出来,如果值为空,那么第二个下拉框所在span要隐藏起来,第一个下拉框后面的指示图片也要隐藏。如果有内容, 则用该行代码$.post(“../chainSelect”, {keyword: carname, type : “top”}, function(data){}, “json”)向上诉的Serlvet发起post请求,post的第一个参数是Serlvet的后台地址,第二个参数画括号括起来的json数据,第三个参数是回调函数,第四个参数”json”表明发送的json数据。在回调函数中,参数data接收Serlvet返回的值,由于Serlvet返回的是可以解析为字符串数组的数据,所以用for循环来遍历得到的数据,并生成option新节点appenTo()插入到select之后。

程序清单1.8中,值得注意的地方还有$(“.loading”).ajaxStart(function(){}).ajaxStop(function(){}),这是为了美化汽车图片加载的代码。这里用到jQuery的动画专用效果的animate(),使程序淡入淡出更加的和谐。

到此几乎把级联效果实现了,但是如果在高并发环境下,每次用户切换选项都向服务器发送请求,服务器的压力可能过大。所以这里我们用jQuery的缓存来保存那些已经缓存过的请求。可以使用jQuery的data()方法。

定义和用法

从被选元素中返回附加的数据。

$(selector).data(name)

name 可选。规定要取回的数据的名称。
如果没有规定名称,则该方法将以对象的形式从元素中返回所有存储的数据。

向元素附加数据

$(selector).data(name,value)

name 必需。规定要设置的数据的名称。
value 必需。规定要设置的数据的值。
data()的使用案例如程序清单1.9:

<html>
<head>
<script type="text/javascript" src="/jquery/jquery.js"></script>
<script type="text/javascript">
$(document).ready(function(){
 $("#btn1").click(function(){
 $("div").data("greeting", "Hello World");
 });
 $("#btn2").click(function(){
 alert($("div").data("greeting"));
 });
});
</script>
</head>
<body>
<button id="btn1">把数据添加到 div 元素</button><br />
<button id="btn2">获取已添加到 div 元素的数据</button>
<div></div>
</body>
</html>

加上缓存之后的完整jQuery代码如下程序清单。
程序清单2.0:chainSelect.js

/**
 * 级联下拉框效果
 */

$(document).ready(function(){
 //找到三个下拉框
 var carnameSelect = $(".carname").children("select");
 var cartypeSelect = $(".cartype").children("select");
 var wheeltypeSelect = $(".wheeltype").children("select");

 carnameSelect.change(function(){
 var carname = carnameSelect.val();
 if(carname != "") {
 if (!carnameSelect.data(carname)) {
 //汽车厂商不为空发起ajax请求
 $.post("../chainSelect", {keyword: carname, type : "top"}, function(data){
  if(data != null && data.length != 0) {
  //清除上一次change的内容
  cartypeSelect.html("");
  $("<option value=''>请选择汽车类型</option>").appendTo(cartypeSelect);
  for(var i = 0; i < data.length; i++) {
  $("<option value='"+data[i]+"'>"+data[i]+"</option>").appendTo(cartypeSelect);
  }
  $(".cartype").show();
  carnameSelect.next("img").show();
  }
  //将data放入缓存
  carnameSelect.data(carname, data);
 }, "json");
 } else {
 //从缓存中取出数据
 var data = carnameSelect.data(carname);
 if(data != null && data.length != 0) {
  //清除上一次change的内容
  cartypeSelect.html("");
  $("<option value=''>请选择汽车类型</option>").appendTo(cartypeSelect);
  for(var i = 0; i < data.length; i++) {
  $("<option value='"+data[i]+"'>"+data[i]+"</option>").appendTo(cartypeSelect);
  }
  $(".cartype").show();
  carnameSelect.next("img").show();
 }
 }
 } else {
 //3.如果值为空,那么第二个下拉框所在span要隐藏起来,第一个下拉框后面的指示图片也要隐藏
 $(".cartype").hide();
 $(".wheeltype").hide();
 $(".carimage").hide();
 $(this).next("img").hide();
 }
 });

 cartypeSelect.change(function(){
 var cartype = cartypeSelect.val();
 if(cartype != "") {
 if(!cartypeSelect.data(cartype)) {
 //汽车类型不为空发起ajax请求
 $.post("../chainSelect", {keyword: cartype, type : "sub"}, function(data){
  if(data != null && data.length != 0) {
  //清除上一次change的内容
  wheeltypeSelect.html("");
  $("<option value=''>请选择车轮类型</option>").appendTo(wheeltypeSelect);
  for(var i = 0; i < data.length; i++) {
  $("<option value='"+data[i]+"'>"+data[i]+"</option>").appendTo(wheeltypeSelect);
  }
  $(".wheeltype").show();
  cartypeSelect.next("img").show();
  }
  cartypeSelect.data(cartype, data);
 }, "json");
 } else {
 var data = cartypeSelect.data(cartype);
 if(data != null && data.length != 0) {
  //清除上一次change的内容
  wheeltypeSelect.html("");
  $("<option value=''>请选择车轮类型</option>").appendTo(wheeltypeSelect);
  for(var i = 0; i < data.length; i++) {
  $("<option value='"+data[i]+"'>"+data[i]+"</option>").appendTo(wheeltypeSelect);
  }
  $(".wheeltype").show();
  cartypeSelect.next("img").show();
 }
 }
 } else {
 //汽车类型为空
 $(".wheeltype").hide();
 $(".carimage").hide();
 $(this).next("img").hide();
 } 
 });

 wheeltypeSelect.change(function(){
 //选中的车轮类型
 var wheeltype = wheeltypeSelect.val(); 
 if(wheeltype != "") {
 //选中的车辆厂商
 var carname = carnameSelect.val();
 //选中的车辆类型
 var cartype = cartypeSelect.val();

 //图片的名称
 var carimgName = carname + "_" + cartype + "_" + wheeltype + ".jpg";

 $(".carimage").show(); 
 //通过Javascript中的Image对象预装载图片
 var cacheimg = new Image();
 $(cacheimg).attr("src", "../image/" + carimgName).load(function(){
 //隐藏loading图片
 $(".carloading").hide("slow");
 $(".carimg").attr("src", "../image/" + carimgName);
 });


 $(".carimage p img").show("slow");
 } else {
 $(".carimage").hide();
 }
 });

 //给数据装载中的节点定义ajax事件,实现动画提示效果
 $(".loading").ajaxStart(function(){
 $(this).css("visibility", "visible");
 $(this).animate({
 opacity: 1
 },0);
 }).ajaxStop(function(){
 $(this).animate({
 opacity: 0
 },500);
 });
});

用了data()之后,当用户选择了下拉框,并不是直接奔着服务器请求而去的,而是先判断缓存是否为空,carnameSelect.data(carname)。如果为空,则发起ajax请求,并将返回的结果放进缓存carnameSelect.data(carname, data)。如果不为空,在循环添加option节点之前data从缓存中拿到var data = carnameSelect.data(carname)。同样的,图片的缓存放进我们的Image对象中var cacheimg = new Image(),这行代码往后的第一行和第四行将缓存中的图片取出并显示出来。

代码下载地址:https://github.com/shizongger/JqueryInAction

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript 模拟点击广告
Jan 02 Javascript
jquery indexOf使用方法
Aug 19 Javascript
基于jquery扩展漂亮的下拉框可以二次修改
Nov 19 Javascript
js通过location.search来获取页面传来的参数
Sep 11 Javascript
详解JavaScript逻辑Not运算符
Dec 04 Javascript
angularjs封装bootstrap时间插件datetimepicker
Jun 20 Javascript
jQuery+CSS3实现四种应用广泛的导航条制作实例详解
Sep 17 Javascript
canvas 绘制圆形时钟
Feb 22 Javascript
利用Angular.js编写公共提示模块的方法教程
May 28 Javascript
vue element-ui 绑定@keyup事件无效的解决方法
Mar 09 Javascript
解决Layui 表单提交数据为空的问题
Aug 15 Javascript
Vue-不允许嵌套式的渲染方法
Sep 13 Javascript
webpack入门+react环境配置
Feb 08 #Javascript
JavaScript实现鼠标点击导航栏变色特效
Feb 08 #Javascript
jQuery实现优雅的弹窗效果(6)
Feb 08 #Javascript
JavaScript中的子窗口与父窗口的互相调用问题
Feb 08 #Javascript
深入理解js中的加载事件
Feb 08 #Javascript
滚动条的监听与内容随着滚动条动态加载的实现
Feb 08 #Javascript
JQuery页面随滚动条动态加载效果的简单实现(推荐)
Feb 08 #Javascript
You might like
Win9x/ME下Apache+PHP安装配置
2006/10/09 PHP
table标签的结构与合并单元格的实现方法
2013/07/24 PHP
php设置允许大文件上传示例代码
2014/03/10 PHP
PHP实现手机号码中间四位用星号(*)隐藏的自定义函数分享
2014/09/27 PHP
js宝典学习笔记(上)
2007/01/10 Javascript
下拉列表select 由左边框移动到右边示例
2013/12/04 Javascript
js实现多选项切换导航菜单的方法
2015/02/06 Javascript
Node.js中使用socket创建私聊和公聊聊天室
2015/11/19 Javascript
JavaScript+html5 canvas绘制的圆弧荡秋千效果完整实例
2016/01/26 Javascript
JQuery导航菜单选择特效
2016/04/11 Javascript
Easyui 之 Treegrid 笔记
2016/04/29 Javascript
js获取所有checkbox的值的简单实例
2016/05/30 Javascript
移动端使用localStorage缓存Js和css文的方法(web开发)
2016/09/20 Javascript
jquery css实现邮箱自动补全
2016/11/14 Javascript
用jQuery旋转插件jqueryrotate制作转盘抽奖
2017/02/10 Javascript
Vue学习之路之登录注册实例代码
2017/07/06 Javascript
写给vue新手们的vue渲染页面教程
2017/09/01 Javascript
jQuery动态添加li标签并添加属性和绑定事件方法
2018/02/24 jQuery
Angular 容器部署的方法
2018/04/17 Javascript
浅析Vue项目中使用keep-Alive步骤
2018/07/27 Javascript
详解微信小程序input标签正则初体验
2018/08/18 Javascript
jQuery实现上下滚动公告栏详细代码
2018/11/21 jQuery
python 解析XML python模块xml.dom解析xml实例代码
2014/02/07 Python
Django与遗留的数据库整合的方法指南
2015/07/24 Python
Django基于ORM操作数据库的方法详解
2018/03/27 Python
python进行文件对比的方法
2018/12/24 Python
python 中xpath爬虫实例详解
2019/08/26 Python
英国鞋网:Rubber Sole
2020/03/03 全球购物
企业厂长岗位职责
2013/12/17 职场文书
护理毕业生自我鉴定
2014/02/11 职场文书
优秀应届毕业生自荐书
2014/06/29 职场文书
2014幼儿园教师个人工作总结
2014/11/08 职场文书
2016年社会主义核心价值观心得体会
2016/01/21 职场文书
《称赞》教学反思
2016/02/17 职场文书
浅谈Python numpy创建空数组的问题
2021/05/25 Python
使用 Apache Dubbo 实现远程通信(微服务架构)
2022/02/12 Servers