vant下拉查询

185 阅读1分钟

使用vant4和vue3实现picker组件下拉查询功能

//searchFilter.js

export default {
    emits: ['getfield', 'beforeclose'],//声明
    data() {
        return {
            selectColumns: [],//picker数据
            selectNewColumns: [],//picker渲染数据
            showPicker: false, //是否显示picker
            fieldValue: "", //input显示文本
            selectedValues: [],//双向绑定数据  对应的是value
            rule: [],//校验规则
        };
    },
    created() {
        // props 会暴露到 `this` 上
        this.selectColumns = this.list_data;
        this.selectNewColumns = this.list_data;
        this.selectedValues[0] = this.modelvalue;
        this.rule = this.resolveArray(this.rules);
        //初始化fieldValue
        if (this.modelvalue != '') {
            const regex = new RegExp(this.modelvalue, 'i');
            this.fieldValue = this.selectColumns.filter((option) => regex.test(option.value))[0].text;
        }
    },
    mounted() {
    },
    methods: {
        //确认
        onConfirm({ selectedOptions }) {
            this.showPicker = false;
            if (selectedOptions[0] != undefined) {
                this.fieldValue = selectedOptions[0].text;
                //调用父组件的方法
                this.$emit('getfield', selectedOptions,this.getfieldflag);
            } else {
                this.fieldValue = '';
                this.selectNewColumns = this.selectColumns;
                this.$emit('getfield', "",this.getfieldflag);
            }
        },
        //取消
        cancel() {
            this.showPicker = false;
            this.selectedValues = []
            this.fieldValue = '';
            this.$emit('getfield', [{ value: null }],this.getfieldflag);
            this.selectNewColumns = this.selectColumns;
        },
        //下拉查询文字过滤
        updateSelect(value) {
            const regex = new RegExp(value, 'i');
            this.selectNewColumns = this.selectColumns.filter((option) => regex.test(option.text));
        },
        //弹出窗关闭前回调,会通知父组件。
        beforeClose() {
            //点击遮罩层时关闭之前触发  。如果输入的数据未全匹配,则清空输入框数据
            this.showPicker = false;
            let queryObj = this.selectColumns.filter((option) => option.text == this.fieldValue);
            if (queryObj.length == 0) {
                this.selectedValues = []
                this.fieldValue = '';
                this.selectNewColumns = this.selectColumns;
            } else {
                this.$emit('getfield', queryObj,this.getfieldflag);
            }
            //关闭通知父组件进行回调
            this.$emit('beforeclose',this.getfieldflag);
        },
        //解析规则
        resolveArray(arr) {
            if(arr != undefined){
                let jsonString = arr;
                // 将属性名和字符串值中的单引号替换为双引号
                jsonString = jsonString.replace(/(\w+):/g, '"$1":').replace(/'([^']*)'/g, '"$1"');
                // 解析为 JavaScript 对象
                let jsonObject = JSON.parse(jsonString);
                return jsonObject;
            }else{
                return [];
            }
        }
    },
    /*
      *list_data    列表数据
      *getfieldflag 为了将数据反馈给父组件而定义的标记 对应的是父组件的field
      *modelvalue   反馈给父组件field的数据
    */
    props: ["list_data", "placeholder", "label", "rules", "modelvalue","getfieldflag"],
    template: `<van-field 
                v-model="fieldValue" 
                is-link 
                :label="label" 
                :placeholder="placeholder"
                :rules="rule"
                @click="showPicker = true"
                @update:model-value="updateSelect"></van-field>

             <van-popup 
                    overlay-class="hideOverlay" 
                    :before-close="beforeClose"  
                    v-model:show="showPicker" 
                    position="bottom" 
                    :overlay="true">
                    <van-picker 
                            v-model="selectedValues"   
                            :columns="selectNewColumns" 
                            @cancel="cancel"
                            @confirm="onConfirm"></van-picker>
             </van-popup>`,
};
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">


    <script type="text/javascript" src="../../../public/jquery/jquery-3.3.1.min.js"
        th:src="@{/jquery/jquery-3.3.1.min.js}"></script>
    <!--=======================导入Vue==================================-->
    <script src="../../../public/vant/4.8.0/vue.3.4.14.js"></script>
    <script src="../../../public/vant/4.8.0/vant.js"></script>

    <link rel="stylesheet" href="../../../public/vant/4.8.0/index.css" />

    <title>测试demo</title>
    <style>
        body {
            background: #b4aeae;
        }

        #app {
            padding: 6px;
        }

        .hideOverlay {
            background: none;
        }
    </style>
</head>



<body>
    <div id="app">


        <van-form @submit="onSubmit" @failed="submitFailed">
            <ahead-vant-select ref="childRef1" label="城市" 
                placeholder="请选择城市"                
                :list_data="lists"
              
                @getfield="getField" 
                @beforeclose="beforeCloseFun"
                :modelvalue="value1"
                getfieldflag="value1">
            </ahead-vant-select>

            <ahead-vant-select ref="childRef2" label="数字" 
                placeholder="请选择数字"                
                :list_data="lists1"
              
                @getfield="getField" 
                @beforeclose="beforeCloseFun"
                :modelvalue="value2"
                getfieldflag="value2">
            </ahead-vant-select>

            <ahead-vant-select ref="childRef3" label="政治面貌" placeholder="请选择政治面貌" :list_data="politiclList"
                 @getfield="getField" @beforeclose="beforeCloseFun"
                :modelvalue="value3"
                getfieldflag="value3">
            </ahead-vant-select>


            <div style="margin: 16px;">
                <van-button round block type="primary" native-type="submit">
                    提交
                </van-button>
            </div>
            <van-button type="primary" @click="clearAll">清空选项</van-button>
        </van-form>


    </div>


</body>

<script type="module">
    const { createApp, reactive, toRefs, ref, watch, onMounted, onBeforeMount, computed, $refs } = Vue;
    import aheadVantSelect from './searchFilter.js';
    const app = createApp({
        setup() {

        },
        data() {
            return {
                lists: [
                    { text: '杭州', value: 'Hangzhou' },
                    { text: '宁波', value: 'Ningbo' },
                    { text: '温州', value: 'Wenzhou' },
                    { text: '绍兴', value: 'Shaoxing' },
                    { text: '湖州', value: 'Huzhou' },
                ],
                lists1: [
                    { text: 'aaa', value: '111' },
                    { text: 'bbb', value: '222' },
                    { text: 'ccc', value: '333' },
                    { text: 'ddd', value: '444' },
                    { text: 'fff', value: '555' },
                ],
                politiclList: [{
                    text: "中共党员",
                    value: "中共党员"
                }, {
                    text: "中共预备党员",
                    value: "中共预备党员"
                }, {
                    text: "共青团员",
                    value: "共青团员"
                }, {
                    text: "群众",
                    value: "群众"
                }, {
                    text: "民革会员",
                    value: "民革会员"
                }, {
                    text: "民盟盟员",
                    value: "民盟盟员"
                }, {
                    text: "民建会员",
                    value: "民建会员"
                }, {
                    text: "民进会员",
                    value: "民进会员"
                }, {
                    text: "农工党党员",
                    value: "农工党党员"
                }, {
                    text: "致公党党员",
                    value: "致公党党员"
                }, {
                    text: "九三学社社员",
                    value: "九三学社社员"
                }, {
                    text: "台盟盟员",
                    value: "台盟盟员"
                }, {
                    text: "无党派民主人士",
                    value: "无党派民主人士"
                }],
                value1: "",
                value2: "",
                value3:""
            }
        },
        methods: {
            getField(selectedOptions,getfieldflag) {
                this[getfieldflag] = selectedOptions[0].value;
            },
            onSubmit(values) {
                console.log('submit', { "value1": this.value1, "value2": this.value2, "value3": this.value3 });
            },
            clearAll() {
                console.log("清空");
                this.$refs.childRef1.cancel();
                this.$refs.childRef2.cancel();
            },
            beforeCloseFun() {
                console.log("关闭前触发");
            },
            submitFailed() {//表单失败触发

            }
        },
    })

    app.component('ahead-vant-select', aheadVantSelect);
    app.use(vant);
    app.mount("#app");
</script>


<script>
    //app vant工具类
</script>

</html>

</html>