jQuery插件实现多级联动菜单效果


Posted in Javascript onDecember 01, 2015

开发中,有好多地方用到联动菜单,以前每次遇到联动菜单的时候都去重新写,代码重用率很低,前几天又遇到联动菜单的问题,总结了下,发现可以开发一个联动菜单的功能,以后想用的时候就方便多了。项目中每个页面都有引用jQuery,,开发个jQuery联动菜单插件,说动手就动手,下面跟大家分享分享。

我用的jQuery插件方式

(function($){
 $.fn.casmenu=function(argvs){
   //your code
 }
})(jQuery);

其中jQuery传入的是jquery对象,需要在扩展之前引用。在扩展中同样使用jQuery的短格式$。

$.fn是指jquery的命名空间,加在fn上的方法及属性,会对jquery实例每一个有效,看看下面的jquery源码101行左右:

jQuery.fn = jQuery.prototype = {
 ......
}

比如说后面要开发的$.fn.casmenu(),定义之后,在后面的jquery对象都可以使用该方法。

这里还有一种扩展的方法:

$.extend({
 funName: function(){
  //your code
 },
});

这种扩展方法和上面的是有区别的,要是拿类做类比的话,$.extend这种方法相当于类中的静态方法,上面的一种方式相当于非静态方法,必须有对象才可以使用。简单的理解,是下面这样的:

//$.fn.casemenu 方式扩展的方法,必须在有jquery对象的时候才可以使用
$("#mydiv").casmenu();

//$.extend({}) 方式扩展的方法,可以直接使用
$.add(2,3);

设计思路
首先是层级菜单的数据保存方式,看看下面的数据:

var levels={
 //内容中有引号,必须使用单引号,外引号必须用双引号
 //name => value
 1:{
  退出应用: "code1003",
  登录界面:"code1004",
  跳转至个人资料界面:"code1005",
 },
 2:{
  退出应用:{
   应用1:"gameid1",
   应用2:"gameid2",
   应用3:"gameid3",
   应用4:"gameid4",
   应用5:"gameid5",   
  },
  跳转至个人资料界面:{
   主界面:"main interface",
  }
 },
 3:{
  应用1:{
   中级场:"12",
   高级场:"13",
   职业场:"14",
   比赛场:"15",
  }
 }
}

对象levels中的直接键值1、2、3代表菜单的层级,没有就不用些,每一项name=>value代表select中option的名称和value。

层级有规律,某一层级中的某一项要是有下一级菜单,在下一层及有该项的名称,就像levels[1]['退出应用']在有下级菜单,就有levels[2]['退出应用'],要是继续有下级菜单,就像levels[2]['退出应用']['应用1'],会在下一层及中继续有levels[3]['应用1']。这样一来,就实现了无限级联动菜单,不同的联动菜单只需要修改菜单配置文件就可以了。

但是这么做又有一个遗憾,就是如果level2[2]中的子项有两个名称相同的,都有下级菜单,而且下级菜单内容还不一样,就会有问题,因此在设置的时候,有下级菜单的项要取不同的名称,这里要注意下。就目前这种来说,简单,好理解,也够用了。

代码实现
在代码中也用到了$.extend,用来扩展默认配置。

还有一个点要注意,在联动的时候会将实事的菜单值放入一个属性为hidden的input中,用默认逗号分割每个层级之间的值,可以很轻松的获取到联动菜单所有项的值

if(typeof(AI.opts.saveinput) != "undefined" && (AI.opts.saveinput = AI.opts.saveinput.toString()) != ''){
   $("<input type='hidden' value='' name='"+AI.opts.saveinput+"' id='"+AI.opts.saveinput+"' />").appendTo($('body'));
  }
(function($){
 //配置
 var AI={
  opts:{
   saveinput:"jumpcode", //是否将结果保存至input
   levels:{},
   ulObj:{},//保存生成好的ul列表
   length:0, //层级菜单的层级
   divide:",",//默认各个层级菜单之间的分隔符
  }
 };

 $.fn.casmenu=function(opts){
  AI.opts = $.extend(AI.opts, opts);

  if((AI.opts.length = Object.keys(AI.opts.levels).length) <= 0){
   throw "levels arr must not be empty";
   return;
  }

  var _levels = AI.opts.levels;
  if(_levels[1] == undefined){
   throw "menu level 1 must not be empty";
   return;
  }
  var _levels_1 = _levels[1];

  if(typeof(AI.opts.saveinput) != "undefined" && (AI.opts.saveinput = AI.opts.saveinput.toString()) != ''){
   $("<input type='hidden' value='' name='"+AI.opts.saveinput+"' id='"+AI.opts.saveinput+"' />").appendTo($('body'));
  }

  AI.opts.ulObj['level_1'] = '<select class="casmenu" level="1">';
  AI.opts.ulObj['level_1'] += '<option value="null">请选择</option>';
  $("#"+AI.opts.saveinput).val('null');
  for(var i in _levels_1){
   AI.opts.ulObj['level_1'] += '<option name="'+i+'" value="'+_levels_1[i]+'">'+i+'</option>';
  }
  AI.opts.ulObj['level_1'] += '</select>';

  $(AI.opts.ulObj['level_1']).appendTo(this);

  $("body").on("change", ".casmenu", function(){
   var level = $(this).attr("level");
   if(level > AI.opts.length) return;
   level++;
   //移除当前触发菜单之后的菜单
   for(var num=level;num<=AI.opts.length;num++){
    $(".casmenu[level="+num+"]").remove();
   }

   //设置input的值,级联菜单的值
   var _val = '';
   for(var val=1;val<=AI.opts.length;val++){
    var __val = $("select[level="+val+"]");
    if(__val.length <= 0)
     continue;

    _val += __val.val()+AI.opts.divide;
   }
   $("#"+AI.opts.saveinput).val(_val.substr(0, _val.length-1));

   //levels对象中不存在下一级别目录
   if(typeof(AI.opts.levels[level]) == "undefined") return;

   //获取下一级别目录的键值,值不存在的话返回
   var name = $(this).find("option:selected").attr("name");
   if(typeof(AI.opts.levels[level][name]) == "undefined") return;

   if(typeof(AI.opts.ulObj['level_'+level]) == "undefined" || typeof(AI.opts.ulObj['level_'+level][name]) == "undefined"){
    if(typeof(AI.opts.ulObj['level_'+level]) == "undefined")
     AI.opts.ulObj['level_'+level] = {};

    AI.opts.ulObj['level_'+level][name] = '<select class="casmenu" level="'+level+'">';
    AI.opts.ulObj['level_'+level][name] += '<option value="null">请选择</option>';
    var levelinfo = AI.opts.levels[level][name];
    for(var i in levelinfo){
     AI.opts.ulObj['level_'+level][name] += '<option name="'+i+'" value="'+levelinfo[i]+'" >'+i+'</option>';
    }
    AI.opts.ulObj['level_'+level][name] += '</select>';
   }
   $(AI.opts.ulObj['level_'+level][name]).appendTo($(this).parent());
   var _val = '';
   for(var val=1;val<=AI.opts.length;val++){
    var __val = $("select[level="+val+"]");
    if(__val.length <= 0)
     continue;

    _val += __val.val()+AI.opts.divide;
   }
   $("#"+AI.opts.saveinput).val(_val.substr(0, _val.length-1));
  });
 }
})(jQuery);

运行效果:

jQuery插件实现多级联动菜单效果

jQuery插件实现多级联动菜单效果

以上就是为大家分享的jQuery插件实现多级联动菜单效果,希望对大家的学习有所帮助。

Javascript 相关文章推荐
漂亮的提示信息(带箭头)
Mar 21 Javascript
js操作iframe兼容各种主流浏览器示例代码
Jul 22 Javascript
浅谈Javascript数组的使用
Jul 29 Javascript
JavaScript判断图片是否已经加载完毕的方法汇总
Feb 05 Javascript
Java  Spring 事务回滚详解
Oct 17 Javascript
jQuery弹出div层过2秒自动消失
Nov 29 Javascript
angular使用bootstrap方法手动启动的实例代码
Jul 18 Javascript
layui自己添加图片按钮并点击跳转页面的例子
Sep 14 Javascript
如何基于layui的laytpl实现数据绑定的示例代码
Apr 10 Javascript
原生JS封装拖动验证滑块的实现代码示例
Jun 01 Javascript
bootstrap实现tab选项卡切换
Aug 09 Javascript
JavaScript语法约定和程序调试原理解析
Nov 03 Javascript
基于Jquery实现焦点图淡出淡入效果
Nov 30 #Javascript
轻松学习jQuery插件EasyUI EasyUI创建RSS Feed阅读器
Nov 30 #Javascript
轻松学习jQuery插件EasyUI EasyUI创建树形菜单
Nov 30 #Javascript
轻松学习jQuery插件EasyUI EasyUI实现树形网络基本操作(2)
Nov 30 #Javascript
基于javascript实现浏览器滚动条快到底部时自动加载数据
Nov 30 #Javascript
轻松学习jQuery插件EasyUI EasyUI创建树形网络(1)
Nov 30 #Javascript
轻松学习jQuery插件EasyUI EasyUI创建菜单与按钮
Nov 30 #Javascript
You might like
用PHP来写记数器(详细介绍)
2006/10/09 PHP
php中将网址转换为超链接的函数
2011/09/02 PHP
php smarty截取中文字符乱码问题?gb2312/utf-8
2011/11/07 PHP
PHP spl_autoload_register实现自动加载研究
2011/12/06 PHP
CentOS7系统搭建LAMP及更新PHP版本操作详解
2020/03/26 PHP
jQuery UI 应用不同Theme的办法
2010/09/12 Javascript
当jQuery遭遇CoffeeScript的时候 使用分享
2011/09/17 Javascript
同一页面多个商品倒计时JS 基于面向对象的javascript
2012/02/16 Javascript
阻止子元素继承父元素事件具体思路及实现
2013/05/02 Javascript
jquery ajax jsonp跨域调用实例代码
2013/12/11 Javascript
Js保留小数点的4种效果实现代码分享
2014/04/12 Javascript
IE 下Enter提交表单存在重复提交问题的解决方法
2014/05/04 Javascript
兼容Firefox的Javascript XSLT 处理XML文件
2014/12/31 Javascript
JS判断日期格式是否合法的简单实例
2016/07/11 Javascript
浅谈angularjs module返回对象的坑(推荐)
2016/10/21 Javascript
xcode中获取js文件的路径方法(推荐)
2016/11/05 Javascript
jQuery插件zTree实现删除树节点的方法示例
2017/03/08 Javascript
微信小程序页面传值实例分析
2017/04/19 Javascript
详解Js中的模块化是如何实现的
2017/10/18 Javascript
微信小程序使用modal组件弹出对话框功能示例
2017/11/29 Javascript
vue 巧用过渡效果(小结)
2018/09/22 Javascript
基于Vue-cli快速搭建项目的完整步骤
2018/11/03 Javascript
vue 自定指令生成uuid滚动监听达到tab表格吸顶效果的代码
2020/09/16 Javascript
[45:40]Ti4 冒泡赛第二天NEWBEE vs NaVi 1
2014/07/15 DOTA
Python实现字典按照value进行排序的方法分析
2017/12/23 Python
Python设计模式之观察者模式原理与用法详解
2019/01/16 Python
Python连接mysql数据库及简单增删改查操作示例代码
2020/08/03 Python
CSS3中的弹性布局em运用入门详解 1em等于多少像素
2021/02/08 HTML / CSS
微信浏览器左上角返回按钮拦截功能
2017/11/21 HTML / CSS
C#面试题问题集
2016/04/02 面试题
销售人员获奖感言
2014/02/05 职场文书
教师党员自我评价范文
2015/03/04 职场文书
小学教师教育随笔
2015/08/14 职场文书
2015年新教师个人工作总结
2015/10/14 职场文书
大学生各类奖学金申请书
2019/06/24 职场文书
【海涛dota解说】海涛小满开黑4v5被破两路翻盘潮汐第一视角解说
2022/04/01 DOTA