vue2过渡vue3,挺多的写法都不一样,所以记录一下用vue3 setup语法糖二次封装vant组件并使用,其实写多几个基本上就将vue经常所用到的watch,prop,emit,生命周期,定义响应式变量等,这些到时候另外再细写,这里主要给到代码方便使用。
vantUI框架不像elementUIPC端框架的select可以直接使用,大多数都需要结合二次封装,下面想实现类似下图的单选组件
子组件 singlePicker.vue
下面的代码其实不难,这里主要说一下有一个prop属性是customFieldName,这个主要考虑到传入的option数据的不同来处理了的,例如现在默认是text和value,但如果传入的数据内容不是按照text,value,就可以用customFieldName来改变。举个例子:如果传入的columns是[{name:'是',code:'1'},{name:'否',code:'0'},{name:'未知',code:'2'},] ,那么使用该组件的时候就传入 :customFieldName="{text:'name',value:'code'}"即可。下面是子组件的代码:
<template>
<div>
<van-field v-model="text" v-bind="$attrs" readonly is-link :name="name" :label="label" @click="show = !show"></van-field>
<van-popup :show="show" round position="bottom">
<van-picker
:columns="columns"
:columns-field-names="customFieldName"
show-toolbar
:value-key="valueKey"
:title="$attrs.label"
@cancel="show = !show"
@confirm="onConfirm"
></van-picker>
</van-popup>
</div>
</template>
<script setup>
import { ref,toRefs, defineProps,onMounted,watch,reactive,nextTick,defineEmits } from 'vue';
const emit = defineEmits(['update:modelValue'])
const props = defineProps({
//子组件接收父组件传递过来的值
columns: {
type:Array // option中的数据
},
label:String, // 标题
modelValue:String, // 绑定的值
customFieldName:{ // option中数据中对应的name和code的字段名
type:Object,
default:{
text: 'text',
value: 'value',
}
},
name:String,
})
//使用父组件传递过来的值
const {info} = toRefs(props)
onMounted(()=>{
nextTick(()=>{
reShow();
})
})
let show = ref(false)
let text = ref('')
let code = ref('')
const onConfirm = ({ selectedOptions }) => {
// text.value = selectedOptions[0].text;
// code.value = selectedOptions[0].value;
text.value = selectedOptions[0][props.customFieldName.text];
code.value = selectedOptions[0][props.customFieldName.value];
show.value = !show.value;
}
const reShow = () => {
if(props.modelValue) {
props.columns.forEach(res => {
if (res[props.customFieldName.value] == props.modelValue) {
text.value = res[props.customFieldName.text];
}
})
}
}
watch(()=>code.value,(newVal, oldVal) => {
emit('update:modelValue', newVal);
})
watch(()=>props.columns,(newVal,oldVal)=>{
//处理异步数据回显
reShow();
})
watch(()=>props.modelValue,(newVal,oldVal)=>{
//处理异步数据回显
reShow();
})
</script>
使用子组件 index.vue
<single-picker clearable label="地点" name="role" placeholder="请选择地点"
v-model="form.role" v-bind:columns="itemList"
:rules="[{ required: true, message: '请选择地点' }]"/>
<script setup>
import { reactive } from 'vue';
const itemList = reactive([
{ text: '杭州', value: 'Hangzhou' },
{ text: '宁波', value: 'Ningbo' },
{ text: '温州', value: 'Wenzhou' },
{ text: '绍兴', value: 'Shaoxing' },
{ text: '湖州', value: 'Huzhou' },
])
const form = reactive({role: ""})
</script>