这个关联菜单很多网站都有,估计很常用,之前没有看过JavaScript的语法书,所以摸索起来很困难,很多小BUG导致Coding速度非常慢,这么一个简单功能写了快2小时,无力吐槽,有空还是要看看基础的语法书。
实现的功能很简单,从数据库中取得两级列表,然后动态创建一级菜单,再根据一级菜单的选项创建二级菜单,结合到了Struts2,不过关键不在于此就不管了。
遇到的疑问:JS传参貌似不能传JAVA对象,其实很容易理解,因为JS和JAVA其实是独立的两样东西,不知道有没有什么办法是可以传List对象进JS中,如果有,本文的实现方法会显得很笨。
因为上面的提到的不能传List对象的原因,只能自己根据从数据库取得的List对象组装一个字符串,然后将字符串放到struts2的ValueStack中,再在JS中通过“${}”取出来,然后再分解字符串得到数组。
这个办法在条目较少的时候还是可以使用的,但是当菜单项很多的时候估计会影响效率,以后找到更加好的方法自然会另外再记录了。
实验二级菜单如下:
JAVA SE
|--多线程
|--swing
JAVA EE
|--hibernate
|--spring
|--struts
先在struts2的Action中取得List并组装字符串。
//连接数据库返回一个列表,包含一级栏目,一级栏目对象中包含二级栏目列表
this.items = (List<Item>) this.itemManager.getItems();
//要组装的字符串
itemsStrings="";
//迭代一级栏目
for(Item item:items){
for(Subitem subitem:item.getSubItems()){
//因为一级栏目是按顺序排列的,所以就不组装进字符串中,可能会引发异常,此处不考虑
//将二级栏目组装出字符串,以","分隔二级栏目
itemsStrings+=subitem.getSubItemName()+",";
}
//以";"分隔一级栏目
itemsStrings+=";";
}
其余代码如声明,GetSet方法就省略了。
JSP中JS代码如下
<script type="text/javascript"> function redirect(x) { var i=0; /*取得ValueStack中的原始字符串 */ var str = "${itemsStrings}"; /*保存2级栏目 */ var strs = new Array(); var subStrs=new Array(); /*split函数分割一级栏目,因为组装时末尾还会加入一个";"所以数组最后一个为空*/ strs = str.split(";"); /*取出二级栏目,注意长度*/ for(i=0;i<strs.length-1;i++){ /*二维数组,方便根据一级栏目选项编号取二级栏目*/ subStrs[i] = new Array(); /*根据","分割出二级栏目,同样注意数据最后一个为空*/ subStrs[i] = strs[i].split(","); } /*取得二级菜单对象Question为表单名字,sec为select名字*/ var sec = document.Question.sec; var m=0; /*从最后一个选项开始,将多余的选项移除*/ for(m=sec.options.length-1;m>subStrs[x].length-2;m--){ sec.remove(m); } /*根据二级栏目新建Option并放入二级菜单*/ for(i=0;i<subStrs[x].length-1;i++){ sec.options[i]=new Option(subStrs[x][i],subStrs[x][i]); } } </script>
JSP页面代码,用到部分struts2功能,不过很容易替换为其他代码。
<form id="Question" name="Question" action="/sshMyZNT/Question.action" method="post">
<!--一级菜单变化时调用JS函数,动态更新二级菜单 -->
<!--一级菜单 -->
<select name="first" onChange="redirect(this.options.selectedIndex)" >
<!--直接用struts2的标签创建一级菜单-->
<s:iterator var="item" value="#session.items">
<option value=" ${item.itemName}" >${item.itemName}</option>
</s:iterator>
</select>
<!--二级菜单 -->
<select name="sec" >
</select>
<!--初始化页面的时候就根据一级菜单动态创建二级菜单 -->
<script type="text/javascript">
redirect(document.Question.first.options.selectedIndex);
</script>
</form>
实测效果,由于小数据量的原因,组装字符串的做法影响不大,没见有BUG,暂时能用。
没学过JS和JSP的人实现关联菜单功能的方法还是比较笨重,感觉代码很臃肿而且组装字符串部分限制有点多,感觉很容易出问题,以后必然需要再找别的方法替换,学习JS和JSP后应该会再次思考这个问题,暂时记录下来以后比对思考。