核心原理
当 input
输入,存在一个 view 元素容纳输入内容,此时获取 view 元素的宽,将其设置为 input
的宽
特殊情况:回显的时候当前元素可能不存在,此时需要借助一个永远显示的元素进行宽度计算(InputWidthHelper.vue
)
adaption-input.vue
js
<template>
<view class="adaption-input-wrapper">
<view class="adaption-input">
<input
type="text"
:placeholder-style="placeholderStyle"
:placeholder="placeholder"
:style="{ width: inputWidth }"
@input="changeInputFn"
/>
</view>
<view :id="randomID" class="a--input">{{ modelValue || '请输入' }}</view>
</view>
</template>
<script>
export default {
inheritAttrs: false,
props: {
modelValue: {
type: [String, Number],
default: '',
},
placeholder: {
type: String,
default: '请输入',
},
placeholderStyle: {
type: String,
default: 'color: #9ea5bb',
},
},
data() {
return {
randomID: 'adaption_' + new Date().getTime(),
inputWidth: '',
}
},
watch: {
modelValue: {
handler() {
this.$nextTick(() => {
this.changeInputFn()
})
},
immediate: true,
},
},
options: {
virtualHost: true,
},
computed: {
inputVal: {
set(val) {
this.$emit('update:modelValue', val)
this.$emit('change', val)
},
get() {
return this.modelValue
},
},
},
methods: {
changeInputFn() {
setTimeout(() => {
const query = uni.createSelectorQuery().in(this)
query
.select(`#${this.randomID}`)
.boundingClientRect((rect) => {
if (rect) {
// 处于不可见状态,需要借助一个永远显示的 dom 进行处理
if (rect.width == 0) {
uni.$emit('getInputWidth', this.inputVal)
} else {
let rectWidth = rect.width
if (rectWidth > 150) {
rectWidth = 150
}
if (this.inputVal) {
this.inputWidth = rectWidth + 30 + 'px'
} else {
this.inputWidth = rectWidth + 5 + 'px'
}
}
}
})
.exec()
}, 0)
},
},
mounted() {
uni.$on('returnInputWidth', (width) => {
this.inputWidth = width
})
},
}
</script>
<style lang="scss" scoped>
.adaption-input {
font-size: 28rpx;
}
.a--input {
font: inherit;
opacity: 0;
position: fixed;
top: 0;
z-index: -1;
}
</style>
InputWidthHelper.vue
js
<template>
<view :id="randomID" class="a--input">{{ inputValue || '请输入' }}</view>
</template>
<script>
export default {
inheritAttrs: false,
data() {
return {
randomID: 'adaption_' + new Date().getTime(),
inputValue: '',
}
},
mounted() {
uni.$on('getInputWidth', (text) => {
this.inputValue = text
this.$nextTick(() => {
const query = uni.createSelectorQuery().in(this)
query
.select(`#${this.randomID}`)
.boundingClientRect((rect) => {
if (rect) {
let rectWidth = rect.width
if (rectWidth > 150) {
rectWidth = 150
}
if (text) {
uni.$emit('returnInputWidth', rectWidth + 30 + 'px')
} else {
uni.$emit('returnInputWidth', rectWidth + 5 + 'px')
}
}
})
.exec()
})
})
},
}
</script>
<style lang="scss" scoped>
.adaption-input {
font-size: 28rpx;
}
.a--input {
font: inherit;
opacity: 0;
position: fixed;
top: 0;
z-index: -1;
}
</style>