vue 简单的 diy 搜索框 封装,全局组件化,对象配置

Posted tianxiaxuange

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue 简单的 diy 搜索框 封装,全局组件化,对象配置相关的知识,希望对你有一定的参考价值。

1. 目录结构:

技术图片

2. main.js 全局组件

技术图片

3. KjfSearch.vue 代码:

  • <template>
        <div class="kjf_search_box" :class="kjfSearchConfig.className">
            <label class="kjf_search_search_label clearfix">
                <input autocomplete="off" readonly="readonly" type="text" :placeholder="kjfSearchConfig.placeholder"
                       class="search_input" :ref="kjfSearchConfig.refName" v-model="kjfSearchKeyWord"
                       @blur="kjfClearPreSearchData" @focus="kjfHandleSearchEvent" @keyup="kjfHandleSearchEvent($event)" />
                <a class="search_by_inputs" href="javascript:" @click="kjfHandleSearchEvent(‘notEvent‘)">搜索</a>
            </label>
    
            <div class="search_list" v-show="kjfPreSearchData && kjfPreSearchData.length>0">
                <ul class="search_result">
                    <li v-for="(item, index) in kjfPreSearchData" :key="item.index"
                        :class="active: index === kjfPreSearchItem" @click="kjfChoosePreSearchItem(index, item.kjfShowSearchName)">
                        <span class="ellipsis" :title="item.kjfShowSearchName">
                            item.kjfShowSearchName
                        </span>
                    </li>
                </ul>
            </div>
        </div>
    </template>
    
    <script>
        import getElementsByCss from ‘../utils‘;
    
        export default 
            name: ‘KjfSearch‘,
            props: 
                kjfSearchConfig: 
                    type: Object
                
            ,
            data: function() 
                return 
                    kjfSearchKeyWord: ‘‘,
                    kjfPreSearchData: [],
                    kjfPreSearchItem: -1
                ;
            ,
            computed: 
            ,
            watch: 
                kjfPreSearchData: 
                    deep: true,
                    handler(newArr) 
                        if (newArr && typeof this.kjfSearchConfig.watchCallBack === ‘function‘) 
                            return this.kjfSearchConfig.watchCallBack(newArr);
                         else 
                            return [];
                        
                    
                
            ,
            mounted() 
            ,
            methods: 
                kjfClearPreSearchData() 
                    this.$refs[this.kjfSearchConfig.refName].setAttribute(‘readonly‘, ‘readonly‘);
                    window.setTimeout(() => 
                        this.kjfPreSearchData = [];
                        this.kjfPreSearchItem = -1;
                    , 200);
                ,
                kjfChoosePreSearchItem(index, searchName) 
                    this.kjfSearchKeyWord = searchName;
                    this.kjfPreSearchData = [];
                    this.kjfPreSearchItem = -1;
                ,
                async kjfHandleSearchEvent(e) 
                    this.$refs[this.kjfSearchConfig.refName].removeAttribute(‘readonly‘);
    
                    if (e && (e.key === ‘ArrowUp‘ || e.key === ‘ArrowDown‘)) 
                        this.kjfPreSearchItem = e.key === ‘ArrowUp‘ ? (this.kjfPreSearchItem - 1) : (this.kjfPreSearchItem + 1);
                        if (this.kjfPreSearchItem < 0) 
                            this.kjfPreSearchItem = -1;
                        
                        if (this.kjfPreSearchItem >= this.kjfPreSearchData.length) 
                            this.kjfPreSearchItem = this.kjfPreSearchData.length - 1;
                        
                        console.log(‘.‘ + this.kjfSearchConfig.className + ‘ .search_list .search_result‘);
                        const ele = getElementsByCss(‘.‘ + this.kjfSearchConfig.className + ‘ .search_list .search_result‘)[0];
                        ele && ele.scrollTo(0, this.kjfPreSearchItem * 31);
                        return;
                     // 上、下选择下拉选项
    
                    if (e && (e.key === ‘Enter‘) && (this.kjfPreSearchItem !== -1)) 
                        this.kjfSearchKeyWord = this.kjfPreSearchData[this.kjfPreSearchItem].kjfShowSearchName;
                        this.kjfPreSearchData = [];
                        this.kjfPreSearchItem = -1;
                        this.$refs[this.kjfSearchConfig.refName].focus();
                        return;
                     // 回车选中下拉选项
    
                    if ((e === ‘notEvent‘) || (e && e.key === ‘Enter‘)) 
                        window.setTimeout(async () => 
                            this.kjfSearchConfig.enterCallBack(this.kjfSearchKeyWord);
    
                            this.kjfPreSearchData = [];
                            this.kjfPreSearchItem = -1;
                        , 200);
                        this.$refs[this.kjfSearchConfig.refName].focus();
                        return;
                     // 回车键按下 或者 点击搜索按钮
    
                    window.clearTimeout(this.searchTimer);
                    this.searchTimer = window.setTimeout(async () => 
                        if (this.kjfSearchKeyWord && this.kjfSearchKeyWord.trim()) 
                            if (!this.kjfSearchKeyWord) 
                                this.kjfPreSearchData = [];
                                return;
                            
                            if (typeof this.kjfSearchConfig.getPreSearchData === ‘function‘) 
                                this.kjfPreSearchData = await this.kjfSearchConfig.getPreSearchData(this.kjfSearchKeyWord);
                            
                         else 
                            this.kjfPreSearchData = [];
                            this.kjfPreSearchItem = -1;
                        
                    , 200); // 防抖 搜索
                
            
        ;
    </script>
    
    <style lang="stylus" rel="stylesheet/stylus" scoped>
        @import "../../common/stylus/mixins.styl"
    
        .kjf_search_box
            width 100%
            height 100%
            input
                height 30px
                text-indent 2px
                border-radius 4px
                outline none
                border 1px solid #DCDFE6
            .kjf_search_search_label
                display block
                width 100%
                height 100%
                >input
                    float left
                    display block
                    width 240px
                >a
                    float right
                    display block
                    width 50px
                    height 100%
                    border-radius 4px
                    box-sizing border-box
                    padding 0 10px
                    background-color $themeColor
                    color #fff
            .search_list
                color $fontColor
                width 238px
                max-height 300px
                overflow hidden
                .search_result
                    position absolute
                    top 32px
                    left 2px
                    z-index 100
                    width 238px
                    max-height 300px
                    overflow-x hidden
                    overflow-y auto
                    border-radius 0 0 10px 10px
                    background-color #eee
                    padding 0 0 10px 10px
                    box-sizing border-box
                    >li
                        width 180px
                        margin-top 10px
                        color $fontColor
                        white-space normal
                        word-break break-all
                        word-wrap break-word
                        &.active,
                        &:hover
                            cursor pointer
                            >span
                                color #fff
                                background-color $themeColor
                        >span
                            color $fontColor
    
    </style>

4. 使用实例 主要代码: 

  • <template>
        <div id="company_pay_record">
            <ul class="company_pay_record_nav clearfix">
                <li class="right_company_pay_record_search_li clearfix">
                    <KjfSearch :kjfSearchConfig="companyPayRecordSearchConfig"></KjfSearch>
                </li>
            </ul>
        </div>
    </template>
    
    <script>
        import mapState from ‘vuex‘;
        import requestMyLabs from ‘../../../../axios;
    
        export default 
            name: ‘CompanyPayRecord‘,
            props: 
                isPC: Boolean
            ,
            data () 
                return 
                    companyPayRecordSearchConfig: 
                        className: ‘company_pay_record_search‘,
                        refName: ‘companyPayRecordSearch‘,
                        placeholder: ‘请输入操作人/编号‘,
                        kjfShowSearchName: ‘expName‘,
                        enterCallBack: async (searchKeyWord) => 
                            searchKeyWord = searchKeyWord && searchKeyWord.trim();
                            await this.$store.dispatch(‘changeLabsCurPageNo‘, 1);
                            await this.$store.dispatch(‘changeLabsKeyWord‘, searchKeyWord);
                            let response = ‘ - 223 -‘;
                            try 
                                response = await this.$store.dispatch(‘getMyLabs‘, this.myLabsData); // 获取 myLabsData
                             catch (e) 
                                this.myConsole(e);
                                this.myConsole(‘response 228: ‘);
                                this.myConsole(response);
                            
                        ,
                        getPreSearchData: async (searchKeyWord) => 
                            await this.$store.dispatch(‘changeLabsKeyWord‘, searchKeyWord);
                            const response = await requestMyLabs(this.myLabsData);
                            if (response.status === 200) 
                                return response.data.data.content;
                            
                        ,
                        watchCallBack: (newArr) => 
                            let i = 0;
                            for (; i < newArr.length; i++) 
                                newArr[i].kjfShowSearchName = newArr[i].experiment.experimentName;
                            
                            return newArr;
                        
                    
                ;
            ,
            computed: 
                ...mapState(
                    myLabsData: state => state.myLabs.myLabsData
                )
            ,
            async mounted () 
                this.initCompanyPayRecord();
            ,
            methods: 
                async initCompanyPayRecord() 
                
            
        ;
    </script>
    
    <style lang="stylus" rel="stylesheet/stylus" scoped>
        @import "../../../../common/stylus/mixins.styl"
    
        #company_pay_record
            width 100%
            margin 0 auto
            .company_pay_record_nav
                width 100%
                padding-top 20px
                padding-bottom 20px
                box-sizing border-box
                >li
                    float left
                    width 200px
                    height 30px
                    margin-right 14px
                    line-height 30px
                    &:last-child
                        margin-right 0
                .right_company_pay_record_search_li
                    float right
                    position relative
                    width 300px
                    height 30px
    
            .my_labs_pagination
                margin-top 15px
        #company_pay_record_info.is_mobile
            width 100%
            px(‘font-size‘, 14)    // 用于 mobile 设计图单位
    </style>

5. 效果图:

技术图片

以上是关于vue 简单的 diy 搜索框 封装,全局组件化,对象配置的主要内容,如果未能解决你的问题,请参考以下文章

初学福音,手把手带你vue封装弹框组件并全局注册使用~

初学福音,手把手带你vue封装弹框组件并全局注册使用~

vue封装一个简单的div框选时间的组件

vue组件封装- loading框

Vue插槽的使用

vue3:全局搜索解决方案