<template> 
 | 
    <view class="uni-searchbar"> 
 | 
        <view :style="{borderRadius:radius+'px',backgroundColor: bgColor}" class="uni-searchbar__box" 
 | 
            @click="searchClick"> 
 | 
            <view class="uni-searchbar__box-icon-search"> 
 | 
                <slot name="searchIcon"> 
 | 
                    <uni-icons color="#c0c4cc" size="18" type="search" /> 
 | 
                </slot> 
 | 
            </view> 
 | 
            <input v-if="show || searchVal" :focus="showSync" :disabled="readonly" :placeholder="placeholderText" :maxlength="maxlength" 
 | 
                class="uni-searchbar__box-search-input" confirm-type="search" type="text" v-model="searchVal" 
 | 
                @confirm="confirm" @blur="blur" @focus="emitFocus" /> 
 | 
            <text v-else class="uni-searchbar__text-placeholder">{{ placeholder }}</text> 
 | 
            <view v-if="show && (clearButton==='always'||clearButton==='auto'&&searchVal!=='') &&!readonly" 
 | 
                class="uni-searchbar__box-icon-clear" @click="clear"> 
 | 
                <slot name="clearIcon"> 
 | 
                    <uni-icons color="#c0c4cc" size="20" type="clear" /> 
 | 
                </slot> 
 | 
            </view> 
 | 
        </view> 
 | 
        <text @click="cancel" class="uni-searchbar__cancel" 
 | 
            v-if="cancelButton ==='always' || show && cancelButton ==='auto'">{{cancelTextI18n}}</text> 
 | 
    </view> 
 | 
</template> 
 | 
  
 | 
<script> 
 | 
    import { 
 | 
        initVueI18n 
 | 
    } from '@dcloudio/uni-i18n' 
 | 
    import messages from './i18n/index.js' 
 | 
    const { 
 | 
        t 
 | 
    } = initVueI18n(messages) 
 | 
  
 | 
    /** 
 | 
     * SearchBar 搜索栏 
 | 
     * @description 搜索栏组件,通常用于搜索商品、文章等 
 | 
     * @tutorial https://ext.dcloud.net.cn/plugin?id=866 
 | 
     * @property {Number} radius 搜索栏圆角 
 | 
     * @property {Number} maxlength 输入最大长度 
 | 
     * @property {String} placeholder 搜索栏Placeholder 
 | 
     * @property {String} clearButton = [always|auto|none] 是否显示清除按钮 
 | 
     *     @value always 一直显示 
 | 
     *     @value auto 输入框不为空时显示 
 | 
     *     @value none 一直不显示 
 | 
     * @property {String} cancelButton = [always|auto|none] 是否显示取消按钮 
 | 
     *     @value always 一直显示 
 | 
     *     @value auto 输入框不为空时显示 
 | 
     *     @value none 一直不显示 
 | 
     * @property {String} cancelText 取消按钮的文字 
 | 
     * @property {String} bgColor 输入框背景颜色 
 | 
     * @property {Boolean} focus 是否自动聚焦 
 | 
     * @property {Boolean} readonly 组件只读,不能有任何操作,只做展示 
 | 
     * @event {Function} confirm uniSearchBar 的输入框 confirm 事件,返回参数为uniSearchBar的value,e={value:Number} 
 | 
     * @event {Function} input uniSearchBar 的 value 改变时触发事件,返回参数为uniSearchBar的value,e=value 
 | 
     * @event {Function} cancel 点击取消按钮时触发事件,返回参数为uniSearchBar的value,e={value:Number} 
 | 
     * @event {Function} clear 点击清除按钮时触发事件,返回参数为uniSearchBar的value,e={value:Number} 
 | 
     * @event {Function} blur input失去焦点时触发事件,返回参数为uniSearchBar的value,e={value:Number} 
 | 
     */ 
 | 
  
 | 
    export default { 
 | 
        name: "UniSearchBar", 
 | 
        emits: ['input', 'update:modelValue', 'clear', 'cancel', 'confirm', 'blur', 'focus'], 
 | 
        props: { 
 | 
            placeholder: { 
 | 
                type: String, 
 | 
                default: "" 
 | 
            }, 
 | 
            radius: { 
 | 
                type: [Number, String], 
 | 
                default: 5 
 | 
            }, 
 | 
            clearButton: { 
 | 
                type: String, 
 | 
                default: "auto" 
 | 
            }, 
 | 
            cancelButton: { 
 | 
                type: String, 
 | 
                default: "auto" 
 | 
            }, 
 | 
            cancelText: { 
 | 
                type: String, 
 | 
                default: '取消' 
 | 
            }, 
 | 
            bgColor: { 
 | 
                type: String, 
 | 
                default: "#F8F8F8" 
 | 
            }, 
 | 
            maxlength: { 
 | 
                type: [Number, String], 
 | 
                default: 100 
 | 
            }, 
 | 
            value: { 
 | 
                type: [Number, String], 
 | 
                default: "" 
 | 
            }, 
 | 
            modelValue: { 
 | 
                type: [Number, String], 
 | 
                default: "" 
 | 
            }, 
 | 
            focus: { 
 | 
                type: Boolean, 
 | 
                default: false 
 | 
            }, 
 | 
            readonly: { 
 | 
                type: Boolean, 
 | 
                default: false 
 | 
            } 
 | 
        }, 
 | 
        data() { 
 | 
            return { 
 | 
                show: false, 
 | 
                showSync: false, 
 | 
                searchVal: '' 
 | 
            } 
 | 
        }, 
 | 
        computed: { 
 | 
            cancelTextI18n() { 
 | 
                return this.cancelText || t("uni-search-bar.cancel") 
 | 
            }, 
 | 
            placeholderText() { 
 | 
                return this.placeholder || t("uni-search-bar.placeholder") 
 | 
            } 
 | 
        }, 
 | 
        watch: { 
 | 
            // #ifndef VUE3 
 | 
            value: { 
 | 
                immediate: true, 
 | 
                handler(newVal) { 
 | 
                    this.searchVal = newVal 
 | 
                    if (newVal) { 
 | 
                        this.show = true 
 | 
                    } 
 | 
                } 
 | 
            }, 
 | 
            // #endif 
 | 
            // #ifdef VUE3 
 | 
            modelValue: { 
 | 
                immediate: true, 
 | 
                handler(newVal) { 
 | 
                    this.searchVal = newVal 
 | 
                    if (newVal) { 
 | 
                        this.show = true 
 | 
                    } 
 | 
                } 
 | 
            }, 
 | 
            // #endif 
 | 
            focus: { 
 | 
                immediate: true, 
 | 
                handler(newVal) { 
 | 
                    if (newVal) { 
 | 
                        if(this.readonly) return 
 | 
                        this.show = true; 
 | 
                        this.$nextTick(() => { 
 | 
                            this.showSync = true 
 | 
                        }) 
 | 
                    } 
 | 
                } 
 | 
            }, 
 | 
            searchVal(newVal, oldVal) { 
 | 
                this.$emit("input", newVal) 
 | 
                // #ifdef VUE3 
 | 
                this.$emit("update:modelValue", newVal) 
 | 
                // #endif 
 | 
            } 
 | 
        }, 
 | 
        methods: { 
 | 
            searchClick() { 
 | 
                if(this.readonly) return 
 | 
                if (this.show) { 
 | 
                    return 
 | 
                } 
 | 
                this.show = true; 
 | 
                this.$nextTick(() => { 
 | 
                    this.showSync = true 
 | 
                }) 
 | 
            }, 
 | 
            clear() { 
 | 
                this.$emit("clear", { 
 | 
                    value: this.searchVal 
 | 
                }) 
 | 
                this.searchVal = "" 
 | 
            }, 
 | 
            cancel() { 
 | 
                if(this.readonly) return 
 | 
                this.$emit("cancel", { 
 | 
                    value: this.searchVal 
 | 
                }); 
 | 
                this.searchVal = "" 
 | 
                this.show = false 
 | 
                this.showSync = false 
 | 
                // #ifndef APP-PLUS 
 | 
                uni.hideKeyboard() 
 | 
                // #endif 
 | 
                // #ifdef APP-PLUS 
 | 
                plus.key.hideSoftKeybord() 
 | 
                // #endif 
 | 
            }, 
 | 
            confirm() { 
 | 
                // #ifndef APP-PLUS 
 | 
                uni.hideKeyboard(); 
 | 
                // #endif 
 | 
                // #ifdef APP-PLUS 
 | 
                plus.key.hideSoftKeybord() 
 | 
                // #endif 
 | 
                this.$emit("confirm", { 
 | 
                    value: this.searchVal 
 | 
                }) 
 | 
            }, 
 | 
            blur() { 
 | 
                // #ifndef APP-PLUS 
 | 
                uni.hideKeyboard(); 
 | 
                // #endif 
 | 
                // #ifdef APP-PLUS 
 | 
                plus.key.hideSoftKeybord() 
 | 
                // #endif 
 | 
                this.$emit("blur", { 
 | 
                    value: this.searchVal 
 | 
                }) 
 | 
            }, 
 | 
            emitFocus(e) { 
 | 
                this.$emit("focus", e.detail) 
 | 
            } 
 | 
        } 
 | 
    }; 
 | 
</script> 
 | 
  
 | 
<style lang="scss"> 
 | 
    $uni-searchbar-height: 36px; 
 | 
  
 | 
    .uni-searchbar { 
 | 
        /* #ifndef APP-NVUE */ 
 | 
        display: flex; 
 | 
        /* #endif */ 
 | 
        flex-direction: row; 
 | 
        position: relative; 
 | 
        padding: 10px; 
 | 
        // background-color: #fff; 
 | 
    } 
 | 
  
 | 
    .uni-searchbar__box { 
 | 
        /* #ifndef APP-NVUE */ 
 | 
        display: flex; 
 | 
        box-sizing: border-box; 
 | 
        /* #endif */ 
 | 
        overflow: hidden; 
 | 
        position: relative; 
 | 
        flex: 1; 
 | 
        justify-content: center; 
 | 
        flex-direction: row; 
 | 
        align-items: center; 
 | 
        height: $uni-searchbar-height; 
 | 
        padding: 5px 8px 5px 0px; 
 | 
    } 
 | 
  
 | 
    .uni-searchbar__box-icon-search { 
 | 
        /* #ifndef APP-NVUE */ 
 | 
        display: flex; 
 | 
        /* #endif */ 
 | 
        flex-direction: row; 
 | 
        // width: 32px; 
 | 
        padding: 0 8px; 
 | 
        justify-content: center; 
 | 
        align-items: center; 
 | 
        color: #B3B3B3; 
 | 
    } 
 | 
  
 | 
    .uni-searchbar__box-search-input { 
 | 
        flex: 1; 
 | 
        font-size: 14px; 
 | 
        color: #333; 
 | 
    } 
 | 
  
 | 
    .uni-searchbar__box-icon-clear { 
 | 
        align-items: center; 
 | 
        line-height: 24px; 
 | 
        padding-left: 8px; 
 | 
        /* #ifdef H5 */ 
 | 
        cursor: pointer; 
 | 
        /* #endif */ 
 | 
    } 
 | 
  
 | 
    .uni-searchbar__text-placeholder { 
 | 
        font-size: 14px; 
 | 
        color: #B3B3B3; 
 | 
        margin-left: 5px; 
 | 
    } 
 | 
  
 | 
    .uni-searchbar__cancel { 
 | 
        padding-left: 10px; 
 | 
        line-height: $uni-searchbar-height; 
 | 
        font-size: 14px; 
 | 
        color: #333333; 
 | 
        /* #ifdef H5 */ 
 | 
        cursor: pointer; 
 | 
        /* #endif */ 
 | 
    } 
 | 
</style> 
 |