vue实现带搜索的模拟下拉框组件

先上效果图:

组件特点:

  • 模拟下拉框
  • 可输入文字搜索选项,keyup或input事件触发搜索(并优化了原生keyup和input事件的问题)
  • 数据源异步加载
  • 滚动加载选项数据
  • 同一页面可重复使用该组件

技术工具说明:

  • 基础框架 vue.js
  • jquery.js辅助
  • 样式 element-ui.js
  • 注意:非单页面,非前后端分离开发


进入正文:

创建项目

1. 新建项目文件夹 cw-input-select

打开,以下内容都是在此文件夹内操作,不赘述

2. 新建demo.html

  1. 引用jquery,vue,element-ui(cdn)
  2. 创建一个id="app"的根元素
  3. 在body元素尾部添加<script></script>标签,创建vue实例(这部分代码也可以单独写一个js文件)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <script src="https://cdn.bootcss.com/vue/2.6.10/vue.min.js"></script>
    <script src="https://cdn.bootcss.com/element-ui/2.10.1/index.js"></script>
</head>
<body>
    <div id="app">
        
    </div>

    <script>
        new Vue({
            el: '#app'
        })
    </script>
</body>
</html>

3. 新建文件夹component,并在里面新建cw-input-select.js和cw-input-select.css文件

结构如下:

| cw-input-select

  | demo.html

  | component

    | cw-input-select.js

    | cw-input-select.css

4. 在demo.html header标签里引入cw-input-select.js和cw-input-select.css

    <!-- 引入cw-input-select组件 -->
    <link rel="stylesheet" href="component/cw-input-select.css">
    <script src="component/cw-input-select.js"></script>

编写组件

1.编写一个vue全局组件 cw-input-select

component/cw-input-select.js

Vue.component('cw-input-select', {
    template: '<div></div>',
    data: function () {
        return {}
    },
    created () {},
    methods: {},
})

2.在demo.html 添加组件标签

demo.html

<div id="app">
    <cw-input-select></cw-input-select>
</div>

3. 实现静态(无动态数据无交互)的下拉框布局和样式,并用静态数组模拟选项(后面替换动态数据源)

component/cw-input-select.js

Vue.component('cw-input-select', {
    template: `<div class="cw-input-select_wrap">
    <div class="cw-input-select">
        <div class="cw-input-select_box">
            <span>请选择</span>
        <i class="cw-arrow"></i>
        </div>
        <div class="cw-input-select_pop">
            <input type="text" class="cw-input-select_ipt" placeholder="搜索" />
            <ul class="cw-input-select_options">
                <li>
                    <span>不限</span>
                </li>
                <li v-for="option in optionsList">
                    {{option}}
                </li>
            </ul>
            <span class="cw-input-select_arrow"></span>
        </div>
    </div>
</div>`,
    data: function () {
        return {
            optionsList: ['选项1', '选项2', '选项3']
        }
    },
    created () {},
    methods: {},
})

component/cw-input-select.css

/* 基础样式reset */
input {
    box-sizing: border-box;
    outline: 0;
}
ul {
    margin: 0;
    padding: 0;
}
ul, li {
    list-style: none;
}

/* 组件整体容器 */
.cw-input-select_wrap {
    position: relative;
    width: 198px;
    height: 28px;
    font-size: 14px;
}

/* 组件内容 */
.cw-input-select {
    width: 198px;
    position: absolute;
}

/* 基本下拉框 */
.cw-input-select_box {
    height: 28px;
    border: 1px solid #b7b7b7;
    border-radius: 4px;
    background-color: white;
    position: relative;
    cursor: pointer;
}

/* 基本下拉框里面右边的线体上下箭头(可旋转) */
.cw-arrow {
    content: '';
    display: block;
    position: absolute;
    right: 10px;
    top: 8px;
    border-top: 1px solid #C0C4CC;
    border-right: 1px solid #C0C4CC;
    border-radius: 1px;
    width: 8px;
    height: 8px;
    background: transparent;
    transition: transform .3s, -webkit-transform .3s;
    transform: rotate(135deg);
    z-index: 10;
}

/* 基本下拉框 文字 */
.cw-input-select_box > span {
    display: inline-block;
    line-height: 28px;
    padding: 0 30px 0 15px;
    font-size: 12px;
    color: #606266;
    /* 文字超出用省略号 */
    white-space: nowrap;
    text-overflow: ellipsis;
    width: 100%;
    overflow: hidden;
}

/* 选项列表盒子 */
.cw-input-select_pop {
    position: relative;
    background-color: white;
    border: 1px solid #E4E7ED;
    border-radius: 4px;
    max-height: 274px;
    box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
    margin-top: 12px;
    padding: 5px;
    box-sizing: border-box;
    z-index: 9;
}

/* 选项列表盒子上方的三角形箭头 */
.cw-input-select_arrow {
    position: absolute;
    display: block;
    width: 0;
    height: 0;
    border-color: transparent;
    border-style: solid;
    border-width: 6px;
    filter: drop-shadow(0 2px 12px rgba(0, 0, 0, .03));
    top: -6px;
    left: 35px;
    margin-right: 3px;
    border-top-width: 0;
    border-bottom-color: #fff;
    z-index: 99;
}

/* 选项列表盒子里面的输入框 */
.cw-input-select .cw-input-select_pop .cw-input-select_ipt {
    position: absolute;
    top: 5px;
    z-index: 99;
    height: 24px;
    line-height: 20px;
    width: 94%;
    border: 1px solid #DCDFE6;
    padding: 1px 5px;
    font-size: 12px;
}

/* 选项列表内容 */
.cw-input-select_options {
    display: block;
    margin-top: 26px;
    max-height: 234px;
}

/* 选项单元 */
.cw-input-select_options li {
    padding: 8px 15px;
    background-color: white;
    cursor: pointer;
}

/* 选项单元hover */
.cw-input-select_options li:hover {
    background-color: #F5F7FA;
}
点击查看css

 css注释我尽量写详细,因为很难把css分开讲解。

至此,效果如下:

-

4. 实现点击基本框显示或隐藏选项列表盒子,线体箭头可上下旋转

(1)在基本框class=cw-input-select_box的div上添加click事件调用selectHandle方法

<div class ="cw-input-select_box" v-on:click="selectHandle">

 (2)在组件实例data选项里添加一个变量isShowPop,methods选项里添加selectHandle方法

    data: function () {
        return {
            optionsList: ['选项1', '选项2', '选项3'],
            isShowPop: false
        }
    },
    methods: {
        // 点击基本框显示或隐藏选项列表盒子
        selectHandle: function () {
            this.isShowPop = !this.isShowPop;
        },
    },

(3)在class=cw-input-select_pop的div上添加v-if="isShowPop"

<div class="cw-input-select_pop" v-if="isShowPop">

(4)为了测试多个组件是否互相干扰,可在demo.html添加多个<cw-input-select></cw-input-select>看看效果。不会干扰。

(5)此时有个小问题

每次点击组件,很容易把文字选中,我们使用下拉框并不需要文字选中效果。

解决办法:

在组件最外层div加上 onselectstart="return false"

<div class="cw-input-select_wrap" onselectstart="return false">

就好了。现在无论点击多少次文字都不会被选中。

(6)基本框右侧箭头的旋转

这个只需要css就可以搞定

在cw-input-select.css文件的.cw-arrow下面添加.cw-arrow.up

/* 箭头向上 */
.cw-arrow.up {
    transform: rotate(-45deg);
    top: 12px;
}

回到组件js文件

<i class="cw-arror"></i> 添加 v-bind:class="{'up': isShowPop}"

<i class="cw-arrow" v-bind:class="{'up': isShowPop}"></i>

至此完成了点击基本框显示和隐藏选项列表的功能。

5. 点击本组件以外的范围,隐藏选项列表盒子(如果它正显示着)

怎么实现?在body上添加一个点击事件?组件内部是无法操纵调用它的父级页面的,也不是无法操纵,记得vue文档上说过,最好不要这么干。 但现在没有别的办法,且先如此尝试一下。

(1)先在组件methods里定义一个专门用来隐藏的方法hidePop

        hidePop: function () {
            this.isShowPop = false;
        }

(2)再在组件created钩子函数里面给body绑定click事件,调用hidePop方法,并排除组件自身的范围

    created: function () {
        // 点全局范围收起下拉框
        var that = this;
        $('body').click(function (e) {
            console.log(e);
            if (e.target.className=='cw-input-select_wrap' || $(e.target).parents('.cw-input-select_wrap').length>0) {
                return;
            }
            that.hidePop();
        });
    },

 这里注意,因为页面上内容少,body的高度也很小,所以点击页面空白处是不会触发body上的click事件的。此时,需要给body设置高度。至此demo.html完整代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <script src="https://cdn.bootcss.com/vue/2.6.10/vue.min.js"></script>
    <script src="https://cdn.bootcss.com/element-ui/2.10.1/index.js"></script>

    <!-- 引入cw-input-select组件 -->
    <link rel="stylesheet" href="component/cw-input-select.css">
    <script src="component/cw-input-select.js"></script>
    <style>
        body {
            height: 100vh;
        }
    </style>
</head>
<body>
    <div id="app">
        <div style="display: inline-block;">
            <cw-input-select></cw-input-select>
        </div>
        <div style="display: inline-block;">
            <cw-input-select></cw-input-select>
        </div>
    </div>

    <script>
        new Vue({
            el: '#app'
        })
    </script>
</body>
</html>
查看demo.html代码

这一需求基本完成,但是又有个小问题,点击另一个组件的时候,其他组件的选项列表盒子是不会隐藏的。因为所有的组件都满足 e.target.className=='cw-input-select_wrap' ,如何区别让当前点击的这个组件?

思来想去,我也没有更好的办法,最简单直接的办法就是在父页面调用组件的时候传入一个唯一识别——componentId,当然我试过在组件内部用13位时间戳生成唯一componentId,结果就是多个组件可能生成重复的componentId,这是为什么?说明vue组件生成的时间比时间戳还快。

(3)组件props选项,添加componentId接口

props: ['componentId'],

(4)在组件最外层容器上添加 v-bind:id="componentId"

<div v-bind:id="componentId" class="cw-input-select_wrap" v-bind:class="{'open': isShowPop}" onselectstart="return false">

(5)在demo.html 组件标签上添加 component-id属性传入不一样的值

    <div id="app">
        <div style="display: inline-block;">
            <cw-input-select component-id="cw-input-select-1"></cw-input-select>
        </div>
        <div style="display: inline-block;">
            <cw-input-select component-id="cw-input-select-2"></cw-input-select>
        </div>
        <div style="display: inline-block;">
            <cw-input-select component-id="cw-input-select-3"></cw-input-select>
        </div>
    </div>

注意:相信你们很多人都知道,就是props里面写的驼峰名称,在标签里面要使用-拼接式,比如componentId,对应component-id. 我当初就掉进过这个坑。

为了测试效果,我们放3个组件

至此,我们可以区分组件,并且在组件内部可以拿到component-id进行操作。

(6)回到组件$('body').click()事件里面,修改如下:

    created: function () {
        // 点全局范围收起下拉框
        var that = this;
        $('body').click(function (e) {
            if (e.target.id==that.componentId || $(e.target).parents('#' + that.componentId).length>0) {
                return;
            }
            that.hidePop();
        });
    },

注意:click function里面一定要用that代替this,否则,呵呵

 完美实现了点击组件以外范围隐藏选项列表盒子

外部的事情解决了,现在完善组件内部的功能。

6.模拟下拉框选中效果

 (1)在组件data选项里添加一个变量selectedValue来保存选中值

component/cw-input-select.js data 选项:

    data: function () {
        return {
            optionsList: ['选项1', '选项2', '选项3'],
            isShowPop: false,
            selectedValue: '', // 选中值
        }
    },

(2)在基本框的span里渲染selectedValue,有值则显示值,无值则显示“请选择”

component/cw-input-select.js template选项:

        <div class="cw-input-select_box" v-on:click="selectHandle">
            <span>{{selectedValue || '请选择'}}</span>
            <i class="cw-arrow" v-bind:class="{'up': isShowPop}"></i>
        </div>

(3)现在,在选项li上添加点击事件,来修改选中值

component/cw-input-select.js template选项:

            <ul class="cw-input-select_options">
                <li v-on:click="selected('不限')">
                    <span>不限</span>
                </li>
                <li v-for="option in optionsList" v-on:click="selected(option)">
                    {{option}}
                </li>
            </ul>

(4)在组件methods选项 添加selected方法

        // 点击选项
        selected: function (val) {
            this.selectedValue = val;
            this.isShowPop = false;
        }

选中值功能完成。

到此为止,这个模拟的下拉框只适用于简单的选项,但我们工作中经常遇到对象数组的选项。

7. 兼容由对象组成的数组选项列表

(1)在组件data选项里的添加一个由对象组成的数组optionsList2(optionsList和optionsList2都是临时的,后面会讲动态获取选项列表)

    data: function () {
        return {
            optionsList: ['选项1', '选项2', '选项3'],
            optionsList2: [{
                id: 1,
                name: '选项A',
            },{
                id: 2,
                name: '选项B',
            },{
                id: 3,
                name: '选项C',
            }],
            isShowPop: false,
            selectedValue: '', // 选中值
        }
    },

(2)在选项li里面添加v-if判断

                <li v-for="option in optionsList2" v-on:click="selected(option)">
                    <span v-if="typeof option == 'object'">{{option.name}}</span>
                    <span v-else>{{option}}</span>
                </li>

现在你手动修改v-for里面的数据源,无论是optionsList还是optionsList2都能正确地渲染选项名称。

但是点击选中值好像有点奇怪,基本框里直接显示了一个对象,这是正常的,接下来我们需要修改selected方法,让它兼容两种数据

(3)修改selected方法

        // 点击选项
        selected: function (val) {
            var value;
            if (typeof val == 'object') { // 对象数据
                value = val.name;
            } else { // 简单数据
                value = val;
            }
            this.selectedValue = value;
            this.isShowPop = false;
        }

这段代码可以用三元表达式写得更简洁

        // 点击选项
        selected: function (val) {
            this.selectedValue = typeof val == 'object' ? val.name : val;
            this.isShowPop = false;
        }

数据本身并不属于组件,所以需要把数据分离出来。

8. 动态传入选项列表

(1)在根目录下新建一个data.js ,创建几个有代表性的数组

MUSICALS 是一个简单数组
BOOKS和PLANTS是两个label和value名不一样的对象数组

data.js代码如下:

const MUSICALS = ['钢琴', '吉他', '小提琴', '架子鼓']

const BOOKS = [
    {
        bookId: '1222ssw',
        name: '海边的卡夫卡'
    },
    {
        bookId: '998435j',
        name: '树上的男爵'
    },
    {
        bookId: 'iwihsn222',
        name: '挪威的森林'
    },
    {
        bookId: '2231ff',
        name: '1Q84'
    }
]

const PLANTS = [
    {
        id: 001,
        ename: 'Sinocrassula'
    },
    {
        id: 002,
        ename: 'Orostachys'
    },
    {
        id: 003,
        ename: 'Hylotelephium'
    },
    {
        id: 004,
        ename: 'Phedimus'
    },
    {
        id: 005,
        ename: 'Sempervivum'
    },
    {
        id: 006,
        ename: 'Monanthes'
    },
    {
        id: 007,
        ename: 'Aeonium'
    },
    {
        id: 008,
        ename: 'Dudleya'
    }
]
点击查看data.js

(2)在demo.html 引入data.js

<script src="data.js"></script>

(3)在demo.html <script> Vue实例data选项里添加3个变量,引用data.js里面的数据

    <script>
        new Vue({
            el: '#app',
            data () {
                return {
                    musicals: MUSICALS, // 乐器
                    books: BOOKS, //
                    plants: PLANTS, // 植物
                }
            },
        })
    </script>

(4)现在需要改写cw-input-select组件,让它能够接收外来的数据作为选项

首先在组件props选项里面添加 'options'

component/cw-input-select.js

props: ['componentId', 'options'],

在组件created钩子函数里给optionsList赋值

    created: function () {
        this.optionsList = JSON.parse(JSON.stringify(this.options));
        // 点全局范围收起下拉框
        var that = this;
        $('body').click(function (e) {
            if (e.target.id==that.componentId || $(e.target).parents('#' + that.componentId).length>0) {
                return;
            }
            that.hidePop();
        });
    },

组件data选项修改如下:

    data: function () {
        return {
            optionsList: [],
            isShowPop: false,
            selectedValue: '', // 选中值
            searchTxt: '', // 搜索词
        }
    },

删掉临时数据源optionsList2

(5)在demo.html 组件标签上通过options传入数据

    <div id="app">
        <div style="display: inline-block;">
            <cw-input-select component-id="cw-input-select-1" v-bind:options="musicals"></cw-input-select>
        </div>
        <div style="display: inline-block;">
            <cw-input-select component-id="cw-input-select-2" v-bind:options="books"></cw-input-select>
        </div>
        <div style="display: inline-block;">
            <cw-input-select component-id="cw-input-select-3" v-bind:options="plants"></cw-input-select>
        </div>
    </div>

现在浏览一下效果,应该是实现了。但是第三个下拉框选项列表没有名称,是空白的。这是因为我们把对象选项渲染的名称写死了,选项名称必须是name,否则就不显示。这可不行。我们需要适应不同的名称。

9. 适应不同的选项名称

(1)在组件props添加'labelName'

props: ['componentId', 'options', 'labelName'],

(2)在demo.html 需要的组件标签上添加属性 label-name

像第一个组件上传入的是简单的数据,就不需要label-name

    <div id="app">
        <div style="display: inline-block;">
            <cw-input-select component-id="cw-input-select-1" v-bind:options="musicals"></cw-input-select>
        </div>
        <div style="display: inline-block;">
            <cw-input-select component-id="cw-input-select-2" v-bind:options="books" label-name="name"></cw-input-select>
        </div>
        <div style="display: inline-block;">
            <cw-input-select component-id="cw-input-select-3" v-bind:options="plants" label-name="ename"></cw-input-select>
        </div>
    </div>

(3)修改组件写死的name,有2处,

一个是选项li里面,

                <li v-for="option in optionsList" v-on:click="selected(option)">
                    <span v-if="typeof option == 'object'">{{option[labelName]}}</span>
                    <span v-else>{{option}}</span>
                </li>

一个是selected方法里面

        // 点击选项
        selected: function (val) {
            this.selectedValue = typeof val == 'object' ? val[this.labelName] : val;
            this.isShowPop = false;
        },

现在第三个下拉框的选项也显示了,不过内容超出了...

10. 选项列表滚动条

(1)给cw-input-select_options添加overflow-y: scroll (或auto,就是不能hidden)

component/cw-input-select.css .cw-input-select_options

/* 选项列表内容 */
.cw-input-select_options {
    display: block;
    margin-top: 26px;
    max-height: 234px;
    overflow-y: scroll; /* 超出滚动 */
}

滚动是有了,不过内容没超出的也有一个难看的滚动条背景。接下来就写美化滚动条。

(2)美化滚动条

component/cw-input-select.css 添加如下代码:

/*自定义滚动条样式*/
.cw-input-select_options::-webkit-scrollbar { /*滚动条整体样式*/
    width: 6px; /*高宽分别对应横竖滚动条的尺寸*/
    height: 0;
}

.cw-input-select_options::-webkit-scrollbar-thumb { /*滚动条里面小方块*/
    border-radius: 6px;
    background-color: rgba(144,147,153,0.3);
    transition: background-color 0.3s;
}

.cw-input-select_options::-webkit-scrollbar-track { /*滚动条里面轨道*/
    border-radius: 6px;
    background: transparent;
}

这是一段可通用的滚动条美化代码

现在选项列表滚动条好看多了。但是我发现element-ui里面的下拉框组件只有鼠标移上去才显示滚动条,如何做到这个效果?

把.cw-input-select_options::-webkit-scrollbar-thumb里面的背景颜色alpha值改成0,hover的时候改成0.3

.cw-input-select_options::-webkit-scrollbar-thumb { /*滚动条里面小方块*/
    border-radius: 6px;
    background-color: rgba(144,147,153,0); /* 重点在这里!! */
    transition: background-color 0.3s;
}
.cw-input-select_options:hover::-webkit-scrollbar-thumb {
    background-color: rgba(144,147,153,0.3);
}

这就是为什么我用rgba作background-color的值,用其他的值实现不了这个效果的。

好了,今天就写到这里吧。马上要下班了。没想到一个不算太难的组件教程我写了一整天。并且还没写完。我都开始怀疑有没有写的必要,到底是写给谁看呢?是不是该提高下写教程的效率?

 

11. 选项搜索

不同的数据源,选项搜索方式也不同。主要有两种,一种是传入固定的数组作为选项数据源,一种是请求接口动态获取数据。

我自己工作中用到的是后者,在这里为了方便演示,我用前者。

(1)给组件选项搜索框添加input事件

<input type="text" v-model="searchTxt" v-on:input="searchHandle(searchTxt)" class="cw-input-select_ipt" placeholder="搜索" />

(2)在组件methods选项里添加searchHandle方法

        // 选项搜索
        searchHandle (val) {
            // 深拷贝一份源数据
            var originList = JSON.parse(JSON.stringify(this.options));
            // filter过滤函数
            this.optionsList = originList.filter((item, index) => {
                // 根据选项类型给名称赋值
                var content = typeof item == 'object' ? item[this.labelName] : item;
                return content.indexOf(val) > -1;
            });
        }

这里要注意,如果不用箭头函数,函数体内的this不代表外面的this.

此时,如果输入空格,也一样会执行搜索,解决办法有2个,一是在input标签v-model上加.trim修饰符

二是在searchHandle方法里面过滤空格。

12.搜索清除

(1)先写布局和样式

这里清除图标将和输入框作为一个整体,所以先在输入框外面包裹一层div

            <div class="cw-input-select_ipt_wrap">
                <input type="text" v-model="searchTxt" v-on:input="searchHandle(searchTxt)" class="cw-input-select_ipt" placeholder="搜索" />
                <span class="icon-clear">
                    <svg t="1575258400555" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2468" width="16" height="16"><path d="M509.866667 32C245.333333 32 32 247.466667 32 512s213.333333 480 477.866667 480S987.733333 776.533333 987.733333 512 774.4 32 509.866667 32z m0 896C281.6 928 96 742.4 96 512S281.6 96 509.866667 96 923.733333 281.6 923.733333 512s-185.6 416-413.866666 416z" fill="#8a8a8a" p-id="2469"></path><path d="M693.333333 330.666667c-12.8-12.8-32-12.8-44.8 0L512 467.2l-136.533333-136.533333c-12.8-12.8-32-12.8-44.8 0-12.8 12.8-12.8 32 0 44.8l136.533333 136.533333-136.533333 136.533333c-12.8 12.8-12.8 32 0 44.8 6.4 6.4 14.933333 8.533333 23.466666 8.533334s17.066667-2.133333 23.466667-8.533334l136.533333-136.533333 136.533334 136.533333c6.4 6.4 14.933333 8.533333 23.466666 8.533334s17.066667-2.133333 23.466667-8.533334c12.8-12.8 12.8-32 0-44.8L556.8 512l136.533333-136.533333c12.8-12.8 12.8-32 0-44.8z" fill="#8a8a8a" p-id="2470"></path></svg>
                </span>
            </div>

图标使用iconfont svg,缺点是代码一大堆,优点是用法简单,复制粘贴即可使用,样式可控。对于这种演示demo非常适合。项目中一半用font awesome,引入成套的样式组件等等……

添加样式

cw-input-select.css

.cw-input-select_ipt_wrap {
    position: relative;
}
.icon-clear {
    color: #aaa;
    position: absolute;
    right: 18px;
    top: 9px;
    z-index: 99;
    cursor: pointer;
}

(2)清除功能

清除图标默认隐藏,搜索框有内容时才显示。

<span class="icon-clear" v-if="searchTxt">...</span>

给清除图标添加点击事件绑定清除方法

<span class="icon-clear" v-if="searchTxt" v-on:click="clearHandle">...</span>

清除方法

cw-input-select.js methods选项:

        // 清除搜索
        clearHandle () {
            this.searchTxt = '';
            // 深拷贝一份源数据
            this.optionsList = JSON.parse(JSON.stringify(this.options));
        }

此时清除是实现了,不过效果有点奇怪,清除的同时选项列表盒子也瞬间隐藏了,应该是body的点击事件没有过滤掉清除图标。解决办法就是在clearHandle添加阻止冒泡方法。

clearHandle方法修改如下:

        // 清除搜索
        clearHandle (e) {
            e.stopPropagation();
            this.searchTxt = '';
            // 深拷贝一份源数据
            this.optionsList = JSON.parse(JSON.stringify(this.options));
        }

这样就完美了。

完整代码

组件github地址

 

https://github.com/cathy1024/cw-ui/tree/master/cw-ui/cw-input-select

(完)

原文地址:https://www.cnblogs.com/cathy1024/p/11952986.html