uni-app 的<input>是原生组件,外部修改 value 不会刷新视图,改 key 强制销毁重建
组件:u-input
<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 |
使用组件:
<!-- 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" />