项目中的表单经常涉及下拉选择,有些需要层级关联,比如选择省市区,有些则不需要,只有一级。现自己封装了一个符合项目ui设计的下拉框。
要求:符合AMD规范;依赖jq;兼容ie8;
组件代码如下:
define('vDrop', [
'jquery'
], function ($) {
'use strict';
/**
* 组件名:v-drop,一个下拉框组件
*
* @exports vDrop
* @author Viocexx
* @version 1.0
* @class
*/
var vDropCreate = function (params) {
/**
* @description 初始化下拉框组件
* @param {id} id 下拉框生成的父级id
* @param {tabs} 示例:["省","市","区","街道"],确定下拉框是几级的,与datajson里的数据层级要对应上,只有一级时不传这个参数。
* @param {datajson} datajson 下拉框显示数据
* @param {callback} 选择后的回调函数
*/
this.id = params.id;
this.tabs = params.tabs;
this.datajson = params.datajson;
this._call = params.callback;
var _this = this;
// 初始化函数 生成最外层div 选择结果显示框 和 下拉选择框
this.init = function () {
var dropHTML = '<div style="position:relative" class="js-dropbox"></div>';
$("#" + _this.id).html(dropHTML);
var ls = _this.tabs;
var dropHtml = ''
if (ls == undefined) {
dropHtml = '<div class="dropInput js-area"><span>点击下拉选择</span></div>'
+ '<div class="dropDownBox js-area-box"></div>';
} else {
var le = ls.length;
dropHtml = '<div class="dropInput js-area">'
for (var i = 0; i < le; i++) {
dropHtml += i < le - 1 ?
'<span>--</span>/' :
'<span>--</span>'
}
dropHtml += '</div>'
+ '<div class="dropDownBox js-area-box"></div>'
}
$("#" + _this.id).find(".js-dropbox").html(dropHtml);
_this.downBox()
}
// 生成下拉选项里的内容 分区域的时候有tab 不分区域的时候没有tab
this.downBox = function () {
var ls = _this.tabs;
var downHtml = ''
if (ls == undefined) {
downHtml = '<div class="js-areaBox"></div>';
}
else {
var le = ls.length;
downHtml = '<div class="clearfix vregionBox js-region">';
for (var i = 0; i < ls.length; i++) {
var ac = i == 0 ? 'vchi' : '';
downHtml += '<div class="fl ' + ac + '" style="width:' + 100 / le + '%">' + ls[i] + '</div>'
}
downHtml += '</div><div class="js-areaBox"></div>';
}
$("#" + _this.id).find(".js-area-box").html(downHtml);
_this.areaBox();
};
// 区域盒子里的数据渲染
this.areaBox = function () {
var data = _this.datajson;
var ls = _this.tabs;
var areHtml = '<ul class="js-address-ul dropShow">';
if (ls != undefined) {
for (var i = 0; i < data.length; i++) {
if (data[i].parent == "CN") {
areHtml += '<li data-id="' + data[i].id + '"><p>' + data[i].name + '</p></li>'
}
}
areHtml += '</ul>';
for (var i = 0; i < ls.length - 1; i++) {
areHtml += '<ul class="js-address-ul">请先选择上一级</ul>'
}
} else if (ls == undefined) {
for (var i = 0; i < data.length; i++) {
areHtml += '<li data-id="' + data[i].id + '"><p>' + data[i].name + '</p></li>'
}
areHtml += '</ul>';
}
$("#" + _this.id).find(".js-areaBox").append(areHtml);
_this.domFunc();
}
// 渲染下一级数据
this.createNext = function (id) {
var data = _this.datajson;
var areHtml = '';
for (var i = 0; i < data.length; i++) {
if (data[i].parent == id) {
areHtml += '<li data-id="' + data[i].id + '"><p>' + data[i].name + '</p></li>'
}
}
return areHtml
}
// 下拉框里的dom 操作函数
this.domFunc = function () {
var regionIndex = "";
var myindex = "";
var liIdLs = [];
$('#' + _this.id).on("click", ".js-area", function (e) {
var e = e || window.e;
stopFunc(e);
var width = $(this).width();
$(this).siblings(".js-area-box").width(width).addClass("dropShow");
regionIndex = $(this).siblings(".js-area-box").find(".js-areaBox").children(".js-address-ul").length;
}).on("click", ".js-region div", function (e) {
var e = e || window.e;
stopFunc(e);
var index = $(this).index();
$(this).addClass("vchi").siblings().removeClass("vchi");
$(this).parent().siblings(".js-areaBox").find(".js-address-ul").eq(index).addClass("dropShow").siblings().removeClass("dropShow");
}).on("click", ".js-address-ul li", function (e) {
var e = e || window.e;
stopFunc(e);
var dataId = $(this).attr("data-id");
var nextContent = _this.createNext(dataId);
myindex = $(this).parent().index() + 1;
console.log(_this)
liIdLs[myindex - 1] = dataId;
var tresult = $(this).children("p").text();
$(this).parent().parent().parent().siblings(".js-area").find("span").eq(myindex - 1).html(tresult).attr("title", tresult).attr("data-id", dataId).nextAll("span").html("--").attr("title", "");
if (myindex == regionIndex) {
$(this).parent().parent().parent().removeClass("dropShow");
$("#" + _this.id).attr("data-id", liIdLs);
if (_this._call != undefined) {
_this._call(liIdLs);
}
} else {
$(this).parent().removeClass("dropShow").eq(myindex).addClass("dropShow");
$(this).parent().parent().find(".js-address-ul").eq(myindex).addClass("dropShow").html(nextContent);
$(this).parent().parent().siblings(".js-region").find("div").eq(myindex).addClass("vchi").siblings().removeClass("vchi");
}
}).on("click", ".js-area-box", function (e) {
var e = e || window.e;
stopFunc(e);
})
$("body").on("click", function (e) {
var e = e || window.e;
stopFunc(e);
$(".js-area-box").removeClass("dropShow")
})
// 阻止事件冒泡
function stopFunc(e) {
/*标准浏览器有效 IE不行 e.stopPropagation();*/
/*没有兼容性问题阻止事件冒泡e.cancelBubble = true;*/
e.stopPropagation ? e.stopPropagation() : e.cancelBubble = true;
}
}
}
var vDrop = {};
vDrop.init = function (params) {
var newT = new vDropCreate(params);
newT.init();
}
return vDrop;
})
遇到的问题:
最开始的时候没有关注this指向问题,当页面有两个地方需要使用下拉框组件的时候,先加载的组件数据会被后加载的数据覆盖。于是做了修改,封装为了对象,使用时new。
require.config:
//模块的加载
//在主模块里面,对模块的加载行为进行自定义 require.config(参数),此参数就是一个对象
require.config({
baseURL: '/VDrop/js',
paths: {
jquery: "/VDrop/js/jquery-1.11.3.min",
vDrop: "/VDrop/v-drop/VDrop"
},
});
使用实例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>drop</title>
<link rel="stylesheet" href="../v-drop/v-drop.css">
<style>
body {
font-size: 14px;
padding: 100px;
}
#div1 {
width: 500px;
margin-top: 50px;
}
#div2 {
width: 500px;
margin-top: 50px;
}
</style>
</head>
<body>
<div id="div1"></div>
<div id="div2"></div>
</body>
<script src="../js/require.js"></script>
<script src="../js/require-conf.js"></script>
<script>
require(['jquery', 'vDrop'], function ($, t) {
var tablist = ["省", "市", "区"];
var listArea = [
{
id: "100",
name: "安徽省",
parent: "CN"
},
{
id: "101",
name: "河南省",
parent: "CN"
},
{
id: "1001",
name: "合肥市",
parent: "100"
}, {
id: "1002",
name: "芜湖市",
parent: "100"
},
{
id: "10011",
name: "蜀山区",
parent: "1001"
}, {
id: "10021",
name: "镜湖区",
parent: "1002"
},
{
id: "1011",
name: "郑州市",
parent: "101"
},
{
id: "10111",
name: "某某区",
parent: "1011"
},
]
var list2 = [
{
id: "100",
name: "01"
},
{
id: "101",
name: "02"
}
];
function _cll(val) {
console.log(val, 'ids')
}
$(function () {
t.init({ id: "div1", datajson: listArea, tabs: tablist });
t.init({ id: "div2", datajson: list2, callback: _cll });
})
})
</script>
</html>