vue3如何使用vant-picker封装省市二级联动

目录
  • 首先,项目中引入vant-ui
  • 子组件代码PickerArea
  • 父组件代码

怕什么真理无穷,进一步有进一步的欢喜呀,不得不承认的就是,兴趣和擅长是一个良性迭代的循环啊,你擅长某件事情,就会越喜欢它,越喜欢,就越愿意花时间,进而越擅长。所以代码码起来吧哈哈哈

近期用上了vue3,还顺手写了个小需求,用vant-picker封装一个省市的二级联动,并且在从后端接口获取省市的数据,点开弹出框需要展示默认的选项,比如点击广东省-深圳市输入框,弹出的picker级联选择器需要默认广东 -深圳。

如下图:

好,那么话不多说,接下来一步一步来实现。

首先,项目中引入vant-ui

import { Popup, Picker } from 'vant'
components: {
    [Picker.name]: Picker,
    [Popup.name]: Popup,
  },

vant官网中,地区联动的形式是这样的

而我的数据格式是这样的

[ {
    "citys": [
      {
        "cityName": "北京市"
      }
    ],
    "provinceName": "北京市"
  },
  {
    "citys": [
      {
        "cityName": "天津市"
      }
    ],
    "provinceName": "天津市"
  },
  {
    "citys": [
      {
        "cityName": "上海市"
      }
    ],
    "provinceName": "上海市"
  },
  {
    "citys": [
      {
        "cityName": "重庆市"
      }
    ],
    "provinceName": "重庆市"
  },]

然后对数据做了处理,处理成官网的形式,这样就可以联动了

 const columnsData = chinaAreaDataType.map((item, index) => {
      const children: { text: string }[] = []
      item.citys.forEach((item) => {
        children.push({
          text: item.cityName,
        })
      })
      return { text: item.provinceName, children }
    })

其中关于一些vue3父子组件的传值就不过多赘述了,有需要可自行查看官方文档

接下来说一说,点开弹出框需要展示默认的选项怎么实现的吧,此处,vant官网给出了一个api,不过没有使用示例,捣鼓了半天。

使用setIndexes设置获取到的索引值,就可以实现点开弹出框需要展示默认的选项了,在onMounted中通过ref去设置相应的索引即可。

onMounted(() => {
      const cityName = toRef(props, 'areaValue').value.split('-')
      const findProvinceName = columnsData.findIndex((value) => value.text === cityName[0])
      const findCityName = columnsData[findProvinceName].children.findIndex((value) => value.text === cityName[1])
      areaPicker.value?.setIndexes([findProvinceName, findCityName])
    })

你以为这样就结束了吗,no no no,还要在popup 中设置lazy-render为false,这样就结束拉~

好吧废话不多说,上子组件代码

子组件代码PickerArea

<template>
  <div class="container">
    <van-popup v-model:show="refShowOverlay" position="bottom" :lazy-render="false" round>
      <van-picker
        ref="areaPicker"
        show-toolbar
        :columns="columnsData"
        value-key="text"
        @change="handleChangeArea"
        @cancel="handleCancelArea"
        @confirm="handleConfirmArea"
      >
        <template v-slot:cancel>
          <div class="icon--button">
            <img src="@/assets/icons/lineCross.svg" />
          </div>
        </template>
        <template v-slot:title>
          <p class="title">{{ title }}</p>
        </template>
        <template v-slot:confirm>
          <div class="icon--button">
            <img src="@/assets/icons/lineHook.svg" />
          </div>
        </template>
      </van-picker>
    </van-popup>
  </div>
</template>
<script lang="ts">
import { defineComponent, ref, toRef, watch, reactive, onMounted } from 'vue'
import { Popup, Picker, Field } from 'vant'
import chinaAreaDataType from './chinaAreaData.json'
export default defineComponent({
  name: 'TasPickerArea',
  components: {
    [Picker.name]: Picker,
    [Popup.name]: Popup,
    [Field.name]: Field,
  },
  props: {
    areaValue: {
      type: String,
      default: '',
    },
    show: {
      type: Boolean,
      default: false,
    },
    showDatePicker: {
      type: Boolean,
      default: false,
    },
    title: {
      type: String,
      default: '请选择地区',
    },
  },
  setup(props, { emit }) {
    const refShowOverlay = ref(false)
    const computedShowOverlay = toRef(props, 'showDatePicker')
    const areaPicker = ref<typeof Picker>()
    const handleCancelArea = () => {
      emit('close', false)
    }
    const columnsData = chinaAreaDataType.map((item, index) => {
      const children: { text: string }[] = []
      item.citys.forEach((item) => {
        children.push({
          text: item.cityName,
        })
      })
      return { text: item.provinceName, children }
    })
    const handleChangeArea = (area: Array<{ text: string }>) => {
      emit('change-area', area)
    }
    const handleConfirmArea = (area: Array<{ text: string }>) => {
      emit('confirm-area', area)
      handleCancelArea()
    }
    watch(computedShowOverlay, (nV) => {
      refShowOverlay.value = nV
    })
    onMounted(() => {
      const cityName = toRef(props, 'areaValue').value.split('-')
      const findProvinceName = columnsData.findIndex((value) => value.text === cityName[0])
      const findCityName = columnsData[findProvinceName].children.findIndex((value) => value.text === cityName[1])
      areaPicker.value?.setIndexes([findProvinceName, findCityName])
    })
    return {
      refShowOverlay,
      areaPicker,
      columnsData,
      handleChangeArea,
      handleCancelArea,
      handleConfirmArea,
    }
  },
})
</script>
<style lang="scss" scoped src="./index.scss" />

父组件代码

<template>
  <div>
    <van-field v-model="areaValue" label="地区" placeholder="请输入地区" @click="handleClickOFF" />
    <tas-picker-china-area
      :show-date-picker="show"
      @close="show = false"
      @confirm-area="handleConfirmArea"
      @change-area="handleChangeArea"
      :areaValue="areaValue"
    />
  </div>
</template>
<script lang="ts">
import { computed, defineComponent, ref, watch, reactive, toRefs } from 'vue'
import { Field } from 'vant'
import { px2remWithUnit } from '@/utils/ui'
import { getThemeVarValue } from '@/config/ui'
import { showDialog } from './components/TasDialog/dialog'
import TasPickerChinaArea from '@/components/TasPickerChinaArea/index.vue'
export default defineComponent({
  name: 'TasButton',
  components: {
    [Field.name]: Field,
    TasPickerChinaArea,
  },
  setup() {
    const show = ref(false)
    const refShowDatePicker = ref(true)
    const areaValue = ref('广东省-深圳市')
    const handleClickOFF = () => {
      show.value = !show.value
    }
    const handleConfirmArea = (area: Array<{ text: string }>) => {
      areaValue.value = `${area[0].text} - ${area[1].text}`
    }
    const handleChangeArea = (area: Array<{ text: string }>) => {}
    return {
      show,
      areaValue,
      refShowDatePicker,
      handleClickOFF,
      handleConfirmArea,
      handleChangeArea,
    }
  },
})
</script>

css代码

.container {
  overflow: hidden;
  &::v-deep(.van-picker-column) {
    font-size: 32px;
  }
  ::v-deep(.van-picker__toolbar) {
    height: auto;
    padding: 30px 45px;
    border-bottom: 1px solid rgba(0, 0, 0, 0.1);
  }
}
.icon--button img {
  width: 52px;
}
.title {
  font-size: 32px;
  font-weight: 500;
  color: #000000;
  line-height: 45px;
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • vue3+ts+vant移动端H5项目搭建的实现步骤

    目录 1.全局安装vue-cli 2.使用vue ui 可视化创建项目 3.打开项目 4.安装vant,并实现按需引入 5.移动端适配(rem) 使用vue-cli搭建项目 1.全局安装vue-cli npm install -g @vue/cli 安装完成验证 vue -V 2.使用vue ui 可视化创建项目 2.1 vue ui vue ui 2.2 点击创建 点击创建 在learn目录下创建项目 填写创建的项目名,选择包管理器npm 2.3 点击下一步 选择手动,点击下一步 2.4 选择

  • 使用Vite+Vue3+Vant全家桶快速构建项目步骤详解

    目录 引言 一.vue3全家桶模板介绍 1.版本依赖 2.全家桶内置集成 二.安装 tive-cli 命令行工具 三.生成项目 四.项目体验 引言 随着Vue3 和 Vite 版本的不断更新完善,开发体验有了质的飞跃.因此,越来越多的大厂也逐步拥抱 Vue3. 利用Vite 脚手架工具可以很轻松生成以 Vue3 为模板的项目,但是作为Vue全家桶的 vue-router.vuex.axios等成员,需要自己一个一个去配置.于是便自行开发了本文讲到的 tive-cli 脚手架模板工具,只需短短几个

  • Vue3+vant+ts 上滑加载解决上滑调用多次数据的问题(推荐)

    之前用vue2的时候,写过vue2的用法,文末扩展知识点击查看,用得挺好的,也没啥问题,照葫芦画瓢的做出来了,但是有问题,下滑之后调用多次数据,按理说 组件通过 loading 和 finished 这俩变量控制加载状态,当组件滚动到底部时,会触发 load 事件并将 loading 设置成 true.此时可以发起异步操作并更新数据,数据更新完毕后,将 loading 设置成 false 即可.若数据已全部加载完毕,则直接将 finished 设置成 true 即可. 但是我打印了一下,在调用方

  • Vue3中使用vant的踩坑实战日记

    目录 前言 一.下载vant 二.下载插件 三.配置插件 四.简单使用 五.我的解决方法 总结 前言 我照着视频中老师教的方式去使用vant(和官网教程一样),发现样式根本不起作用(想截个图来着,但是vite热更新太厉害了,找不到了哈哈哈),然后又反复看了视频一遍,检查自己插件啥的而又没有安装好,发现和老师的一样....,头疼…害...,幸好我最后在想用不用在main.js引入vant(因为老师说插件会自动识别,所以一开始一直以为是自己配置或者代码写错了的问题QAQ),最后成功了嘿嘿嘿(但是这样

  • vue3如何使用vant-picker封装省市二级联动

    目录 首先,项目中引入vant-ui 子组件代码PickerArea 父组件代码 怕什么真理无穷,进一步有进一步的欢喜呀,不得不承认的就是,兴趣和擅长是一个良性迭代的循环啊,你擅长某件事情,就会越喜欢它,越喜欢,就越愿意花时间,进而越擅长.所以代码码起来吧哈哈哈 近期用上了vue3,还顺手写了个小需求,用vant-picker封装一个省市的二级联动,并且在从后端接口获取省市的数据,点开弹出框需要展示默认的选项,比如点击广东省-深圳市输入框,弹出的picker级联选择器需要默认广东 -深圳. 如下

  • vue学习之mintui picker选择器实现省市二级联动示例

    本文介绍了vue学习之mintui picker选择器实现省市二级联动示例,分享给大家,具体如下: Mint UI 使用文档:https://mint-ui.github.io/docs/#/zh-cn2 Popup弹出框介绍:https://mint-ui.github.io/docs/#/zh-cn2/popup Picker选择器介绍:https://mint-ui.github.io/docs/#/zh-cn2/picker Datetime picker日期选择器介绍:https://

  • 微信小程序 使用picker封装省市区三级联动实例代码

    微信小程序 使用picker封装省市区三级联动实例 目前学习小程序更多的是看看能否二次封装其它组件,利于以后能快速开发各种小程序应用.目前发现picker的selector模式只有一级下拉,那么我们是否可以通过3个picker来实现三级联动模板的形式来引入其它页面中呢?答案是肯定可以的.那么我的思路是这样的: 1.使用template模板语法进行封装,数据从页面传入 2.根据picker组件的语法,range只能是一组中文地区数组,但是我们需要每个地区的唯一码来触发下一级联动数据.这样,我的做法

  • AngularJS实现的省市二级联动功能示例【可对选项实现增删】

    本文实例讲述了AngularJS实现的省市二级联动功能.分享给大家供大家参考,具体如下: <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>www.jb51.net 省市二级联动</title> </head> <style> *{ margin:0; padding:0; } .u

  • js实现的全国省市二级联动下拉选择菜单完整实例

    本文实例讲述了js实现的全国省市二级联动下拉选择菜单.分享给大家供大家参考.具体如下: 运行效果截图如下: 在线演示地址如下: http://demo.jb51.net/js/2015/js-province-city-cho-menu-codes/ 具体代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-

  • 省市二级联动小案例讲解

    在网页开发过程中,选择省市的时候,省市之间有关联,这是一个小小的二级联动案例 ,运用到HTML.css.php.js以及 AJAX的异步请求 首先建立city.php和province.php文件和connet.html,将二级联动的大概结构写出来,html代码如下: <label>省份:</label> <select id="province"> <option>请选择</option> </select> &

  • 基于javascript实现全国省市二级联动下拉选择菜单

    本文实例讲述了js实现全国省市二级联动下拉选择菜单,分享给大家供大家参考.具体如下: 效果图: 具体代码: <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> <title>无标题文档</title> <script type="text/javascript"&g

  • javascript支持区号输入的省市二级联动下拉菜单

    省市二级联动下拉菜单,增加了区号输入.多组选项共用一组数据. 选择地区,可以获取区号,填写区号自动选取地区. 某些地市的区号收集中. 省份 选择城区 1)inti(0);findarea();"> 省份 选择城区 1)inti(1);findarea();"> var areaList={ "北京":[["选择城区","10"],["东城区",""],["西城区&q

  • jQuery+Asp.Net实现省市二级联动功能的方法

    本文实例讲述了jQuery+Asp.Net实现省市二级联动功能的方法.分享给大家供大家参考,具体如下: 页面html: <%@ Page Language="C#" AutoEventWireup="true" CodeFile="ddlAjax.aspx.cs" Inherits="ThreeAjaxDrop_ddlAjax" %> <!DOCTYPE html PUBLIC "-//W3C//D

  • Vue配合iView实现省市二级联动的示例代码

    在实现省市二级联动时,如果省份和城市写在一个数组对象中.可以根据,点击某个省份时获取到目标省份的id 是否同 数组中的某个对象id一致 来判断 iView中的on-change事件 on-change事件:即选中的Option变化时触发,默认返回 value.(value在这里只支持String和Number类型) 1.html部分 <template> <Form ref="formValidate" :model="formValidate"

随机推荐