vue实现点击文字出现带搜索的下拉列表组件同时实现自定义组件的双向绑定

283 阅读1分钟

实现效果:参考element-ui下拉样式实现

image.png

参考代码如下:

子组件代码:

<template>
    <span>
        <el-popover placement="bottom" trigger="click" v-model="visible" @show="visibleChange(options)">
            <el-scrollbar>
                <div style="max-height: 274px;">
                    <ul class="options-list">
                        <div style="padding: 0 8px 8px 8px">
                            <el-input class="search_input" type="text" v-model="searchText" @input="focusCustomer(options)" clearable></el-input>
                        </div>
                        <li v-for="(item, index) in allList" :key="index" :label="item.text" :value="item.text" @click="selectOption(item)">
                            {{ item.text }}
                        </li>
                    </ul>
                </div>
            </el-scrollbar>
            <span slot="reference" class="name">{{ localName }} </span>
        </el-popover>
    </span>
</template>
<script>
export default {
    data () {
        return {
            showDropdown: false,
            visible: false,
            searchText: "",
            allList: [],
            newArr: [],
            localName: this.name
        };
    },
    model: {
        event: "myChange",
        prop: "name"
    },
    props: {
        name: "",
        options: []
    },

    methods: {
        selectOption (option) {
            this.visible = false;
            this.localName = option.text
            this.$emit('myChange', option.text);
            this.$emit('select', option.text); // 发送选中的值给父组件
        },
        focusCustomer (val) {
            this.options = val;
            //     options是后端请求到的数据
            //         reg :trim是去除input两边的空格
            var reg = this.searchText.trim();
            //    如果输入框里有value值
            if (reg.length > 0) {
                //newArr 是 data中声明的空数组
                this.newArr = this.options.filter((item) => {
                    //    判断输入框的内容在下拉框是否存在
                    var numberfliter = item.text.toUpperCase().indexOf(reg.toUpperCase());
                    //    为0的时候,代表存在,-1为不存在
                    if (numberfliter == 0) {
                        //    直接返回有相同的给newArr数组
                        return item;
                    }
                });
                //    listt是选项变量的数组
                this.allList = this.newArr;
            } else {
                //    如果没有搜索词,就显示所有的数据
                this.allList = this.options;
            }
        },
        visibleChange (alternatives) {
            this.allList = alternatives;
        }
    },

};
</script>

<style scoped>
.input {
    width: 100%;
    padding: 8px;
    border: 1px solid #ccc;
}

.options-list {
    list-style: none;
    padding: 6px 0;
    margin: 0;
    box-sizing: border-box;
}
.options-list li {
    font-size: 14px;
    padding: 0 20px;
    position: relative;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    color: #606266;
    height: 34px;
    line-height: 34px;
    box-sizing: border-box;
    cursor: pointer;
}
.options-list li:hover {
    background-color: #f5f7fa;
}
.name {
    text-decoration: underline;
    text-decoration-skip-ink: auto;
    white-space: nowrap;
    text-decoration-color: #b2d235;
}
</style>

父组件

 <dropdown-select v-model="q.text" :options="q.alternatives" :name="q.text" @select="changeQuery"></dropdown-select>