效果:
1.单后缀
2.多后缀
版本:
"vue": "^3.2.47",
"element-plus": "^2.3.6",
需求:
样式中类似 height: 100px;有很多这种带单位样式,那么需要做一个填值,然后选择后缀的element 组件。
实际就是一个原生字段,对应多个修改字段。
问题说明:
使用props,子组件使用v-model绑定后,可以传值给子组件,但是子组件不能修改。
使用attrs,可以传值给子组件,可以修改但是父组件的源数据不会一起变化且源数据变化,它也不会变化。
如果子组件需要影响源数据,需要使用emits。
解决方式:
1.父子组件都绑定同一个源数据,比如pinia。(这种不能叫组件且耦合)
2.prop接收源数据,attrs接收其他信息,然后使用emits来更改源数据。
例如:element 后缀组件
API:
属性名称 | 作用 | 例子 |
data | 源数据 | v-model:data="inputS" |
suffix | 后缀。string | Array | 例如:"suffix",["suffix1","suffix2"],[["suffixLabel","suffix"],["suffixLabel","suffix2"]] |
inputClick | 输入时就同步数据给源数据,否则就是输入框change同步数据 | :valueAttrs="valueAttrs" const valueAttrs = { |
valueAttrs | 值输入框的属性 | |
suffixAttrs | 后缀的属性 | 同valueAttrs |
使用:
<template>
<div>
<InputSuffix2 v-model:data="inputS" :suffix="['px', '%']"/>
</div>
</template>
<script setup>
import InputSuffix2 from "@component/element/input_suffix2.vue";
</script>
组件代码:
<template>
<div class="custom-com-input-suffix" v-bind="attrs.divAttrs">
<template v-if="attrs.inputClick !== undefined">
<el-input @input="valueChange" v-model="input" style="width: 65%;" v-bind="attrs.valueAttrs"/>
<template v-if="typeof attrs.suffix === 'string'">
<el-input @input="suffixChange" v-model="suffix" type="text" style="width: 35%;"
v-bind="attrs.suffixAttrs"/>
</template>
</template>
<template v-else>
<el-input @change="valueChange" v-model="input" style="width: 65%;" v-bind="attrs.valueAttrs"/>
<template v-if="typeof attrs.suffix === 'string'">
<el-input @change="suffixChange" v-model="suffix" type="text" style="width: 35%;"
v-bind="attrs.suffixAttrs"/>
</template>
</template>
<template v-if="Array.isArray(attrs.suffix)">
<el-select @change="suffixChange" v-model="suffix" style="width: 35%;" v-bind="attrs.suffixAttrs"
placeholder=" ">
<template v-for="obj in attrs.suffix">
<template v-if="typeof obj === 'string'">
<el-option :label="obj" :value="obj"/>
</template>
<template v-else>
<template v-if="Array.isArray(obj)">
<el-option :label="obj[0]" :value="obj[1]"/>
</template>
<template v-else>
<el-option :label="obj.label" :value="obj.value"/>
</template>
</template>
</template>
</el-select>
</template>
</div>
</template>
<script setup>
import {ref, useAttrs, watch} from "vue";
const attrs = useAttrs()
const suffix = ref('')
const input = ref('')
const props = defineProps({
data: String
})
watch(props, (val, preVal) => {
setValueAndSuffix(props.data)
})
const setValueAndSuffix = (val) => {
const exceptionStr = '后缀目前只支持字符串和数组,例如:"suffix",["suffix1","suffix2"],[["suffixLabel","suffix"],["suffixLabel","suffix2"]]'
if (typeof attrs.suffix === 'string') {
if (val.indexOf(attrs.suffix) > -1) {
input.value = val.split(suffix.value)[0]
suffix.value = attrs.suffix
}
} else if (Array.isArray(attrs.suffix)) {
for (let i = 0; i < attrs.suffix.length; i++) {
if (typeof attrs.suffix[i] === 'string') {
if (val.indexOf(attrs.suffix[i]) > -1) {
input.value = val.split(attrs.suffix[i])[0]
suffix.value = attrs.suffix[i]
break
}
} else if (Array.isArray(attrs.suffix[i])) {
if (val.indexOf(attrs.suffix[i]) > -1) {
input.value = val.split(attrs.suffix[i])[0]
suffix.value = attrs.suffix[i][1]
break
}
} else {
new TypeError(exceptionStr)
}
}
} else {
new TypeError(exceptionStr)
}
}
setValueAndSuffix(props.data)
const emits = defineEmits(['update:data'])
const valueChange = () => {
emits('update:data', input.value + suffix.value)
}
const suffixChange = () => {
emits('update:data', input.value + suffix.value)
}
</script>
<style scoped>
.custom-com-input-suffix {
display: inline-block;
}
</style>
例子:版本v2
支持直接type定制,使用element的后缀方式,前缀也可以类似实现
使用:
<InputSuffix type="number" v-model:data="inputS" :suffix="POSITION" inputClick/>
<template>
<div class="custom-com-input-suffix" v-bind="attrs.divAttrs">
<template v-if="attrs.inputClick !== undefined">
<el-input :type="inputType" @input="valueChange" v-model="input" v-bind="attrs.valueAttrs">
<template #append>
<template v-if="typeof attrs.suffix === 'string'">
<el-input @input="suffixChange" v-model="suffix" type="text"
v-bind="attrs.suffixAttrs"/>
</template>
<template v-if="Array.isArray(attrs.suffix)">
<el-select @change="suffixChange" v-model="suffix"
v-bind="attrs.suffixAttrs"
placeholder=" ">
<template v-for="obj in attrs.suffix">
<template v-if="typeof obj === 'string'">
<el-option :label="obj" :value="obj"/>
</template>
<template v-else>
<template v-if="Array.isArray(obj)">
<el-option :label="obj[0]" :value="obj[1]"/>
</template>
<template v-else>
<el-option :label="obj.label" :value="obj.value"/>
</template>
</template>
</template>
</el-select>
</template>
</template>
</el-input>
</template>
<template v-else>
<el-input :type="inputType" @change="valueChange" v-model="input" v-bind="attrs.valueAttrs">
<template #append>
<template v-if="typeof attrs.suffix === 'string'">
<el-input @change="suffixChange" v-model="suffix" type="text"
v-bind="attrs.suffixAttrs"/>
</template>
<template v-if="Array.isArray(attrs.suffix)">
<el-select @change="suffixChange" v-model="suffix"
v-bind="attrs.suffixAttrs"
placeholder=" ">
<template v-for="obj in attrs.suffix">
<template v-if="typeof obj === 'string'">
<el-option :label="obj" :value="obj"/>
</template>
<template v-else>
<template v-if="Array.isArray(obj)">
<el-option :label="obj[0]" :value="obj[1]"/>
</template>
<template v-else>
<el-option :label="obj.label" :value="obj.value"/>
</template>
</template>
</template>
</el-select>
</template>
</template>
</el-input>
</template>
</div>
</template>
<script setup>
import {ref, useAttrs, watch} from "vue";
const attrs = useAttrs()
const suffix = ref('')
const input = ref('')
const inputType = ref('type')
const props = defineProps({
data: String
})
watch(props, (val, preVal) => {
setValueAndSuffix(props.data)
})
if (attrs.type && attrs.type.length > 0) {
inputType.value = attrs.type
}
const setValueAndSuffix = (val) => {
const exceptionStr = '后缀目前只支持字符串和数组,例如:"suffix",["suffix1","suffix2"],[["suffixLabel","suffix"],["suffixLabel","suffix2"]]'
if (typeof attrs.suffix === 'string') {
if (val.indexOf(attrs.suffix) > -1) {
input.value = val.split(suffix.value)[0]
suffix.value = attrs.suffix
}
} else if (Array.isArray(attrs.suffix)) {
for (let i = 0; i < attrs.suffix.length; i++) {
if (typeof attrs.suffix[i] === 'string') {
if (val.indexOf(attrs.suffix[i]) > -1) {
input.value = val.split(attrs.suffix[i])[0]
suffix.value = attrs.suffix[i]
break
}
} else if (Array.isArray(attrs.suffix[i])) {
if (val.indexOf(attrs.suffix[i]) > -1) {
input.value = val.split(attrs.suffix[i])[0]
suffix.value = attrs.suffix[i][1]
break
}
} else {
new TypeError(exceptionStr)
}
}
} else {
new TypeError(exceptionStr)
}
}
setValueAndSuffix(props.data)
const emits = defineEmits(['update:data'])
const valueChange = () => {
emits('update:data', input.value + suffix.value)
}
const suffixChange = () => {
emits('update:data', input.value + suffix.value)
}
</script>
<style scoped>
.custom-com-input-suffix {
display: inline-block;
}
</style>