下拉列表里的内容点击了一个后,li的hover效果就没有了

下拉列表里的内容点击了一个后,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);

正在回答

登陆购买课程后可参与讨论,去登陆

2回答

同学你好, 针对li的hover效果没有了的问题,解答如下:

因为点击li后,通过js设置的行内样式,所以此时通过css设置的hover样式不会生效。建议:在js代码中绑定mouseenter事件,设置鼠标移入样式。示例:

先定义一个变量,表示当前被点击元素的索引值,默认是-1,表示当前没有被点击的元素

http://img1.sycdn.imooc.com//climg/5eba150c09cf309f03540084.jpg

然后,在点击事件中设置activeIdx的值

http://img1.sycdn.imooc.com//climg/5eba154f09ac654f07940492.jpg

最后,给li绑定mouseenter事件

http://img1.sycdn.imooc.com//climg/5eba15a209c5d0f710960600.jpg

这是一个项目作业,同学完成作业后,在作业区域是可以上传作业的,会有批复作业的老师为你指导,并把问题与修改方案整理成文档发送给你,能够更好的帮助你完善作业。

祝学习愉快~

  • Aurora_Meteor 提问者 #1
    在点击的时候把元素的索引值修改以后,那它们不是就都不是-1了吗?可是为什么鼠标划过的时候只有当前被点击的元素会变为蓝底白字呢?之前点击过的元素索引值好像没有变化过的吧,应该都不是-1吧?
    2020-05-12 12:01:27
好帮手慕慕子 2020-05-12 14:51:13

同学你好,对于你的问题解答如下:

1、是的,当你点击元素时,会将activeIndex值修改为当前被点击元素的索引值。

2、在鼠标移入事件中,当activeIndex不等与-1时,也就是说此时的activeIndex值是被点击元素的索引值,给被点击元素设置了样式为蓝底白字。

http://img1.sycdn.imooc.com//climg/5eba471609d3d92e08000170.jpg

3、因为每次点击元素时,activeIndex值都会被重新赋值,所以之前点击的不会影响当前被点击的元素。

同学可以试着理解下,祝学习愉快~

问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师