【前端】使用jQuery封装一套UI组件 - 级联选择器组件

简介: 本篇文章来讲解下级联选择器组件级联选择器,在实际项目中也是比较常用的组件,比如:省市区三级关联,上下级联动等最后面会附上全部代码
作者:小5聊基础
简介:一只喜欢全栈方向的程序员,欢迎咨询,尽绵薄之力答疑解惑
编程原则:Write Less Do More

GI2F.gif

【级联选择器特点】

1)级联选择器,可以多层展开

2)当没有子集时,则不显示展开下级箭头

3)当有子集时,则有显示展开下级的向右箭头

4)没有限制的情况下,可以无限展开

5)json格式可以定义为

{
    text:'一级文本',
    value:'值,也可以是ID唯一值',
    children:[
        {
            text:'二级文本',
            value:'ID值',
            children:[]
        }
    ]
}

【级联选择器布局设计】

1)先设置一个父级div,宽度设定为200px,高度和行高为35px,同时设定文本超过宽度隐藏,并设置决定定位,占一个空间位置,同时也是为了给子元素一个相对定位参考

2)再设置一个箭头向下的默认图标,这里通过css样式的方式设置一个箭头图标,有个小技巧,就是设置一个div高宽度为0,但是边框有值得情况,只显示其中一个方向得边框就可以出现箭头,其他三个边框设定为透明即可,如下

image.png

<div style="margin-left:100px;display:inline-block;width:0;height:0;border-top: 30px solid #aaa;border-right: 30px solid #ccc;border-bottom: 30px solid #999;border-left: 30px solid #555;">

</div>

<div style="margin-left:100px;display:inline-block;width:0;height:0;border-top: 30px solid #aaa;border-right: 30px solid transparent;border-bottom: 30px solid transparent;border-left: 30px solid transparent;">

</div>

3)接着设置一个关键弹窗div,宽度设定为200px,最小高度为150px,最大高度为300px

4)然后就是选项div,设置内边距以及选项hover样式,同时在左右边设置一个小箭头

image.png

.ci-arrow {
    position: absolute;
    top: 10px;
    right: 10px;
    border: 2px solid #999;
    width: 8px;
    height: 8px;
    border-left: none;
    border-bottom: none;
    transform: rotate( 45deg);
}

5)同时在弹出div外再嵌套一个父级div设置阴影,大概原型就出来了

image.png

6)滚动条样式设置

image.png

/* 设置滚动条的样式 */
::-webkit-scrollbar {
    width: 6px;
}
/* 滚动竖线 */
::-webkit-scrollbar-track {
    border-radius: 6px;
}
/* 滚动条滑块 */
::-webkit-scrollbar-thumb {
    border-radius: 6px;
    background: rgba(0,0,0,0.1);
}
    ::-webkit-scrollbar-thumb:window-inactive {
        background: rgba(255,0,0,0.4);
    }

【级联选择器交互】

1)定义一个json数组值,用于遍历动态生成下拉选项值

2)先绑定文本框得点击事件,点击后先动态生成一级选项,并弹出显示,同时箭头也变为向上。切换可以用一个flag来做判断,隐藏和显示

3)循环添加选项逻辑<br/>
如果有子集,那么选项添加一个向右的箭头<br/>
完成选项循环后,给选型绑定一个点击事件<br/>
如果选项有子集,那么就再次调用循环选项方法,动态生成,以此类推<br/>
特别是多层嵌套,必须给每个选项添加一个index下标,格式:index|index|...

image.png

【全局代码】

<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <title>cascader级联选择器组件</title>
    <style>
        body, html {
            margin: 0;
            padding: 0;
            font-size: 100%;
        }
    </style>
</head>
<body>

    <style type="text/css">
        .cascader-box {
            position: relative;
            font-size: 15px;
            color: #555;
        }

        .cascader-text-div {
            width: 178px;
            height: 35px;
            line-height: 35px;
            border: 1px solid #c0c4cc;
            padding: 0 10px;
            cursor: pointer;
        }

        .cascader-arrow-down {
            width: 0;
            height: 0;
            border-top: 8px solid #aaa;
            border-left: 8px solid transparent;
            border-right: 8px solid transparent;
            float: right;
            margin-top: 15px;
        }

        .cascader-arrow-up {
            width: 0;
            height: 0;
            border-bottom: 8px solid #aaa;
            border-left: 8px solid transparent;
            border-right: 8px solid transparent;
            float: right;
            margin-top: 15px;
        }

        .cascader-area {
            width: 200px;
            height: 172px;
            box-shadow: 0 0 13px #ccc;
            position: absolute;
            left: 0px;
            top: 40px;
        }

        .cascader-div {
            position: absolute;
            top: 0px;
            left: 0px;
            width: 198px;
            border: 1px solid #c0c4cc;
            background: #fff;
            min-height: 150px;
            z-index: 10;
            height: 100%;
            overflow: auto;
        }

        .cascader-item {
            padding: 0 10px;
            height: 35px;
            line-height: 35px;
            cursor: pointer;
            position: relative;
        }

            .cascader-item:hover {
                background: #e3e3e3;
            }

        .cascader-item-action {
            background: #e3e3e3 !important;
        }

        .ci-arrow {
            position: absolute;
            top: 10px;
            right: 10px;
            border: 2px solid #999;
            width: 8px;
            height: 8px;
            border-left: none;
            border-bottom: none;
            transform: rotate( 45deg);
        }

        .cascader-scrollbar {
            scrollbar-face-color: #fcfcfc;
            scrollbar-highlight-color: #6c6c90;
            scrollbar-shadow-color: #fcfcfc;
            scrollbar-3dlight-color: #fcfcfc;
            scrollbar-arrow-color: #240024;
            scrollbar-track-color: #fcfcfc;
            scrollbar-darkshadow-color: #48486c;
            scrollbar-base-color: #fcfcfc
        }

        /* 设置滚动条的样式 */
        ::-webkit-scrollbar {
            width: 6px;
        }
        /* 滚动竖线 */
        ::-webkit-scrollbar-track {
            border-radius: 6px;
        }
        /* 滚动条滑块 */
        ::-webkit-scrollbar-thumb {
            border-radius: 6px;
            background: rgba(0,0,0,0.1);
        }
            ::-webkit-scrollbar-thumb:window-inactive {
                background: rgba(255,0,0,0.4);
            }
    </style>
    <div style="width:600px;height:500px;background:#fff;padding:10px;margin:0 auto;margin-top:30px;border-radius:10px;box-shadow:0 0 13px #ccc;">
        
        <div class="cascader-box" style="margin-top:200px;">
            <div id="cascader2" class="cascader-text-div">
                <span>请选择所属值</span>
                <div class="cascader-arrow-down"></div>
            </div>

            <div class="cascader-area" style="display:none;"></div>
        </div>
    </div>



</body>
</html>

<!--交互js-->
<script src="https://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script type="text/javascript">
    $(function () {

        var jsonArr = [
            {
                text: '一级文本',
                value: '1',
                children: [
                    {
                        text: '二级文本1',
                        value: '1',
                        children: []
                    },
                    {
                        text: '二级文本2',
                        value: '2',
                        children: [
                            {
                                text: '三级文本1',
                                value: '1',
                                children: []
                            },
                            {
                                text: '三级文本2',
                                value: '2',
                                children: []
                            },
                        ]
                    },
                    {
                        text: '二级文本3',
                        value: '3',
                        children: []
                    }
                ]
            },
            {
                text: '一级文本2',
                value: '2',
                children: []
            },
            {
                text: '一级文本3',
                value: '3',
                children: [
                    {
                        text: '二级文本1',
                        value: '1',
                        children: []
                    },
                    {
                        text: '二级文本2',
                        value: '2',
                        children: []
                    }
                ]
            },
            {
                text: '一级文本4',
                value: '4',
                children: []
            },
            {
                text: '一级文本5',
                value: '5',
                children: []
            },
            {
                text: '一级文本6',
                value: '6',
                children: []
            },
            {
                text: '一级文本7',
                value: '7',
                children: []
            }
        ];

        function loadData(level, index) {

            var dom = $('<div></div>');
            dom.addClass("cascader-div cascader-scrollbar");

            if (level == 2) {
                dom.css({ "left": (200 - 1), "zIndex": 10 - level });
            }
            else if (level == 3) {
                dom.css({ "left": (400 - level - 1), "zIndex": 10 - level });
            }

            var json = jsonArr;
            if (level == 2 && index != undefined) {
                json = jsonArr[index].children;
            }
            else if (level == 3 && index != undefined) {
                var ids = index.split('|');
                json = jsonArr[ids[0]].children[ids[1]].children;
            }

            for (var i = 0; i < json.length; i++) {
                var data = json[i];
                var option = $('<div><span></span></div>');
                option.addClass("cascader-item");
                option.attr('data-value', data.value);
                option.attr('data-level', level);
                if (level == 1) {
                    option.attr('data-index', i);
                }
                else {
                    option.attr('data-index', index + "|" + i);
                }
                option.attr('data-length', data.children.length);

                $("span", option).eq(0).html(data.text);

                if (data.children.length > 0) {
                    option.append('<span class="ci-arrow"></span>');
                }

                dom.append(option);
            }

            $(".cascader-area").append(dom);
        }

        $("#cascader2").click(function () {

            var flag = $(this).attr('data-flag');
            if (flag == undefined || flag == "close") {
                flag = "open";
                $(".cascader-area").show();
                $(".cascader-arrow-down").removeClass("cascader-arrow-down").addClass("cascader-arrow-up");
            }
            else {
                flag = "close";
                $(".cascader-area").hide();
                $(".cascader-arrow-up").removeClass("cascader-arrow-up").addClass("cascader-arrow-down");
            }
            $(this).attr('data-flag', flag);

            loadData(1);
        });

        function itemEvent() {
            $(document).on("click", ".cascader-item", function () {
                var level = parseInt($(this).attr('data-level'));
                var index = $(this).attr('data-index');
                var length = parseInt($(this).attr('data-length'));

                var parent = $(this).parent();
                $(".cascader-item", parent).removeClass('cascader-item-action');
                $(this).addClass('cascader-item-action');

                $(".cascader-div").eq(level).remove();
                if (parseInt(length) > 0) {
                    var next_level = level + 1;
                    loadData(next_level, index);

                    $(".cascader-area").css({ "width": next_level * 200 - next_level });
                }
                else {

                    $(".cascader-area").css({ "width": level * 200 - level });
                }
            });
        }
        itemEvent();

    })
</script>
相关文章
|
1月前
|
前端开发
前端通过input标签封装Upload组件实现文件上传
前端通过input标签封装Upload组件实现文件上传
51 0
|
2月前
|
前端开发 数据可视化 JavaScript
前端图形学实战: 从零开发一款轻量级滑动验证码组件(vue3 + vite版)
前端图形学实战: 从零开发一款轻量级滑动验证码组件(vue3 + vite版)
66 0
element-ui中Select 选择器异步加载下一页
element-ui中Select 选择器异步加载下一页
|
4月前
|
前端开发 JavaScript 程序员
[前端学习]文件组件专题
[前端学习]文件组件专题
32 1
|
3月前
|
前端开发
element-ui组件DatePicker日期选择器移动端兼容
element-ui组件DatePicker日期选择器移动端兼容
element-ui组件DatePicker日期选择器移动端兼容
|
3月前
|
前端开发
elementui-upload组件自定义样式上传(upload中常用的属性,但是网络上却找不到教程)(解决bug删除之后再次上传会上传删除的图片)专注后端工程师的前端速成
elementui-upload组件自定义样式上传(upload中常用的属性,但是网络上却找不到教程)(解决bug删除之后再次上传会上传删除的图片)专注后端工程师的前端速成
61 0
|
3月前
|
前端开发 JavaScript 测试技术
掌握函数式组件:迈向现代化前端开发的关键步骤(下)
掌握函数式组件:迈向现代化前端开发的关键步骤(下)
掌握函数式组件:迈向现代化前端开发的关键步骤(下)
|
3月前
|
缓存 前端开发 JavaScript
掌握函数式组件:迈向现代化前端开发的关键步骤(上)
掌握函数式组件:迈向现代化前端开发的关键步骤(上)
掌握函数式组件:迈向现代化前端开发的关键步骤(上)
|
3月前
|
负载均衡 前端开发 Java
字节后端面试题(前端发送请求到后端的过程(MVC),网关gateway作用,怎么解决跨域,各微服务组件作用)
字节后端面试题(前端发送请求到后端的过程(MVC),网关gateway作用,怎么解决跨域,各微服务组件作用)
118 0
|
3月前
|
前端开发
前端改原生组件遇到的一个神奇的现象
前端改原生组件遇到的一个神奇的现象

热门文章

最新文章