怎么实现级联菜单?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了怎么实现级联菜单?相关的知识,希望对你有一定的参考价值。

这是百度知道里设置分类的级联菜单,我也想实现一个类似的,请问应该怎么实现?我java web的知识懂得不多,所以最好能有一些学习教程。谢谢!

对于一个多条件的查询,我们希望在选择了一个菜单项后,另外一个下拉菜单能够根据我们所选择的第一个菜单项显示其所有子菜单项。这就是本文提到的级联菜单问题。级联菜单实现的方法有很多,本文根据笔者所做的一个小实验,简单的介绍一下如何通过XML来实现级联菜单的功能。

首先要定义一个XML文件,用以存放级联菜单的信息,我们命名为query.xml,其代码如下:
<?xml version="1.0" encoding="gb2312"?>
<info>
<course>
<text>软件工程</text>
<value>1</value>
</course>
<course>
<text>数据结构</text>
<value>2</value>
</course>
<course>
<text>操作系统</text>
<value>3</value>
</course>
<course>
<text>计算机组成原理</text>
<value>4</value>
</course>
<teacher>
<text>张老师</text>
<value>1</value>
</teacher>
<teacher>
<text>李老师</text>
<value>2</value>
</teacher>
<teacher>
<text>刘老师</text>
<value>3</value>
</teacher>
<teacher>
<text>王老师</text>
<value>4</value>
</teacher>
<class>
<text>一班</text>
<value>1</value>
</class>
<class>
<text>二班</text>
<value>2</value>
</class>
<class>
<text>三班</text>
<value>3</value>
</class>
<class>
<text>四班</text>
<value>4</value>
</class>
</info>

然后再创建一个html文件,命名为query.html
在query.html里,首先创建一个表单
<form id="queryForm">
<select id="keyword" name="keyword" onChange="showDetail()">
<option value="default">default</option>
<option value="1">课程</option>
<option value="2">教师</option>
<option value="3">班级</option>
</select>
<select id="content" name="content" onChange="showValue()">
<option value="default">default</option>
</select>
</form>
从上面的代码可以看出,当我们选择第一级菜单时,会触发showDetail方法,这是通过javascript来实现的,因此我们还需要定义一个showDetail方法,其实现代码如下:
function showDetail()
var document_xml = new ActiveXObject("Microsoft.XMLDOM");
document_xml.load("query.xml"); //加载info.xml
var RootNode = document_xml.documentElement; //获得info.xml文档的根节点

var keyword = document.getElementByIdx("keyword").value;
var details; //用以存放二级菜单内容,是一个数组对象
var content = document.getElementByIdx("content");
content.options.length = 0;//先清空
if(keyword=="default")
var option = new Option("default","default");
content.add(option);
else
if(keyword=="1")
details = document_xml.getElementsByTagName_r("course");
else if(keyword=="2")
details = document_xml.getElementsByTagName_r("teacher");
else if(keyword=="3")
details = document_xml.getElementsByTagName_r("class");

for(var i=0;i<details.length;i++)
var xText = details[i].childNodes[0].firstChild.nodeValue; //获取文本
var xValue = details[i].childNodes[1].firstChild.nodeValue; //获取文本以应的值
var option = new Option(xText,xValue);
content.add(option);



从上面的代码可以看出,showDetail方法会根据一级菜单选项的不同显示对应的子菜单。这里涉及到通过JavaScript来读取xml文件的操作,可以参见源码的注释部分,记得结合xml文件里的内容一起看哦。

二级菜单显示出来之后,我们就可以进行选择了,选择之后,会调用showValue方法,把选到的子菜单项的value和text显示出来。showValue的定义如下:
function showValue()
var content= document.getElementByIdx("content");
var contentText = content.options[content.selectedIndex].text; //获取text值
var contentValue = document.getElementByIdx("content").value; //获取文本
alert(contentValue+" "+contentText);

在这个方法里,要注意option当中text值的获取,它与select表单域的value的获取方式不大一样,详见代码及其注释。

把两个方法封装在<head></head>之间,记得要写上<script language="javascript">和</script>了,然后你直接打开query.xml就可以看到效果了。

不知是否对楼主有用,希望对楼主有所帮助。追问

你这种是下拉框的那种形式,跟我给的图不一样呀

参考技术A 代码如下:
<!DOCTYPE html>
<html>
<head>
<title>menu.html</title>

<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="this is my page">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">

<link rel="stylesheet" type="text/css" href="../css/menu.css">
<script type="text/javascript" src="../js/jquery-1.10.2.js"></script>
<script type="text/javascript" src="../js/menu.js"></script>

</head>

<body>
<ul>
<li class="menu">
<div class="title">
<span>电脑数码类产品</span>
</div>
<ul class="content">
<li class="optn"><a href="#">笔记本</a>
<ul class="tip">
<li><a href="#">笔记本1</a></li>
<li><a href="#">笔记本1</a></li>
<li><a href="#">笔记本1</a></li>
<li><a href="#">笔记本1</a></li>
</ul>
</li>

<li class="optn"><a href="#">移动硬盘</a>
<ul class="tip">
<li><a href="#">移动硬盘1</a></li>
<li><a href="#">移动硬盘1</a></li>
<li><a href="#">移动硬盘1</a></li>
<li><a href="#">移动硬盘1</a></li>

</ul>
</li>
<li class="optn"><a href="#">电脑软件</a>
<ul class="tip">
<li><a href="#">电脑软件1</a></li>
<li><a href="#">电脑软件1</a></li>
<li><a href="#">电脑软件1</a></li>
<li><a href="#">电脑软件1</a></li>

</ul>
</li>
<li class="optn"><a href="#">数码产品</a>
<ul class="tip">
<li><a href="#">数码产品1</a></li>
<li><a href="#">数码产品1</a></li>
<li><a href="#">数码产品1</a></li>
<li><a href="#">数码产品1</a></li>
</ul>
</li>

</ul>
</li>

</ul>
</body>
</html>

menu.css
代码如下:
@CHARSET "UTF-8";

*
margin: 0px;
padding: 0px;



ul,li
list-style-type: none;



.menu
width: 190px;
border: 1px red solid;
background-color: #fffdd2;


.optn
width: 190px;
line-height: 28px;
border-top: 1px red dashed;



.content
padding-top:10px;
clear: left;


a
text-decoration: none;
color: #666;
padding: 10px;

.optnFocus
background-color: #fff;
font-weight: bold;



div
padding: 10px;


.tip
width: 190px;
border: 2px red solid;
position: absolute;
background-color: #fff;
display: none;


.tip li
line-height: 23px;


接下来就是主要的jquery代码:menu.js
代码如下:
$(function()

var curY;//获取所选想的TOP
var curH;//获取所选的Height
var curW;//获取所选的width
var objL;//获取当前对象

//自定义函数用于获取当前位置
function setInitValue(obj)
curY=obj.offset().top;
curH=obj.height();
curW=obj.width();


//设置当前所选项的鼠标滑动事件
$(".optn").mouseover(function()
objL=$(this);//获取当前对象
setInitValue(objL);
var allY=curY-curH +"px";

objL.addClass("optnFocus");
//获取气元素下的下一个ul
$(".tip",this).show().css("top":allY,"left":curW);;

);
$(".optn").mouseout(function()

$(this).removeClass("optnFocus");
$(".tip",this).hide();

);

//为了防止移到子菜单时子菜单不见,我们也要为子菜单设置鼠标事件

$(".tip").mouseover(function()

$(this).show();
objL=$(this).prev("li");
setInitValue(objL);
objL.addClass("optnFocus");
);

$(".tip").mouseout(function()
$(this).hide();
$(this).prev("li").removeClass("optnFocus");

);
);

注意要点:

1.由于用的是较高版本的jquery文件库,所以有些方法是不支持的,例如获取下一个元素的第一个子元素next(erp),在10.1中是不支持的,所以换了一种方法$(chiled,select),表示在select的范围进行元素的选择

2.整个效果的实现我们还要为子选项框绑定鼠标事件,目的就是为了不在移动到子选项卡中,突然消失。
参考技术B   先在一个不用的sheet里做好下拉菜单内容。然后选中以级联菜单形式输入的单元格或区域,在菜单里找到“数据有效性”,应该是数据菜单,然后“设置”里面的“允许”框里选择“序列”,下面的“来源”框里选定做好的下拉菜单内容,确定。 参考技术C 学学页面上如何使用ajax追问

ajax基础的我会,就是不会这个,能帮忙解决吗?

追答

本来只有一个选择框,其他都是隐藏或者动态生成的。根据第一个选择栏的结果发出请求,把刷选出的2级菜单显示出来

[伪] 级联菜单,两级菜单

[伪] 级联菜单,两级菜单

这段时间需要做一个类似效果的一个菜单样式,所以就查了各种文档,各种百度各种搜索,的确也是搜到了不少的第三方组件,比如(CascadingMenuViewLib)就是其中一个,但是,我脑子笨,研究了3天左右的时间,改不成我需要得样子,So...我用我自己的方式,实现了这个效果(对了,还没有完全实现,因为TextView被点中的样式我还没有设置,不过这都是小事情了..)

技术分享技术分享

在这里,我提供一个思路,代码很简单,当然,我也会附一些上来,好的,我首先说一下思路


首先,我们的xml文件是一个横向的LinearLayout,左边是一个纵向的LinearLayout(里面装着一个个的TextView),右边是一个ListView代码如下

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <LinearLayout
            android:id="@+id/tools_scrlllview"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="2.5"
            android:orientation="vertical">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical">
                <!-- 这个分类   我就直接给他定死了  就好  因为就那几个分类咩-->
                <LinearLayout
                    android:id="@+id/activity_orders_style_choose_ll_mbc"
                    android:layout_width="100dp"
                    android:layout_height="wrap_content"
                    android:background="@drawable/selector_choose_ll"
                    android:clickable="true"
                    android:gravity="center"
                    android:orientation="horizontal"
                    android:padding="5dp">

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginLeft="20dp"
                        android:text="主色"
                        android:textSize="16sp" />

                    <ImageView
                        android:layout_width="20dp"
                        android:layout_height="30dp"
                        android:scaleType="fitXY"
                        android:src="@drawable/title_left_back_press" />
                </LinearLayout>

                <LinearLayout
                    android:id="@+id/activity_orders_style_choose_ll_installway"
                    android:layout_width="100dp"
                    android:layout_height="wrap_content"
                    android:background="@drawable/selector_choose_ll"
                    android:clickable="true"
                    android:gravity="center"
                    android:orientation="horizontal"
                    android:padding="5dp">

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginLeft="20dp"
                        android:text="安装"
                        android:textSize="16sp" />

                    <ImageView
                        android:layout_width="20dp"
                        android:layout_height="30dp"
                        android:scaleType="fitXY"
                        android:src="@drawable/title_left_back_press" />
                </LinearLayout>

                <LinearLayout
                    android:id="@+id/activity_orders_style_choose_ll_thickness"
                    android:layout_width="100dp"
                    android:layout_height="wrap_content"
                    android:background="@drawable/selector_choose_ll"
                    android:clickable="true"
                    android:gravity="center"
                    android:orientation="horizontal"
                    android:padding="5dp">

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginLeft="20dp"
                        android:text="壁厚"
                        android:textSize="16sp" />

                    <ImageView
                        android:layout_width="20dp"
                        android:layout_height="30dp"
                        android:scaleType="fitXY"
                        android:src="@drawable/title_left_back_press" />
                </LinearLayout>

                <LinearLayout
                    android:id="@+id/activity_orders_style_choose_ll_twine"
                    android:layout_width="100dp"
                    android:layout_height="wrap_content"
                    android:background="@drawable/selector_choose_ll"
                    android:clickable="true"
                    android:gravity="center"
                    android:orientation="horizontal"
                    android:padding="5dp">

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginLeft="20dp"
                        android:text="网丝"
                        android:textSize="16sp" />

                    <ImageView
                        android:layout_width="20dp"
                        android:layout_height="30dp"
                        android:scaleType="fitXY"
                        android:src="@drawable/title_left_back_press" />
                </LinearLayout>

                <LinearLayout
                    android:id="@+id/activity_orders_style_choose_ll_size"
                    android:layout_width="100dp"
                    android:layout_height="wrap_content"
                    android:layout_marginBottom="8dp"
                    android:background="@drawable/selector_choose_ll"
                    android:clickable="true"
                    android:gravity="center"
                    android:orientation="horizontal"
                    android:padding="5dp">

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginLeft="20dp"
                        android:text="尺寸"
                        android:textSize="16sp" />

                    <ImageView
                        android:layout_width="20dp"
                        android:layout_height="30dp"
                        android:scaleType="fitXY"
                        android:src="@drawable/title_left_back_press" />
                </LinearLayout>
            </LinearLayout>


        </LinearLayout>
        <!--看看看看 我用GridView多好?填充起来一点儿也不费事-->
        <ListView
            android:id="@+id/activity_orders_style_choose_lv_right"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:layout_weight="1"
            android:clickable="false"
            android:orientation="vertical" />
    </LinearLayout>

这个XML写完之后 大致是这个效果技术分享

之后 我们需要写一个Adapter,里面的代码如下,没什么好说的,也有注释

/**
 * 是一个适配器 为了每次更新右边的布局 做的一个适配器..||
 * <p/>
 * 构造函数中有参数 来决定到底是填充哪一个布局
 */
public class MyStyleChooseAdapter extends BaseAdapter {
    //    只有一条的视图数据源
    private List mViews;
    //    数据数据源
    private List mDatas;
    //    上下文
    private Activity mActivity;
    //    一个参数 判断是加载哪一个布局  0. msc  1. installway 2. thickness 3. twine 4.size
    private int flag;

    /**
     * 构造函数
     *
     * @param mActivity
     */
    public MyStyleChooseAdapter(Activity mActivity, int flag) {
        this.mActivity = mActivity;
        this.flag = flag;
    }

    @Override
    public int getCount() {
//        只有一条
        return 1;
    }

    @Override
    public Object getItem(int position) {
        return 1;
    }

    @Override
    public long getItemId(int position) {
        return 1;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
//        就一个布局  也不用考虑优化问题吧  直接填充就是了
        LinearLayout ll = null;
//        填充主色布局...好麻烦
        if (flag == 0) {
            ll = (LinearLayout) mActivity.getLayoutInflater().inflate(R.layout.item_style_choose_mbc, null);
            return ll;
        }
//        安装方式的布局 就是一个RadioGroup
        if (flag == 1) {
            ll = (LinearLayout) mActivity.getLayoutInflater().inflate(R.layout.item_style_choose_installway, null);
            return ll;
        }
//        壁厚的布局
        if (flag == 2) {
            ll = (LinearLayout) mActivity.getLayoutInflater().inflate(R.layout.item_style_choose_thickness, null);
            return ll;
        }
//        网丝的布局
        if (flag == 3) {
            ll = (LinearLayout) mActivity.getLayoutInflater().inflate(R.layout.item_style_choose_twine, null);
            return ll;
        }
//        尺寸的布局
        if (flag == 4) {
            ll = (LinearLayout) mActivity.getLayoutInflater().inflate(R.layout.item_style_choose_size, null);
            return ll;
        }
        return ll;
    }
}

 

之后,我们只需要在主界面上,为这几个TextView添加点击事件,这个效果就算是完成了..总感觉这样做有点傻瓜,所以发上来,让大牛们给我提一下建议,同时也起个记录作用吧!

技术分享
//            主色点击事件
            case R.id.activity_orders_style_choose_ll_mbc:
                lv_right.setAdapter(new MyStyleChooseAdapter(OrdersStyleChooseActivity.this, 0));
                break;
//            安装方式点击事件
            case R.id.activity_orders_style_choose_ll_installway:
                lv_right.setAdapter(new MyStyleChooseAdapter(OrdersStyleChooseActivity.this, 1));
                break;
//            壁厚点击事件
            case R.id.activity_orders_style_choose_ll_thickness:
                lv_right.setAdapter(new MyStyleChooseAdapter(OrdersStyleChooseActivity.this, 2));
                break;
//            网丝点击事件
            case R.id.activity_orders_style_choose_ll_twine:
                lv_right.setAdapter(new MyStyleChooseAdapter(OrdersStyleChooseActivity.this, 3));
                break;
//            尺寸点击事件
            case R.id.activity_orders_style_choose_ll_size:
                lv_right.setAdapter(new MyStyleChooseAdapter(OrdersStyleChooseActivity.this, 4));
                break;
View Code

 

最后呢 附上我的一个小心得...

 

RadioButton需要加id并且和RadioGroup结合使用才可以互斥,要是不加id 再设置某一个RadioButton的checked为true时,会出现它永远为点击状态的现象

以上是关于怎么实现级联菜单?的主要内容,如果未能解决你的问题,请参考以下文章

ASP+ACCESS 级联下拉菜单

js实现级联菜单(没有后台)

yii实现级联下拉菜单的方法

[伪] 级联菜单,两级菜单

vue利用级联选择器实现全国省市区乡村五级菜单联动

级联菜单