vue组件实践-可搜索下拉框扩展

一、效果
这里写图片描述

二、代码
dropdown-ext.vue

<template>
    <div class="vue-dropdown-ext" :class="themestyle" v-show-extend="show">
        <div class="search-module clearfix" v-show="itemlist.length">
            <input class="search-text" @keyup='search($event)' 
            :placeholder="placeholder" />
            <span class="glyphicon glyphicon-search search-icon"></span>
        </div>
        <ul class="list-module" v-show="length" :style="{maxHeight:maxH+'px'}">
            <li v-for ="(item,index) in datalist" @click="appClick(item,$event)" 
            :key="index" :title="item.name">
                <span v-if="addIcon" :class="iconClass"></span>
                :style="itemTextStyle">{{item.name}}</span>
                <span v-if="statusIconType == 'text' && hasStatus" 
                :class="item.statusClass">{{item.statusText}}</span>
                 :class="item.statusClass"></span>
            </li>
        </ul>
        <div class="tip__nodata" v-show="!length&&itemlist.length">
        {{nodatatext}}
        </div>
    </div>
</template>

<script>
    export default {
        data(){
            return {
                datalist:[]
            }
        },
        props:{
            'show':{//用于外部控制组件的显示/隐藏
                type:Boolean,
                default:true
            },
            'itemlist':Array,
            'placeholder':String,
            'nodatatext':String,
            'themestyle':{
                type:String,
                default:'default-theme'
            },
            'item-text-style':{
                type:Object,
                default:function(){
                    return {
                        width:'80%'
                    }
                }
            },
            'add-icon':{
                type:Boolean,
                default:true
            },
            'icon-class':{
                type:String,
                default:''
            },
            'has-status':{
                type:Boolean,
                default:false
            },
            'status-icon-type':{
                type:String,
                default:'text'//text or icon
            },
            'max-h':{
                type:Number,
                default:$(window).height()-400
            }
        },
        watch:{
            itemlist:function(val){
                this.datalist = val.concat();
            }
        },
        directives:{
            'show-extend':function(el,binding,vnode){//bind和 update钩子
                let value = binding.value,searchInput = null;
                if(value){
                    el.style.display='block';
                }else{//隐藏后,恢复初始状态
                    el.style.display='none';
                    searchInput = el.querySelector(".search-text");
                    searchInput.value = '';
                    //还原渲染数据
                    vnode.context.datalist = vnode.context.itemlist;
                }
            }
        },
        methods:{
            appClick:function(data,event){
                this.$emit('item-click',data,event);
            },
            search:function(e){
                let vm = this,searchvalue = e.currentTarget.value;
                vm.datalist = vm.itemlist.filter(
                function(item,index,arr){
                    return item.name.indexOf(searchvalue) != -1;
                });
            },
            statusIconClass:function(status){
                let statusClass = '';
                return statusClass;
            }
        },
        computed:{
            length:function(){
                return this.datalist.length;
            }
        }
    }
</script>

<style lang="scss" scoped>
    .text-overflow__style {
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
    }
    .vue-dropdown-ext {

        .search-module { position: relative;
            .search-text { width: 100%;
                height: 30px;
                padding-right: 2em;
                padding-left:0.5em;
                box-shadow: none;
                border: 1px solid #ccc;
                background: #fff;
                &:focus { border-color: #2198f2;
                }
            }

            .search-icon {
                position: absolute;
                top: 24%;
                right: 0.5em;
                color: #aaa;
            }

        }

        .list-module {
            overflow: auto;
            li { position: relative;
                margin-top: 0.5em;
                padding: 0.5em;
                border: 1px solid #ccc;
                white-space: nowrap;

                &>span { display: inline-block;
                    vertical-align: middle;
                }

            }
        }

        .tip__nodata {
            font-size: 12px;
            margin-top: 1em;
        }

        &.default-theme {
            .list-module li { &:hover { cursor: pointer;
                    border-color: #00a0e9;
                }

                &.active {
                    border-color: #00a0e9;
                    color: #00a0e9;
                }
            }

        }
    }
</style>

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wl_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值