下拉列表里的内容点击了一个后,li的hover效果就没有了
题目要求移入下拉列表里的每一项时,背景变为灰色,我的只有一开始没有选择的时候移入会变为灰色(使用css里的hover伪类设置的,不知道是不是应该使用js的事件设置?)。在点击了一个li以后,再点开下拉列表,移入li就没有背景变灰的效果了,但是cursor:poionter的效果却还有。
另外麻烦老师看一下还有没有别的什么问题。
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div id="wrap">
<div class="define">
<div class="title">自定义select</div>
<p class="select">
<span class="content">未选择</span>
<span class="arrow"></span>
</p>
<div class="list">
<input type="text" placeholder="搜索">
<div class="type">
<div>
<span class="name">构建工具</span>
<ul></ul>
</div>
<div>
<span class="name">前端框架</span>
<ul></ul>
</div>
</div>
</div>
</div>
<div>
<p id="out"></p>
</div>
<div>
<div class="title">原生select</div>
<select>
<option value="1" type="构建工具">Babel</option>
<option value="2" type="构建工具">Webpack</option>
<option value="3" type="构建工具">Rollup</option>
<option value="4" type="前端框架">Vue</option>
<option value="5" type="前端框架">Angular</option>
<option value="6" type="前端框架">React</option>
<option value="7" type="前端框架">Nerv</option>
</select>
</div>
</div>
<script src="js/data.js"></script>
<script src="js/index.js"></script>
<script>
const option = new $Option({
data,
parasitifer: '#wrap'
});
</script>
</body>
</html>
css/style.css
* {
padding: 0;
margin: 0;
}
html,
body {
width: 100%;
height: 100%;
}
body {
display: flex;
justify-content: center;
align-items: center;
background-color: #eee;
}
#wrap {
display: flex;
flex-direction: column;
justify-content: space-between;
}
#wrap>div {
display: flex;
flex-direction: column;
align-items: center;
margin: 20px auto;
}
.title {
color: dodgerblue;
margin: 20px;
}
/* 下拉框 */
.select {
margin: 10px auto 0;
width: 300px;
height: 30px;
display: flex;
cursor: pointer;
}
.select .content {
width: 85%;
height: 30px;
line-height: 30px;
padding-left: 5px;
background-color: #fff;
box-shadow: 0 0 0 1px rgb(114, 192, 223) inset;
font-size: 15px;
}
.select .arrow {
width: 15%;
height: 100%;
background-color: rgb(114, 192, 223);
position: relative;
}
.select .arrow::after {
content: ' ';
display: block;
width: 0;
height: 0;
border: 8px solid;
border-color: #fff transparent transparent;
position: absolute;
left: 14.5px;
top: 11.5px;
}
.define {
position: relative;
}
/* 下拉列表 */
.list {
margin: 0 auto !important;
width: 300px;
max-height: 200px;
position: absolute;
top: 100%;
background-color: #fff;
overflow: auto;
display: none;
flex-direction: column;
align-items: flex-start;
transition: all .2s;
box-shadow: 0 0 0 1px rgb(114, 192, 223) inset;
}
.list input {
width: 90%;
padding: 5px;
margin: 5px 0 0 5px;
}
.list .type {
width: 95%;
}
.list .type div {
padding-left: 5px;
line-height: 30px;
font-size: 17px;
}
.list .type .name {
font-weight: bold;
}
.list .type div ul li {
list-style: none;
width: 100%;
height: 30px;
line-height: 30px;
padding-left: 5px;
font-size: 15px;
}
.list .type div ul li:hover {
background-color: #eee;
cursor: pointer;
}
/* 列表下面显示改变前后的值的部分 */
#out {
text-align: center;
font-size: 17px;
}
js/data.js
// 获取select每一项option的集合
const options = document.querySelectorAll('option');
const data = [];
// 遍历option集合,将每一项的内容插入data中
options.forEach(option => {
data.push({
value: option.value,
type: option.getAttribute('type'),
text: option.innerText
});
});
js/index.js
(function(window, document) {
// 公共方法集合
const methods = {
appendChild(parent, ...children) {
children.forEach(el => {
parent.appendChild(el);
});
},
$(selector, root = document) {
return root.querySelector(selector);
},
$$(selector, root = document) {
return root.querySelectorAll(selector);
}
};
// 构造函数
let Option = function(options) {
this._init(options);
this._createElement();
this._bind();
}
// 初始化
Option.prototype._init = function({
data,
parasitifer
}) {
this.parasitifer = methods.$(parasitifer); // 挂载点
this.types = []; //所有的分类
this.all = []; // 所有select内的选项
this.classified = {}; //按照类型分类后的select内容
this._classify(data);
};
// 对select的每一项内容进行分类
Option.prototype._classify = function(data) {
this.values = [];
this.texts = [];
data.forEach(({
value,
type,
text
}) => {
if (!this.types.includes(type)) {
this.types.push(type);
}
if (!Object.keys(this.classified).includes(type)) {
this.classified[type] = [];
}
if (!this.texts.includes(text)) {
// 选项没有生成过,生成选项,添加到对应的分类中
this.texts.push(text);
this.values.push(value);
this.classified[type].push(this.texts[this.texts.length - 1]);
} else {
// 选项生成过,去all中找到对应的选项,添加到对应的分类中
this.classified[type].push(this.texts[this.texts.findIndex(s1 => s1 === text)]);
}
});
};
// 生成DOM
Option.prototype._createElement = function() {
let list = methods.$('.list');
let names = methods.$$('.name', list);
Object.keys(this.classified).forEach(type => {
names.forEach(name => {
if (name.innerText === type) {
this.classified[type].forEach(value => {
var li = document.createElement('li');
li.innerText = value;
methods.appendChild(name.nextElementSibling, li);
});
}
});
});
};
// 显示隐藏元素
Option.prototype._showHide = function(el, dis) {
el.style.display = dis;
}
// 绑定事件
Option.prototype._bind = function() {
// 已显示的搜索框
let select = methods.$('.select', this.parasitifer);
// 要显示的下拉列表
let list = methods.$('.list', this.parasitifer);
// 下拉列表里的搜索框
let search = methods.$('input', list);
// 所有的li元素
let lis = methods.$$('li', list);
// 下拉框
let content = methods.$('.content', select);
// 列表下面显示改变前后的值的部分
let out = methods.$('#out', this.parasitifer);
var bool = true;
// 点击搜索框显示select
select.addEventListener('click', e => {
e.stopPropagation();
if (bool) {
this._showHide(list, 'flex');
bool = false;
} else {
this._showHide(list, 'none');
bool = true;
}
});
// 点击下拉列表的时候,它不会隐藏
list.addEventListener('click', e => {
e.stopPropagation();
this._showHide(list, 'flex');
});
// 点击非下拉框的部分收起下拉列表
document.addEventListener('click', () => {
this._showHide(list, 'none');
bool = true;
});
// 根据下拉列表的搜索框里输入的内容,对分类进行筛选
search.addEventListener('input', () => {
// 搜索框里输入的内容
let searchContent = search.value;
lis.forEach(li => {
// 隐藏所有的li
this._showHide(li, 'none');
// 显示包含输入的内容的li
if (li.innerText.includes(searchContent)) {
this._showHide(li, 'block');
}
});
});
// 给所有的li绑定事件
lis.forEach(li => {
li.addEventListener('click', e => {
e.stopPropagation();
// 恢复所有li的背景和字体
lis.forEach(li => {
li.style.background = '#fff';
li.style.color = '#000';
});
// 设置当前li的背景和字体
li.style.background = 'rgb(114, 192, 223)';
li.style.color = '#fff';
// 改变前的值
let prevText = content.innerText;
let prevValue = this.values[this.texts.findIndex(text => text === prevText)];
// 改变后的值
let nextText = li.innerText;
let nextValue = this.values[this.texts.findIndex(text => text === nextText)];
// 改变上面搜索框的内容
content.innerText = nextText;
// 改变列表下面显示改变前后的值的部分里的内容
out.innerText = `
之前的值是 ${prevText} - ${prevValue}
改变后的值是 ${nextText} - ${nextValue}
`;
// 隐藏下拉列表
this._showHide(list, 'none');
bool = true;
});
});
};
window.$Option = Option;
})(window, document);
正在回答
同学你好, 针对li的hover效果没有了的问题,解答如下:
因为点击li后,通过js设置的行内样式,所以此时通过css设置的hover样式不会生效。建议:在js代码中绑定mouseenter事件,设置鼠标移入样式。示例:
先定义一个变量,表示当前被点击元素的索引值,默认是-1,表示当前没有被点击的元素
然后,在点击事件中设置activeIdx的值
最后,给li绑定mouseenter事件
这是一个项目作业,同学完成作业后,在作业区域是可以上传作业的,会有批复作业的老师为你指导,并把问题与修改方案整理成文档发送给你,能够更好的帮助你完善作业。
祝学习愉快~
- 参与学习 人
- 提交作业 239 份
- 解答问题 10739 个
本阶段带你深入前端开发的肌理,通过ES6基础知识和前端主流高级框架的学习,助你快速构建企业级移动webAPP应用,进入职场的终极battle
了解课程
恭喜解决一个难题,获得1积分~
来为老师/同学的回答评分吧
0 星