0%

JS实现商城排序

实现效果

  • 根据上架时间/热度/价格进行升序/降序排序
  • 上箭头亮代表升序,下箭头亮代表降序

商城排序

渲染 li 标签

  • 获取 ul 以便让每一个 li 渲染到页面
1
2
var lists = document.querySelector(".lists");
var lis = null;
  • 把每一个 li 渲染到页面上

    这里为了操作方便,给每一个 li 绑定自定义属性,之后根据属性值获取其中内容 li.getAttribute(...) 即可

    如果不这样做,则需要通过 li.querySelector(...).innerText 获取

    注意:querySelectorAll 获取到的是类数组,因为需要进行排序,使用数组的 sort() 方法,所以需要用 [].slice.call()Array.from 转换成数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function Init(data) {
let str = "";
for (let i = 0; i < data.length; i++) {
const el = data[i];
str += `<li time="${el.time}" hot="${el.hot}" price="${el.price}">
<img src="${el.img}" alt="">
<p class="title">${el.title}</p>
<p class="time">${el.time}</p>
<p class="info">
<span class="price">${el.price}</span>
<span class="hot">${el.hot}</span>
</p>
</li>`;
}
lists.innerHTML = str;
lis = [].slice.call(lists.querySelectorAll("li"));
}

点击 a 标签进行排序

  • 获取 a 标签
1
var links = document.querySelectorAll(".top a");
  • 给 a 标签添加鼠标点击事件

    为实现每次排序都是上一次的倒序,需要给每一个 a 标签添加一个自定义属性作为标志 links[i].flag = -1 ,flag 值为1代表升序,每次点击事件只需 flag 取反即可 this.flag *= -1

    注意: sort() 方法中回调函数 this 指向 window,所以需要用一个变量存储 this let that = this;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
for (let i = 0; i < links.length; i++) {
links[i].flag = -1;
links[i].onclick = function () {
this.flag *= -1;
let that = this;
let sortFlag = this.getAttribute("sortFlag");
if (sortFlag == "time") {
lis.sort(function (a, b) {
return (a.getAttribute(sortFlag).replace(/-/g, "") - b.getAttribute(sortFlag).replace(/-/g, "")) * that.flag;
});
} else {
lis.sort(function (a, b) {
return (a.getAttribute(sortFlag) - b.getAttribute(sortFlag)) * that.flag;
});
}
for (let i = 0; i < lis.length; i++) {
lists.appendChild(lis[i])
}
};
}

点击 a 标签点亮排序箭头

  • 升/降序高亮对应箭头字体图标
1
2
3
4
5
6
7
8
9
10
let arrows = this.querySelectorAll("b");
let arrCur = document.querySelectorAll(".top b.current");
for (let i = 0; i < arrCur.length; i++) {
arrCur[i].classList.remove("current");
}
if (this.flag == 1) {
arrows[0].classList.add("current");
} else {
arrows[1].classList.add("current");
}

优化

  • for 每进行一次循环都会引起浏览器的回流,非常耗性能
1
2
3
for (let i = 0; i < lis.length; i++) {
lists.appendChild(lis[i]);
}
  • 可以使用 DocumentFragment 来创建一个新的空白的文档片段,把元素附加到这个文档片段中,之后通过这个文档片段附加到 DOM 树

    因为文档片段存在内存中,并不在 DOM 树中,所以将子元素插入到文档片段时不会引起页面回流。因此,使用文档片段会带来更好的性能

1
2
3
4
5
let frg = document.createDocumentFragment();
for (let i = 0; i < lis.length; i++) {
frg.appendChild(lis[i]);
}
lists.appendChild(frg)
  • 如果希望点击完当前a标签,再点击其他a标签时都是升序排列的话,需要每次都将其他标签的flag设置为 -1
1
2
3
4
5
for (let i = 0; i < links.length; i++) {
if (links[i] != this) {
links[i].flag = -1;
}
}

完整代码

index.html(html+css)

  • 创建 index.html 文件,粘贴如下代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
<!DOCTYPE html>

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>商城排序</title>
<style>
* {
margin: 0;
padding: 0;
}
ul {
list-style: none;
}
a {
text-decoration: none;
}
body, html {
background: lavender;
}
.main {
width: 1185px;
margin: 0 auto;
}
.main .topBar {
height: 50px;
background: #fff;
display: flex;
align-items: center;
padding-left: 20px;
box-sizing: border-box;
}
.main .shortBtn {
display: flex;
align-items: center;
margin: 0 10px;
color: blue;
}
.main .shortBtn .arrows {
color: #333;
display: flex;
flex-direction: column;
margin-left: 10px;
}
.main .shortBtn .iconfont {
font-size: 14px;
}
.shortBtn:hover>span {
color: red;
}
.lists {
display: flex;
flex-wrap: wrap;
}
.lists li {
margin-top: 20px;
width: 225px;
background: #fff;
padding: 20px;
box-sizing: border-box;
font-size: 14px;
margin-right: 15px;
line-height: 30px;
}
.lists li:nth-child(5n){
margin-right: 0;
}
.lists li img {
width: 140px;
display: block;
margin: 0 auto;
}
.lists li .numInfo {
display: flex;
justify-content: space-between;
}
.arrowUp {
border: 5px solid #333;
margin-bottom: 10px;
border-color: transparent transparent #333 transparent;
}
.arrowUp.current {
border-color: transparent transparent red transparent;
}
.arrowDown {
border: 5px solid #333;
border-color: #333 transparent transparent transparent;
}
.arrowDown.current {
border-color: red transparent transparent transparent;
}
</style>
</head>

<body>
<div class="main">
<div class="topBar">
<span>排序</span>
<a href="javascript:;" class="shortBtn" sortFlag="time">
<span>上架时间</span>
<div class="arrows">
<b class="arrowUp"></b>
<b class="arrowDown"></b>
</div>
</a>
<a href="javascript:;" class="shortBtn" sortFlag="hot">
<span>热度</span>
<div class="arrows">
<b class="arrowUp"></b>
<b class="arrowDown"></b>
</div>
</a>
<a href="javascript:;" class="shortBtn" sortFlag="price">
<span>价格</span>
<div class="arrows">
<b class="arrowUp"></b>
<b class="arrowDown"></b>
</div>
</a>
</div>
<!-- 图片列表 -->
<ul class="lists"></ul>
</div>
</body>

</html>
<script src="index.js"></script>

data.json

  • 这里需要用 Ajax 请求一下如下 json 数据
  • 创建 data.json ,粘贴如下数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
[
{
"id": 1,
"title": "HUAWEI全网通版(亮黑色)",
"price": 499,
"time": "2017-03-15",
"hot": 198,
"img": "img/1.jpg"
},
{
"id": 2,
"title": "HUAWEI(曜石黑)",
"price": 129,
"time": "2017-02-08",
"hot": 25,
"img": "img/2.jpg"
},
{
"id": 3,
"title": "华为畅享7(香槟金)",
"price": 895,
"time": "2017-01-25",
"hot": 568,
"img": "img/3.jpg"
},
{
"id": 4,
"title": "HUAWEI全网通版(曜石黑)",
"price": 1895,
"time": "2016-12-30",
"hot": 20000,
"img": "img/4.jpg"
},
{
"id": 5,
"title": "HUAWEI全网通版(玫瑰金)",
"price": 3587,
"time": "2016-01-30",
"hot": 1032654,
"img": "img/5.jpg"
},
{
"id": 6,
"title": "华为畅享7(香槟金)",
"price": 992,
"time": "2018-01-01",
"hot": 1,
"img": "img/6.jpg"
},
{
"id": 7,
"title": "HUAWEI全网通版(樱语粉)",
"price": 564,
"time": "2017-02-19",
"hot": 400,
"img": "img/7.jpg"
},
{
"id": 8,
"title": "HUAWEI全网通版(曜石黑)",
"price": 420,
"time": "2017-01-25",
"hot": 240,
"img": "img/8.jpg"
},
{
"id": 9,
"title": "HUAWEI P10(钻雕金)",
"price": 12,
"time": "2014-01-01",
"hot": 12345678,
"img": "img/9.jpg"
},
{
"id": 10,
"title": "HUAWEI全网通版(曜石黑)",
"price": 420,
"time": "2017-01-25",
"hot": 240,
"img": "img/8.jpg"
}
]

index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// 获取页面元素
let lists = document.querySelector(".lists");
let links = document.querySelectorAll(".topBar a");
let lis = lists.getElementsByTagName("li");
// Ajax 请求数据
let data = null;

// 1.数据请求 Ajax四部曲
function getData(url) {
let xhr = new XMLHttpRequest();
xhr.open("get", url);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
data = JSON.parse(xhr.responseText);
BindHtml(data);
}
};
xhr.send();
}
getData("data/data.json");

// 2.渲染li
function BindHtml(data) {
var str = "";
for (let i = 0; i < data.length; i++) {
const el = data[i];
str += `<li time="${el.time}" price="${el.price}" hot="${el.hot}">
<img src="${el.img}" alt="">
<p class="title">${el.title}</p>
<p class="time">${el.time}</p>
<p class="numInfo">
<span class="price">${el.price}</span>
<span class="hot">${el.hot}</span>
</p>
</li>`;
}
lists.innerHTML = str;
lis = [].slice.call(lis);
}
// 3.给link绑定事件
for (let i = 0; i < links.length; i++) {
links[i].flag = -1;
links[i].onclick = function () {
let that = this;
for (let i = 0; i < links.length; i++) {
if (links[i] != this) {
links[i].flag = -1;
}
}
this.flag *= -1;
let sortFlag = this.getAttribute("sortFlag");
let arrows = this.querySelectorAll("b");
let arrCur = document.querySelectorAll("b.current");
for (let i = 0; i < arrCur.length; i++) {
arrCur[i].classList.remove("current");
}
if (this.flag == 1) {
arrows[0].classList.add("current");
} else {
arrows[1].classList.add("current");
}
let frg = document.createDocumentFragment();
if (sortFlag == "time") {
lis.sort(function (a, b) {
return (a.getAttribute(sortFlag).replace(/-/g, "") - b.getAttribute(sortFlag).replace(/-/g, "")) * that.flag;
});
} else {
lis.sort(function (a, b) {
return (a.getAttribute(sortFlag) - b.getAttribute(sortFlag)) * that.flag;
});
}
for (let i = 0; i < lis.length; i++) {
frg.appendChild(lis[i]);
}
lists.appendChild(frg);
};
}