编写目的
本文说明基于vue3定义uniapp组件的关键点:
1、一般定义在components文件夹创建组件,组件与页面已经没有明确的语法格式区别,所以可以与页面的语法保持一致 ;
2、组件定义后使用该组件的页面不需要引用组件即可使用;
3、1级选项利用modelValue属性实现双向绑定,2级选项使用回调函数实现数据回传;
组件源码
在components文件夹下新建vol-picker文件夹,文件夹下新建vol-picker.vue,代码如下:
<template>
<up-picker :show="show" :defaultIndex="defaultIndex" ref="uPickerRef" :loading="pickerLoading"
:closeOnClickOverlay="true" :columns="datas" keyName="label" @confirm="confirm"
@change="changeHandler"></up-picker>
<up-input v-model="content.label" border="bottom" :readonly="true" :placement="placement">
<template #suffix>
<up-button @click="show = true" type="default" size="mini">
<up-icon name="arrow-right"></up-icon>
</up-button>
</template>
</up-input>
</template>
<script setup>
import {ref,reactive,onMounted,defineEmits} from 'vue';
const uPickerRef = ref(null);
//选择框是否显示
const show = ref(false);
const pickerLoading = ref(false);
//默认值
const defaultIndex = ref([0]);
//选择到的值
const content = ref({
label: "",
name: ""
});
onMounted(() => {
//设置默认值
if (props.modelValue) {
//2级
if (props.datas.length == 2) {
//查找1级数组索引
let level1Index = props.datas[0].findIndex(f => f.list.some(s => s.id == props.modelValue));
if (level1Index > -1) {
//查找2级数组索引
let level2Index = props.datas[0][level1Index].list.findIndex(f => f.id == props.modelValue);
defaultIndex.value = [level1Index, level2Index];
}
content.value = props.datas[0][level1Index];
//设置二级数组
uPickerRef.value.setColumnValues(1, content.value.list);
}
//1级
else {
let oldVal = props.datas[0].find(f => f.id == props.modelValue);
if (oldVal) {
content.value = oldVal;
let levle1 = props.datas[0].findIndex(f => f.id == props.modelValue);
defaultIndex.value = [levle1]
}
}
}
});
const props = defineProps({
modelValue: {
type: String,
default: '' //
},
datas: {
type: Array,
default: () => {
return [
[]
]
}
},
placement: {
type: String,
default: ''
},
readonly: { //默认是否只读
type: Boolean,
default: false
}
})
const emit = defineEmits(['update', 'updateValue']);
function changeHandler(e) {
const {
columnIndex, //列的索引
value, //是一个数组[]
values, // values为当前变化列的数组内容
index // 选值元素的索引
} = e
//console.log(e, index)
// 当第一列值发生变化时,变化第二列(后一列)对应的选项
if (props.datas.length == 2) {
// 变更第2列对应的选项
uPickerRef.value.setColumnValues(1, value[0].list)
}
};
// 回调参数包含columnIndex、value、values
function confirm(e) {
// console.log(e)
//两级选值
if (props.datas.length == 2) {
content.value = e.value[1];
emit("updateValue", e.value);
}
//只有一级选择
else {
content.value = e.value[0];
emit("update:modelValue", e.value[0].id);
//当只有一级选项时,请根据需要 执行回调函数
//emit("updateValue", e.value);
}
// console.log(content.value)
show.value = false
}
</script>
使用演示
<vol-picker>是组件文件名称。
<template>
<vol-picker v-model="formData.Gender"
:datas="countrys"
@updateValue="fun_updateValue"
placement="选择">
</template>
<script setup>
import {ref,reactive,watch,defineProps,defineEmits,defineExpose,getCurrentInstance} from 'vue';
//示例1:1级选项
const countrys = reactive([
[
{label: '业主',id: "1"},
{label: '租客',id: "2"},
]
])
//示例2:2级选项
const countrys = reactive([
[
{label: '业主',id: "1",list: [{label: '业主3',id: "3"}, {label: '业主4',id: "4"}]},
{label: '租客',id: "2",list: [{label: '租客5',id: "5"}, {label: '租客6',id: "6"}]},
]
,[]
])
const emit = defineEmits(['input,updateValue']);
let formData = reactive({
Gender: "2"
});
//picker回调
const fun_updateValue = (values) => {
//2级选项的回调,二级选项时可能展示的数据格式需要不同,因此不使用modelValue 通过回调函数返回选择的值
if(countrys.length==2){
formData.Gender=values[1].id;
}else{
//1级选项 时 根据需要回调 ,组件暂时不回调,已通过modelValue实现双向绑定
//formData.Gender=values[0].id;
}
}
展示效果