From f26f29d84e0a68831a6af14dab3eec5500496d2e Mon Sep 17 00:00:00 2001 From: spring <2396852758@qq.com> Date: 星期三, 28 五月 2025 16:48:52 +0800 Subject: [PATCH] 初始化项目 --- uview-ui/components/u-input/u-input.vue | 387 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 387 insertions(+), 0 deletions(-) diff --git a/uview-ui/components/u-input/u-input.vue b/uview-ui/components/u-input/u-input.vue new file mode 100644 index 0000000..f2aea72 --- /dev/null +++ b/uview-ui/components/u-input/u-input.vue @@ -0,0 +1,387 @@ +<template> + <view + class="u-input" + :class="{ + 'u-input--border': border, + 'u-input--error': validateState + }" + :style="{ + padding: `0 ${border ? 20 : 0}rpx`, + borderColor: borderColor, + textAlign: inputAlign + }" + @tap.stop="inputClick" + > + <textarea + v-if="type == 'textarea'" + class="u-input__input u-input__textarea" + :style="[getStyle]" + :value="defaultValue" + :placeholder="placeholder" + :placeholderStyle="placeholderStyle" + :disabled="disabled" + :maxlength="inputMaxlength" + :fixed="fixed" + :focus="focus" + :autoHeight="autoHeight" + :selection-end="uSelectionEnd" + :selection-start="uSelectionStart" + :cursor-spacing="getCursorSpacing" + :show-confirm-bar="showConfirmbar" + @input="handleInput" + @blur="handleBlur" + @focus="onFocus" + @confirm="onConfirm" + /> + <input + v-else + class="u-input__input" + :type="type == 'password' ? 'text' : type" + :style="[getStyle]" + :value="defaultValue" + :password="type == 'password' && !showPassword" + :placeholder="placeholder" + :placeholderStyle="placeholderStyle" + :disabled="disabled || type === 'select'" + :maxlength="inputMaxlength" + :focus="focus" + :confirmType="confirmType" + :cursor-spacing="getCursorSpacing" + :selection-end="uSelectionEnd" + :selection-start="uSelectionStart" + :show-confirm-bar="showConfirmbar" + @focus="onFocus" + @blur="handleBlur" + @input="handleInput" + @confirm="onConfirm" + /> + <view class="u-input__right-icon u-flex"> + <view class="u-input__right-icon__clear u-input__right-icon__item" @tap="onClear" v-if="clearable && value != '' && focused"> + <u-icon size="32" name="close-circle-fill" color="#c0c4cc"/> + </view> + <view class="u-input__right-icon__clear u-input__right-icon__item" v-if="passwordIcon && type == 'password'"> + <u-icon size="32" :name="!showPassword ? 'eye' : 'eye-fill'" color="#c0c4cc" @click="showPassword = !showPassword"/> + </view> + <view class="u-input__right-icon--select u-input__right-icon__item" v-if="type == 'select'" :class="{ + 'u-input__right-icon--select--reverse': selectOpen + }"> + <u-icon name="arrow-down-fill" size="26" color="#c0c4cc"></u-icon> + </view> + </view> + </view> +</template> + +<script> +import Emitter from '../../libs/util/emitter.js'; + +/** + * input 杈撳叆妗� + * @description 姝ょ粍浠朵负涓�涓緭鍏ユ锛岄粯璁ゆ病鏈夎竟妗嗗拰鏍峰紡锛屾槸涓撻棬涓洪厤鍚堣〃鍗曠粍浠秛-form鑰岃璁$殑锛屽埄鐢ㄥ畠鍙互蹇�熷疄鐜拌〃鍗曢獙璇侊紝杈撳叆鍐呭锛屼笅鎷夐�夋嫨绛夊姛鑳姐�� + * @tutorial http://uviewui.com/components/input.html + * @property {String} type 妯″紡閫夋嫨锛岃瀹樼綉璇存槑 + * @property {Boolean} clearable 鏄惁鏄剧ず鍙充晶鐨勬竻闄ゅ浘鏍�(榛樿true) + * @property {} v-model 鐢ㄤ簬鍙屽悜缁戝畾杈撳叆妗嗙殑鍊� + * @property {String} input-align 杈撳叆妗嗘枃瀛楃殑瀵归綈鏂瑰紡(榛樿left) + * @property {String} placeholder placeholder鏄剧ず鍊�(榛樿 '璇疯緭鍏ュ唴瀹�') + * @property {Boolean} disabled 鏄惁绂佺敤杈撳叆妗�(榛樿false) + * @property {String Number} maxlength 杈撳叆妗嗙殑鏈�澶у彲杈撳叆闀垮害(榛樿140) + * @property {String Number} selection-start 鍏夋爣璧峰浣嶇疆锛岃嚜鍔ㄨ仛鐒︽椂鏈夋晥锛岄渶涓巗election-end鎼厤浣跨敤锛堥粯璁�-1锛� + * @property {String Number} maxlength 鍏夋爣缁撴潫浣嶇疆锛岃嚜鍔ㄨ仛鐒︽椂鏈夋晥锛岄渶涓巗election-start鎼厤浣跨敤锛堥粯璁�-1锛� + * @property {String Number} cursor-spacing 鎸囧畾鍏夋爣涓庨敭鐩樼殑璺濈锛屽崟浣峱x(榛樿0) + * @property {String} placeholderStyle placeholder鐨勬牱寮忥紝瀛楃涓插舰寮忥紝濡�"color: red;"(榛樿 "color: #c0c4cc;") + * @property {String} confirm-type 璁剧疆閿洏鍙充笅瑙掓寜閽殑鏂囧瓧锛屼粎鍦╰ype涓簍ext鏃剁敓鏁�(榛樿done) + * @property {Object} custom-style 鑷畾涔夎緭鍏ユ鐨勬牱寮忥紝瀵硅薄褰㈠紡 + * @property {Boolean} focus 鏄惁鑷姩鑾峰緱鐒︾偣(榛樿false) + * @property {Boolean} fixed 濡傛灉type涓簍extarea锛屼笖鍦ㄤ竴涓�"position:fixed"鐨勫尯鍩燂紝闇�瑕佹寚鏄庝负true(榛樿false) + * @property {Boolean} password-icon type涓簆assword鏃讹紝鏄惁鏄剧ず鍙充晶鐨勫瘑鐮佹煡鐪嬪浘鏍�(榛樿true) + * @property {Boolean} border 鏄惁鏄剧ず杈规(榛樿false) + * @property {String} border-color 杈撳叆妗嗙殑杈规棰滆壊(榛樿#dcdfe6) + * @property {Boolean} auto-height 鏄惁鑷姩澧為珮杈撳叆鍖哄煙锛宼ype涓簍extarea鏃舵湁鏁�(榛樿true) + * @property {String Number} height 楂樺害锛屽崟浣峳px(text绫诲瀷鏃朵负70锛宼extarea鏃朵负100) + * @example <u-input v-model="value" :type="type" :border="border" /> + */ +export default { + name: 'u-input', + mixins: [Emitter], + props: { + value: { + type: [String, Number], + default: '' + }, + // 杈撳叆妗嗙殑绫诲瀷锛宼extarea锛宼ext锛宯umber + type: { + type: String, + default: 'text' + }, + inputAlign: { + type: String, + default: 'left' + }, + placeholder: { + type: String, + default: '璇疯緭鍏ュ唴瀹�' + }, + disabled: { + type: Boolean, + default: false + }, + maxlength: { + type: [Number, String], + default: 140 + }, + placeholderStyle: { + type: String, + default: 'color: #c0c4cc;' + }, + confirmType: { + type: String, + default: 'done' + }, + // 杈撳叆妗嗙殑鑷畾涔夋牱寮� + customStyle: { + type: Object, + default() { + return {}; + } + }, + // 濡傛灉 textarea 鏄湪涓�涓� position:fixed 鐨勫尯鍩燂紝闇�瑕佹樉绀烘寚瀹氬睘鎬� fixed 涓� true + fixed: { + type: Boolean, + default: false + }, + // 鏄惁鑷姩鑾峰緱鐒︾偣 + focus: { + type: Boolean, + default: false + }, + // 瀵嗙爜绫诲瀷鏃讹紝鏄惁鏄剧ず鍙充晶鐨勫瘑鐮佸浘鏍� + passwordIcon: { + type: Boolean, + default: true + }, + // input|textarea鏄惁鏄剧ず杈规 + border: { + type: Boolean, + default: false + }, + // 杈撳叆妗嗙殑杈规棰滆壊 + borderColor: { + type: String, + default: '#dcdfe6' + }, + autoHeight: { + type: Boolean, + default: true + }, + // type=select鏃讹紝鏃嬭浆鍙充晶鐨勫浘鏍囷紝鏍囪瘑褰撳墠澶勪簬鎵撳紑杩樻槸鍏抽棴select鐨勭姸鎬� + // open-鎵撳紑锛宑lose-鍏抽棴 + selectOpen: { + type: Boolean, + default: false + }, + // 楂樺害锛屽崟浣峳px + height: { + type: [Number, String], + default: '' + }, + // 鏄惁鍙竻绌� + clearable: { + type: Boolean, + default: true + }, + // 鎸囧畾鍏夋爣涓庨敭鐩樼殑璺濈锛屽崟浣� px + cursorSpacing: { + type: [Number, String], + default: 0 + }, + // 鍏夋爣璧峰浣嶇疆锛岃嚜鍔ㄨ仛鐒︽椂鏈夋晥锛岄渶涓巗election-end鎼厤浣跨敤 + selectionStart: { + type: [Number, String], + default: -1 + }, + // 鍏夋爣缁撴潫浣嶇疆锛岃嚜鍔ㄨ仛鐒︽椂鏈夋晥锛岄渶涓巗election-start鎼厤浣跨敤 + selectionEnd: { + type: [Number, String], + default: -1 + }, + // 鏄惁鑷姩鍘婚櫎涓ょ鐨勭┖鏍� + trim: { + type: Boolean, + default: true + }, + // 鏄惁鏄剧ず閿洏涓婃柟甯︽湁鈥濆畬鎴愨�滄寜閽偅涓�鏍� + showConfirmbar:{ + type:Boolean, + default:true + } + }, + data() { + return { + defaultValue: this.value, + inputHeight: 70, // input鐨勯珮搴� + textareaHeight: 100, // textarea鐨勯珮搴� + validateState: false, // 褰撳墠input鐨勯獙璇佺姸鎬侊紝鐢ㄤ簬閿欒鏃讹紝杈规鏄惁鏀逛负绾㈣壊 + focused: false, // 褰撳墠鏄惁澶勪簬鑾峰緱鐒︾偣鐨勭姸鎬� + showPassword: false, // 鏄惁棰勮瀵嗙爜 + lastValue: '', // 鐢ㄤ簬澶存潯灏忕▼搴忥紝鍒ゆ柇@input涓紝鍓嶅悗鐨勫�兼槸鍚﹀彂鐢熶簡鍙樺寲锛屽洜涓哄ご鏉′腑鏂囦笅锛屾寜涓嬮敭娌℃湁杈撳叆鍐呭锛屼篃浼氳Е鍙慇input鏃堕棿 + }; + }, + watch: { + value(nVal, oVal) { + this.defaultValue = nVal; + // 褰撳�煎彂鐢熷彉鍖栵紝涓斾负select绫诲瀷鏃�(姝ゆ椂input琚缃负disabled锛屼笉浼氳Е鍙慇input浜嬩欢)锛屾ā鎷熻Е鍙慇input浜嬩欢 + if(nVal != oVal && this.type == 'select') this.handleInput({ + detail: { + value: nVal + } + }) + }, + }, + computed: { + // 鍥犱负uniapp鐨刬nput缁勪欢鐨刴axlength缁勪欢蹇呴』瑕佹暟鍊硷紝杩欓噷杞负鏁板�硷紝缁欑敤鎴峰彲浠ヤ紶鍏ュ瓧绗︿覆鏁板�� + inputMaxlength() { + return Number(this.maxlength); + }, + getStyle() { + let style = {}; + // 濡傛灉娌℃湁鑷畾涔夐珮搴︼紝灏辨牴鎹畉ype涓篿nput杩樻槸textare鏉ュ垎閰嶄竴涓粯璁ょ殑楂樺害 + style.minHeight = this.height ? this.height + 'rpx' : this.type == 'textarea' ? + this.textareaHeight + 'rpx' : this.inputHeight + 'rpx'; + style = Object.assign(style, this.customStyle); + return style; + }, + // + getCursorSpacing() { + return Number(this.cursorSpacing); + }, + // 鍏夋爣璧峰浣嶇疆 + uSelectionStart() { + return String(this.selectionStart); + }, + // 鍏夋爣缁撴潫浣嶇疆 + uSelectionEnd() { + return String(this.selectionEnd); + } + }, + created() { + // 鐩戝惉u-form-item鍙戝嚭鐨勯敊璇簨浠讹紝灏嗚緭鍏ユ杈规鍙樼孩鑹� + this.$on('on-form-item-error', this.onFormItemError); + }, + methods: { + /** + * change 浜嬩欢 + * @param event + */ + handleInput(event) { + let value = event.detail.value; + // 鍒ゆ柇鏄惁鍘婚櫎绌烘牸 + if(this.trim) value = this.$u.trim(value); + // vue 鍘熺敓鐨勬柟娉� return 鍑哄幓 + this.$emit('input', value); + // 褰撳墠model 璧嬪�� + this.defaultValue = value; + // 杩囦竴涓敓鍛藉懆鏈熷啀鍙戦�佷簨浠剁粰u-form-item锛屽惁鍒檛his.$emit('input')鏇存柊浜嗙埗缁勪欢鐨勫�硷紝浣嗘槸寰俊灏忕▼搴忎笂 + // 灏氭湭鏇存柊鍒皍-form-item锛屽鑷磋幏鍙栫殑鍊间负绌猴紝浠庤�屾牎楠屾贩璁� + // 杩欓噷涓嶈兘寤舵椂鏃堕棿澶煭锛屾垨鑰呬娇鐢╰his.$nextTick锛屽惁鍒欏湪澶存潯涓婏紝浼氶�犳垚娣蜂贡 + setTimeout(() => { + // 澶存潯灏忕▼搴忕敱浜庤嚜韬玝ug锛屽鑷翠腑鏂囦笅锛屾瘡鎸変笅涓�涓敭(灏氭湭瀹屾垚杈撳叆)锛岄兘浼氳Е鍙戜竴娆input锛屽鑷撮敊璇紝杩欓噷杩涜鍒ゆ柇澶勭悊 + // #ifdef MP-TOUTIAO + if(this.$u.trim(value) == this.lastValue) return ; + this.lastValue = value; + // #endif + // 灏嗗綋鍓嶇殑鍊煎彂閫佸埌 u-form-item 杩涜鏍¢獙 + this.dispatch('u-form-item', 'on-form-change', value); + }, 40) + }, + /** + * blur 浜嬩欢 + * @param event + */ + handleBlur(event) { + // 鏈�寮�濮嬩娇鐢ㄧ殑鏄洃鍚浘鏍嘆touchstart浜嬩欢锛岃嚜浠巋x2.8.4鍚庯紝姝ゆ柟娉曞湪寰俊灏忕▼搴忓嚭閿� + // 杩欓噷鏀逛负鐩戝惉鐐瑰嚮浜嬩欢锛屾墜鐐瑰嚮娓呴櫎鍥炬爣鏃讹紝鍚屾椂涔熷彂鐢熶簡@blur浜嬩欢锛屽鑷村浘鏍囨秷澶辫�屾棤娉曠偣鍑伙紝杩欓噷鍋氫竴涓欢鏃� + setTimeout(() => { + this.focused = false; + }, 100) + // vue 鍘熺敓鐨勬柟娉� return 鍑哄幓 + this.$emit('blur', event.detail.value); + setTimeout(() => { + // 澶存潯灏忕▼搴忕敱浜庤嚜韬玝ug锛屽鑷翠腑鏂囦笅锛屾瘡鎸変笅涓�涓敭(灏氭湭瀹屾垚杈撳叆)锛岄兘浼氳Е鍙戜竴娆input锛屽鑷撮敊璇紝杩欓噷杩涜鍒ゆ柇澶勭悊 + // #ifdef MP-TOUTIAO + if(this.$u.trim(value) == this.lastValue) return ; + this.lastValue = value; + // #endif + // 灏嗗綋鍓嶇殑鍊煎彂閫佸埌 u-form-item 杩涜鏍¢獙 + this.dispatch('u-form-item', 'on-form-blur', event.detail.value); + }, 40) + }, + onFormItemError(status) { + this.validateState = status; + }, + onFocus(event) { + this.focused = true; + this.$emit('focus'); + }, + onConfirm(e) { + this.$emit('confirm', e.detail.value); + }, + onClear(event) { + this.$emit('input', ''); + }, + inputClick() { + this.$emit('click'); + } + } +}; +</script> + +<style lang="scss" scoped> +@import "../../libs/css/style.components.scss"; + +.u-input { + position: relative; + flex: 1; + @include vue-flex; + + &__input { + //height: $u-form-item-height; + font-size: 28rpx; + color: $u-main-color; + flex: 1; + } + + &__textarea { + width: auto; + font-size: 28rpx; + color: $u-main-color; + padding: 10rpx 0; + line-height: normal; + flex: 1; + } + + &--border { + border-radius: 6rpx; + border-radius: 4px; + border: 1px solid $u-form-item-border-color; + } + + &--error { + border-color: $u-type-error!important; + } + + &__right-icon { + + &__item { + margin-left: 10rpx; + } + + &--select { + transition: transform .4s; + + &--reverse { + transform: rotate(-180deg); + } + } + } +} +</style> -- Gitblit v1.9.3