uni-app 的 <input> 是原生组件,外部修改 value 不会刷新视图,改 key 强制销毁重建
组件:u-input
html
<template>
<view class="input-wrapper">
<!-- 用 key 强制重新渲染,解决 uni-app input 值不同步的问题 -->
<input class="uni-input" :key="inputKey" :placeholder="placeholder" :value="value" :type="inputType"
:password="showPassword" @input="handleInput" v-bind="$attrs" />
<uni-icons v-if="showClearIcon" type="close" class="uni-icon" :size="iconSize" :color="iconColor"
@click="handleClearValue" />
<uni-icons v-if="isPassWord" class="uni-icon" :size="iconSize" :color="iconColor" @click="changePassword"
:type="showPassword ? 'eye-filled' : 'eye-slash-filled'" />
</view>
</template>
<script>
export default {
name: "u-input",
inheritAttrs: false,
props: {
value: {
type: [String, Number],
default: "",
},
type: {
type: String,
default: "text",
},
placeholder: {
type: String,
default: "请输入",
},
iconSize:{
type:Number,
default:20
},
iconColor:{
type:String,
default:"#808080"
}
},
data() {
return {
showPassword: false,
showClearIcon: false,
inputKey: 0, // 用于强制刷新 input
};
},
computed: {
isPassWord() {
return this.type === "password" || this.type === "safe-password";
},
inputType(){
this.showPassword = this.isPassWord
return this.isPassWord?"":this.type
}
},
watch: {
// 监听 value 变化,保持清除按钮状态同步
value: {
immediate: true,
handler(val) {
this.showClearIcon = val && val.length > 0;
},
},
},
methods: {
handleInput(event) {
const val = event.detail.value;
this.$emit("input", val);
this.showClearIcon = val.length > 0;
},
handleClearValue() {
this.$emit("input", "");
this.showClearIcon = false;
this.inputKey++;
},
changePassword() {
this.showPassword = !this.showPassword;
},
},
};
</script>
<style scoped lang="scss">
.input-wrapper {
display: flex;
flex-direction: row;
align-items: center;
width: 100%;
}
.uni-input {
flex: 1;
width: 100%;
}
.uni-icon{
margin: 0 $uni-spacing-row-sm;
}
</style>
|---------------------------------|-----------------------------------|
| inheritAttrs: false | 阻止 $attrs 自动绑定到组件根元素 <view> 上 |
| v-bind="$attrs" 绑定到 <input> | 未在 props 中声明的属性全部透传给原生 input |
使用组件:
html
<!-- placeholder、maxlength、disabled 等全部透传 -->
<u-input
v-model="form.username"
placeholder="请输入用户名"
maxlength="20"
:disabled="isDisabled"
confirm-type="done"
/>
<u-input
v-model="form.password"
type="password"
placeholder="请输入密码"
maxlength="32"
/>