效果展示
在我们使用某个APP或者网站的时候,需要注册,那么会有地区选择,选择某个省,会自动列出这个省的所有城市,选择城市,会自动列出所有村镇,我们要实现的就是这个效果,在这里村镇就用每个省的学校来替代,完整代码已经上传到github:https://github.com/caohongyu-crypto/Three-level-
,所有的省市信息我放在一个js文件里,省会是一个数组,城市和学校是对象(下面是部分信息截图):
所有不需要向后台请求数据,效果如下:
是不是感觉很简单,没错,就是很简单
HTML部分
html部分代码很简单,是三个select下拉列表,列表的子元素是JS动态生成,所以HTML部分很简洁,一目了然
<ul class="container">
<li class="row">
<p>省 会</p>
<div><select name="" id="province">
</select></div>
</li>
<li class="row">
<p>城 市</p>
<div><select name="" id="city"></select></div>
</li>
<li class="row">
<p>院 校</p>
<div><select name="" id="school"></select></div>
</li>
</ul>
CSS部分代码
CSS的代码就没什么好说的啦~~
*{
padding: 0;
margin: 0;
list-style: none;
}
/* 页面背景颜色 */
body{
background: aliceblue;
}
.container{
width: 300px;
margin: 50px auto;
}
/* 每个li的样式 */
.container li.row{
width: 100%;
height: 42px;
background: white;
border-radius: 15px;
margin-top: 10px;
}
/* 每个li里p元素的样式 */
li.row p{
display: inline-block;
color: #16b7f7;
line-height:42px ;
padding: 0 10px;
}
/* 文字后面的竖线用伪元素表示 */
li.row p::after{
content: '|';
color: #cccccc;
padding: 0 0 0 15px;
}
li.row div{
display: inline-block;
width: 70%;
height: 100%;
}
/* 下拉框的样式 */
li.row div select{
width: 100%;
height: 30px;
border-radius: 5px;
border-color: aliceblue;
}
JS部分
重头戏来啦,这里是实现JS逻辑的部分了,首先应该先分析数据:
1,分析数据 : 通过省会的二维数组中的 城市对应的数字 ----》 城市对象的属性 从而找到 对象城市数组
----》找到city对应的数字 -----》 院校的属性值 从而找到 对应的学院数组
2,实践
省会数组中的每个值与城市对象属性名一一对应,城市对象的值是数组,数组中的代表编号的数字与学生对象的属性名一一对应。所有代码写在一个立即执行函数中,原因是可以防止变量污染,虽然这小demo也没啥可污染的,但是,毕竟编程需要仪式感!请看分析:
省会的获取
首先就是获取省会的数据,这里为什么我要把对省会的获取以及渲染封装在一个函数中呢,因为在后面有可能还要用到同样的代码,这样可以减少冗余。
//获取每个版块的node
var provinceNode = document.getElementById('province');
var cityNode = document.getElementById('city');
var schoolNode = document.getElementById('school');
//省会的获取
/**
*
* @param {*} node 要渲染的父元素
* @param {*} arr 所需信息组成的数组
*/
function render(node, arr){
var provinceStr = '';
for(let i = 0; i < arr.length; i++){
provinceStr += `<option value=${arr[i][0]}>${arr[i][1]}</option>`;
}
node.innerHTML = provinceStr;
}
render(provinceNode, province);
城市的获取
男人的第六感果然是准确的,这里就再次用到了render函数,所以可以一行代码解决的问题,坚决不用多行,自己不想办法偷懒,这怎么能行呢~~
//城市的获取
//根据省会的value值来判断渲染哪一个省的城市
var cityArr = city[provinceNode.value];
render(cityNode, cityArr);
学校的获取
到这里可能又问了,为什么上面已经封装过render函数了,这里怎么又写一遍呢?因为呢,学校的数据和上面省会、城市的有所不同,学校对象每个数组中有三个元素,前两个数字分别对应不同的省或者市,所以第三个值才是学校名称,因此重新封装了一个函数,那么有同学就说了,我就是不想重新封装,我就是要做一个会偷懒的程序猿,这也不是不可以,在render函数里加一个判断就可以了,或者使用三目运算符都可以。
//根据城市的value值判断渲染哪一个城市的学校
var schoolArr = allschool[cityNode.value];
function renderSchool(node, arr){
var schoolStr = '';
for(let i = 0; i <schoolArr.length; i++){
schoolStr += `<option>${schoolArr[i][2]}</option>`
}
schoolNode.innerHTML = schoolStr;
}
renderSchool(schoolNode, schoolArr);
到现在为止,省、市、学校的所有数据都获取到了,也都渲染到了页面上了,下面就是实现改变省、市来动态的变动相应数据了
动态更改数据
当我们重新选择省会的时候,城市的学校都要改变,当我们重新选择城市的时候,学校要改变,省会不变,根据这个原则来实现
//改变下拉框的内容,重新渲染
//省的下拉框改变,重新渲染市和学校
provinceNode.onchange = function(){
let value = this.value;
cityArr = city[value];
render(cityNode, cityArr);
schoolArr = allschool[cityNode.value];
renderSchool(schoolNode, schoolArr);
}
//城市改变,学校重新渲染
cityNode.onchange = function(){
let value = this.value;
schoolArr = allschool[cityNode.value];
renderSchool(schoolNode, schoolArr);
}
每次触发onchange事件的时候都重新获取下拉列表的value值,并重新执行render和renderSchool函数,这样就可以实现啦,整个小demo就全部完成了。希望我的分享对您有些帮助吧!