需求:
- 根据按钮筛选出同一性别的数据。
- 根据输入框输入的名字筛选出具有输入框里字符的数据。
- 根据年龄将数据进行排序。
更新:
- 没有复选效果(点击性别,再输入名字时会重新筛选)
- 增加年龄筛选适应各种情况。
有空再上传
项目样式图
该项目主要练习操作数组的一些方法和不能改变原数据的编程思想。
HTML代码
<div class="wrapper">
<input type="text" >
<button class="active">All</button>
<button>Female</button>
<button>Male</button>
<button>age</button>
<ul>
<!-- <li class="del">
<img src="./1.PNG" alt="">
<p class="name">王某某</p>
<p class="age">18</p>
<p class="say">迎娶白富美,走上人生巅峰</p>
</li>
<li class="del">
<img src="./1.PNG" alt="">
<p class="name">平头哥</p>
<p class="age">18</p>
<p class="say">不服就是干!!</p>
</li> -->
</ul>
</div>
写插入数据的CSS样式时可以自己写一些HTML结构,写完CSS注释掉。后面渲染插入的数据时用JS自动网页面添加HTML。
CSS代码
* {
padding: 0px;
margin: 0px;
list-style: none;
}
.wrapper{
position: absolute;
width: 600px;
border: 1px solid rgb(230, 219, 219);
border-radius: 10px;
left: 50%;
margin-left: -250px;
padding: 10px;
}
.wrapper input{
position: relative;
height: 25px;
width: 280px;
padding-left: 10px;
border: 1px solid blue;
border-radius: 5px;
outline: none;
}
.wrapper button{
float: right;
height: 25px;
width: 60px;
border-radius: 10px;
background-color: #ffff;
outline: none;
border: none;
margin-left: 15px;
font-size: 17px;
font-weight: 600;
line-height: 25px;
text-align: center;
color: blue;
}
.wrapper button.active{
color: #fff;
background-color: blue;
}
.wrapper ul li{
position: relative;
height: 70px;
width: 600px;
margin-top: 5px;
border: 1px solid #fff;
border-bottom: 2px solid rgb(239, 228, 228);
}
.wrapper ul li img{
display: block;
height: 40px;
width: 40px;
margin-top: 10px;
/*margin-left: 5px;*/
}
.wrapper ul li .name{
position: absolute;
height: 20px;
line-height: 20px;
padding: 5px;
font-size: 20px;
font-weight: 800;
left: 45px;
top: 5px;
}
.wrapper ul li .age{
position: absolute;
left: 140px;
top: 15px;
font-size: 15px;
font-weight: 500;
}
.wrapper ul li .say{
position: absolute;
bottom: 10px;
left: 45px;
font-size: 14px;
color: rgb(97, 86, 86);
}
注意不要让Female的字体露出盒子。
JS代码
// 从后端请求来的数据
var personArr = [
{name: '李白', age: 21, sex: 'male', email: '111@163.com'},
{name: '韩信', age: 23, sex: 'male',email: '222@163.com'},
{name: '嬴政', age: 25, sex: 'male', email: '777@163.com'},
{name: '元歌', age: 27, sex: 'male',email: '333@163.com'},
{name: '王朝君', age: 20, sex: 'female', email: '222@163.com'},
{name: '露娜', age: 22, sex: 'female', email: '666@163.com'},
{name: '李元芳', age: 23, sex: 'male',email: '333@163.com'},
{name: '伽罗', age: 21, sex: 'female', email: '222@163.com'},
{name: '花木兰', age: 25, sex: 'female', email: '666@163.com'}
];
// initial variable
var oUl = document.getElementsByTagName("ul")[0];
var oInput = document.getElementsByTagName("input")[0];
// 数据渲染到页面
function randerPage (data) {
// 遍历数据,并把数据填入页面之中
var htmlStr = "";
// 防止请求数据不成功导致出BUG
oUl.innerHTML = "";
data.forEach(function (ele, index, self) {
// 字符串拼接方法
htmlStr += "<li><img src='./1.png'><p class='name'>" + ele.name + "</p><p class='age'>" + ele.age + "</p><p class='say'>" + ele.email + "</p>";
});
// 将拼接好的字符串插入到页面中
oUl.innerHTML = htmlStr;
}
// 首次渲染得到初始页面
randerPage(personArr);
// 添加行为
// 输入框行为
oInput.oninput = function () {
// 把根据文本筛选出的数据传入渲染函数中进行渲染
randerPage(filterArrByText(personArr, this.value));
}
// 根据文本来进行筛选函数(纯函数)
function filterArrByText (data, text) {
if (!text) {
return data;
}else{
// 返回筛选出的数据
return data.filter(function (ele, index) {
// 返回符合文本条件的数据
return ele.name.indexOf(text) != -1;
});
}
}
// btn varible
// 原生方法获取到一堆的DOM元素时,得到的是个类数组
var oBtnArr = [].slice.call(document.getElementsByTagName("button"), 0);
//获取上一次具有被点击样式的元素
var lastActiveBtn = document.getElementsByClassName("active")[0];
// btn 点击样式行为
// 注册事件
oBtnArr.forEach(function(ele, index, self) {
ele.onclick = function () {
// 当一点击性别,css样式就发生改变
changeStyle(this);
if (ele.innerText != "age") {
// 按点击到的性别重新渲染一遍页面
randerPage(filterArrBySex(personArr, ele.innerText));
}else{
// 按点击到的年龄重新渲染一遍页面,因为数组方法sort会改变原数组,所以用克隆的数据进行sort操作
var arr = [];
randerPage(sortByAge(clone(arr, personArr)));
}
}
})
// 点击按钮时css样式改变函数
function changeStyle (currActiveBtn) {
// 当前被点击的元素具有active样式
currActiveBtn.className = "active";
// 把上次被点击的元素的样式清除
lastActiveBtn.className = "";
// 更新上次被点击的元素,以便后续点击操作
lastActiveBtn = currActiveBtn;
}
// 根据性别来筛选数据函数
function filterArrBySex (data, sex) {
// 默认和用户点击All按钮
if (sex == "All") {
// 不进行操作,返回原数组
return data;
}else {
// 返回根据性别筛选出来的数据
return data.filter(function (ele, index) {
// 因为请求来的数据的性别首字母是小写,而行间里的是大写,所以用正则将点击到的行间里的性别替换成小写
var reg = /^\w/g;
// 返回数据中具有相同的性别的一些数据,因为别正则不改变原字符串,所以不需要克隆点击到的字符,
return ele.sex == sex.replace(reg, function ($) {
return $.toLowerCase();
});
});
}
}
// 根据年龄对数据进行排序
function sortByAge (data) {
data.sort(function (a, b) {
// 从小到大排
return a.age - b.age
});
// 排序结果为一个类数组,所以调用数组方法空截,得到数组,(否则后续将排序的数据渲染到页面时调用不了forEach方法)
return [].slice.call(data, 0)
}
// 深度克隆
function clone (target, orange) {
// 兼容用户不传接收克隆好的数据的数组或对象
var target = target || {};
// 判断要克隆的是数组还是对象的方法
var toStr = Object.prototype.toString;
// 将判断要克隆的是数组的条件存一下
var str = "[object Array]"
// 遍历要克隆的数据
for (var prop in orange) {
// 剔除原型上的属性
if (orange.hasOwnProperty(prop)) {
// 剔除除null外的原始值
if (orange !== null && typeof(orange[prop]) == "object") {
// 用储存的方法和条件值判断要克隆的是数组还是对象
target[prop] = toStr.call(orange[prop]) == str ? [] : {};
// 递归克隆对象里还有对象的情况
clone(target[prop], orange[prop])
}else {
// 原始值直接克隆
target[prop] = orange[prop];
}
}
}
// 最后返回克隆好的数据
return target;
}