cookie实现京东五星好评组件评分数据存储
实现目标:
实现京东五星好评部分的组件,实现鼠标经过星星时星星变红色,星星上方出现对应星级的笑脸,同时在评价n星后显示分数为n分,使用cookie缓存使用户在刷新页面后或者重新打开该页面时自动显示上次点击的星星评分,可重新评价,清除浏览器数据缓存后才会显示初始未评价页面。
html代码部分
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script type="module">
import Star from "./js/Star.js";
let list=["商品符合度","店家服务态度","快递配送速度","快递员服务","快递包装"]
for(var i=0;i<list.length;i++){
let star=new Star(list[i]);
star.appendTo("body");
}
</script>
</body>
</html>
js代码部分
import Component from "./Component.js";
export default class Star extends Component {
label = "";
starCon;
face;
score;
pos = -1;
starArr = [];
static STAR_NUM = 5;
constructor(_label) {
super();
this.label = _label;
console.log(this.label)
Object.assign(this.elem.style, {
width: "auto",
float: "left",
height: "16px",
paddingBottom: "10px",
marginRight: "20px",
paddingTop: "16px",
});
this.createLabel(_label);//创建本文
this.createStar();//创建星星
this.createScore();//创建分数
this.list = this.getCookie();//获取缓存
//需要写判断条件,当第一次打开该页面或上次有未评价选项再次打开页面时,没有cookie缓存,获取的缓存是个空对象,如果不写判断条件,该选项的分数会为undefined分
if (this.list[this.label]) {
this.changeStar(this.list[_label] - 1);
this.changeScore(this.list[_label]);
} else {
//当所有选项都有评价,再次打开浏览器先执行获取缓存,改变性星星和分数,使打开的页面显示与上次退出时一致
this.changeStar(-1);
this.changeScore(0);
}
}
// 获取缓存
getCookie() {
if (document.cookie.length === 0) return {};
return document.cookie.split(";").reduce((value, item) => {
var arr = item.split("=");
var v = arr[1].trim();
try {
v = JSON.parse(v);
} catch (e) {}
value[arr[0].trim()] = v;
return value;
}, {});
}
// 创建文本
createLabel(_label) {
let labels = document.createElement("span");
labels.textContent = _label;
Object.assign(labels.style, {
float: "left",
height: "16px",
lineHeight: "16px",
marginRight: "10px",
overflow: "hidden",
whiteSpace: "nowrap",
textOverflow: "ellipsis",
font:
'12px/150% tahoma,arial,Microsoft YaHei,Hiragino Sans GB,"\u5b8b\u4f53",sans-serif',
color: "#666",
});
this.elem.appendChild(labels);
}
// 创建星星
createStar() {
this.starCon = document.createElement("div");
Object.assign(this.starCon.style, {
float: "left",
height: "16px",
position: "relative",
marginTop: "1px",
});
for (let i = 0; i < Star.STAR_NUM; i++) {
let star = document.createElement("div");
Object.assign(star.style, {
width: "16px",
height: "16px",
float: "left",
backgroundImage: "url(./img/commstar.png)",
});
this.starArr.push(star);
this.starCon.appendChild(star);
}
//添加鼠标事件,鼠标经过星星时变色,点击星星时确定有几个星星颜色变色,移开鼠标时保持星星颜色为红色,同时修改显示的分数
this.starCon.addEventListener("mouseover", (e) => this.mouseHandler(e));
this.starCon.addEventListener("click", (e) => this.mouseHandler(e));
this.starCon.addEventListener("mouseleave", (e) => this.mouseHandler(e));
this.face = document.createElement("div");
Object.assign(this.face.style, {
width: "16px",
height: "16px",
backgroundImage: "url(./img/face-red.png)",
position: "absolute",
top: "-16px",
display: "none",
});
this.starCon.appendChild(this.face);
this.elem.appendChild(this.starCon);
}
// 创建分数
createScore() {
this.score = document.createElement("span");
Object.assign(this.score.style, {
position: "relative",
width: "30px",
height: "16px",
top: "-2px",
marginLeft: "10px",
lineHeight: "16px",
textAlign: "right",
color: "#999",
font:
'12px/150% tahoma,arial,Microsoft YaHei,Hiragino Sans GB,"\u5b8b\u4f53",sans-serif',
});
this.score.textContent = "0分";
this.elem.appendChild(this.score);
}
// 鼠标点击更改星星分数和笑脸
mouseHandler(e) {
switch (e.type) {
case "click":
case "mouseover":
let index = this.starArr.indexOf(e.target);
if (index < 0) return;
if (e.type === "click") {
this.pos = index;
this.setCookie();
} else {
this.changeScore(index + 1);
this.changeFace(index);
}
this.changeStar(index);
break;
case "mouseleave":
this.changeStar(this.pos);
this.changeScore(this.pos + 1);
this.changeFace(-1);
break;
}
}
// 改变星星
changeStar(n) {
for (var i = 0; i < this.starArr.length; i++) {
if (i <= n || i <= this.pos) {
this.starArr[i].style.backgroundPositionY = "-16px";
} else {
this.starArr[i].style.backgroundPositionY = "0px";
}
}
}
// 改分数
changeScore(n) {
this.score.textContent = n + "分";
if (n === 0) {
this.score.style.color = "#999";
} else {
this.score.style.color = "#e4393c";
}
}
// 改笑脸
changeFace(n) {
if (n < 0) {
this.face.style.display = "none";
return;
}
var index = Star.STAR_NUM - n - 1;
this.face.style.display = "block";
this.face.style.backgroundPositionX = -index * 20 + "px";
this.face.style.left = this.starArr[n].offsetLeft + "px";
}
// 添加缓存
//每次点击每一个评分项都将该项重新写入缓存
setCookie() {
var date = new Date();
date.setFullYear(2025);
document.cookie =
this.label + "=" + (this.pos + 1) + ";expires=" + date.toUTCString();
}
}
实现效果
初始状态:第一次刚打开页面时显示效果
鼠标经过时:改变星星颜色和显示对应星级笑脸与分数
鼠标点击后离开:星级确定,评分确定,笑脸不再显示
重新打开页面或重启浏览器:与鼠标点击后离开状态显示效果相同,如果清除浏览器缓存后打开,与第一次刚打开页面时显示效果相同
刷新页面后与重启浏览器时显示效果:
清除浏览器缓存后显示效果:
上述代码未添加抛出事件,添加后可以将对应评分项的评分以事件抛发的形式抛发出去,具体实现方法如下
//在鼠标点击事件中添加dispatch()函数,将每一个评分项的评分以evt的属性的形式抛发出去
static StarScoreList = {};//用来保存每个选项的分数,用来抛发
dispatch(){
Star.StarScoreList[this.label]=this.pos+1;
var evt=new Event("change");
evt.score=this.pos+1;
evt.label=this.label;
evt.scoreList=Star.StarScoreList;
this.dispatchEvent(evt);
}