vue 实现仿京东、淘宝省市区三级联动

在做电商或其他项目的时候,物流我们肯定会集成进去,那么我们肯定需要集成地址管理,地址管理除了最基本的省、市、区外,我们还要单独添加一个详细地址字段,不然我们无法精确到详细地址,那么最后我们的详细地址就是省市区加上我们的详细地址字段,好了,我们先来看一下省市区三级联动的效果图

其实这个功能可以封装成一个组件呢,我这里面集成了VUX移动端组件,你用的时候html里面加入,代码本来是对齐规范的,但是贴上来就变形了

1、html代码

<cell is-link title="所属地区" class="require" @click.native="choseAdd()" value-align="left">
<p style="margin-left: 20px">
{{receptAddtess.receiptProvince === '' ? "请选择" : receptAddtess.receiptProvince}} {{receptAddtess.receiptCity}} {{receptAddtess.receiptArea}}
</p>
</cell>
<!-- 省市区三级联动 -->
<section class="myAddress">
<!-- 居住地址三级联动选项 -->
<section class="showChose" v-show="showChose">
<section class="address">
<section class="titleTop">
<div class="titleTopLeft">
<span>选择地址</span>
</div>
<div class="titleTopRight">
<span @click="closeAdd()">×</span>
</div>
</section>
<hr style="height:1px;border:none;border-top:1px solid #EEEEEE;" >
<section class="title">
<div class="area" @click="provinceSelected()">
<span>{{Province?Province:info[province-1].name}}</span>
</div>
<div class="area" @click="citySelected()" :class="City?'':'active'">
{{City?City:'请选择'}}
</div>
<div class="area" @click="districtSelected()" :class="District?'':'active'" v-show="City">
{{District?District:'请选择'}}
</div>
</section>
<hr style="height:1px;border:none;border-top:1px solid #EEEEEE;" >
<ul>
<li class="addList" v-for="(v,k) in info" :key="(v,k).index"
@click="getProvinceId(v.id, v.name, k)"
v-show="showProvince"
:class="v.selected === true ? 'active' : ''">{{v.name}}</li>
<li class="addList" v-for="(v,k) in showCityList" :key="(v,k).index"
@click="getCityId(v.id, v.name, k)"
v-show="showCity"
:class="v.selected ? 'active' : ''">{{v.name}}</li>
<li class="addList" v-for="(v,k) in showDistrictList" :key="(v,k).index"
@click="getDistrictId(v.id, v.name, k)"
v-show="showDistrict"
:class="v.selected ? 'active' : ''">{{v.name}}</li>
</ul>
</section>
</section>
</section>

2、js方法如下

choseAdd () {
this.showChose = true
},
closeAdd () {
this.showChose = false
},
_filter(add, name, code) {
let result = []
for (let i = 0; i < add.length; i++) {
if (code === add[i].id) {
result = add[i][name]
}
}
return result
},
getProvinceId: function(code, input, index) {
this.province = code
this.Province = input
this.showProvince = false
this.showCity = true
this.showDistrict = false
this.showCityList = this._filter(this.info, 'city', this.province)
// 点击选择当前
this.info.map(a => { a.selected = false })
this.info[index].selected = true
this.receptAddtess.receiptProvince = input
},
provinceSelected: function() {
// 清除市级和区级列表
this.showCityList = false
this.showDistrictList = false
// 清除市级和区级选项
this.City = false
this.District = false
// 选项页面的切换
this.showProvince = true
this.showCity = false
this.showDistrict = false
},
getCityId: function(code, input, index) {
this.city = code
this.City = input
this.showProvince = false
this.showCity = false
this.showDistrict = true
this.showDistrictList = this._filter(this.showCityList, 'district', this.city)
// 选择当前添加active
this.showCityList.map(a => { a.selected = false })
this.showCityList[index].selected = true
this.receptAddtess.receiptCity = input
},
citySelected: function() {
this.showProvince = false
this.showCity = true
this.showDistrict = false
},
getDistrictId: function(code, input, index) {
this.district = code
this.District = input
// 选择当前添加active
this.showDistrictList.map(a => { a.selected = false })
this.showDistrictList[index].selected = true
// 选取市区选项之后关闭弹层
this.showChose = false
this.receptAddtess.receiptArea = input
},
districtSelected: function() {
this.showProvince = false
this.showCity = false
this.showDistrict = true
}

3、css代码如下

// 省市区三级联动CSS
.myAddress .cont{
border-bottom: 1px solid rgba(245,245,245,0.8);
}
.myAddress .cont span{
display: inline-block;
font-size: 0.28rem;
color: #333;
line-height: 0.88rem;
margin-left: 0.32rem;
}
.myAddress .cont section{
float:left;
}
.myAddress .cont p{
display: inline-block;
font-size: 0.28rem;
color: #333333;
line-height: 0.88rem;
margin-left: 1rem;
}
.myAddress .cont .pic2{
float: right;
width: 0.14rem;
height: 0.24rem;
margin: 0.32rem 0.32rem 0.32rem 0;
}
.myAddress .cont p.text{
margin-left: 0.72rem;
}
.showChose{
width:100%;
height:100%;
position:fixed;
top:0;
left:0;
z-index:120;
background:rgba(77,82,113,0.8);
}
.address{
.titleTop {
display inline
text-align center
.titleTopLeft {
padding-top 5px
padding-bottom 5px
span {
font-size 18px
}
}
.titleTopRight {
span {
position absolute
right 10px
top -5px
font-size 30px
color: #929292
}
}
}
position:absolute;
bottom:0;
left:0;
z-index:121;
background:#fff;
width:100%;
height: 430px
}
.title {
padding-top 4px
padding-bottom 5px
}
.title h4{
display:inline-block;
font-size:18px;
font-weight:normal;
}
.area{
display:inline-block;
font-size:15px;
margin-left:25px;
}
.addList{
width:85%;
padding-left:0.32rem;
font-size:15px;
line-height:32px;
}
/* 修改的格式 */
.address ul{
width:95%;
height:78%;
overflow:auto;
}
.address ul li{
margin-left:20px;
}
.address .title .active{
color:red;
border-bottom:0.02rem solid red;
}
.address ul .active{
color:red;
}

完成的一个界面如下,我这里面还调了接口,但是利用上面的代码就可以集成了,我的界面完成代码如下

<template>
<div class="modifyAddress">
<v-header title="添加地址" ref="header">
<div slot="right" class="headerRight" style="top: 2px; right: 5px;" @click="handleSaveInfo">
<span>保存</span>
</div>
</v-header>
<div class="inputWrapper">
<x-input placeholder="请输入收货人姓名" v-model="receptAddtess.receiptName">
<p slot="label" style="margin-right:20px">
<font color="red">*</font>昵称</p>
</x-input>
<x-input :max="13" is-type="china-mobile" placeholder="请输入手机号码" v-model="receptAddtess.receiptPhone">
<p slot="label" style="margin-right:20px">
<font color="red">*</font>手机号码</p>
</x-input>
<cell is-link title="所属地区" class="require" @click.native="choseAdd()" value-align="left">
<p style="margin-left: 20px">
{{receptAddtess.receiptProvince === '' ? "请选择" : receptAddtess.receiptProvince}} {{receptAddtess.receiptCity}} {{receptAddtess.receiptArea}}
</p>
</cell>
<!-- 省市区三级联动 -->
<section class="myAddress">
<!-- 居住地址三级联动选项 -->
<section class="showChose" v-show="showChose">
<section class="address">
<section class="titleTop">
<div class="titleTopLeft">
<span>选择地址</span>
</div>
<div class="titleTopRight">
<span @click="closeAdd()">×</span>
</div>
</section>
<hr style="height:1px;border:none;border-top:1px solid #EEEEEE;" >
<section class="title">
<div class="area" @click="provinceSelected()">
<span>{{Province?Province:info[province-1].name}}</span>
</div>
<div class="area" @click="citySelected()" :class="City?'':'active'">
{{City?City:'请选择'}}
</div>
<div class="area" @click="districtSelected()" :class="District?'':'active'" v-show="City">
{{District?District:'请选择'}}
</div>
</section>
<hr style="height:1px;border:none;border-top:1px solid #EEEEEE;" >
<ul>
<li class="addList" v-for="(v,k) in info" :key="(v,k).index"
@click="getProvinceId(v.id, v.name, k)"
v-show="showProvince"
:class="v.selected === true ? 'active' : ''">{{v.name}}</li>
<li class="addList" v-for="(v,k) in showCityList" :key="(v,k).index"
@click="getCityId(v.id, v.name, k)"
v-show="showCity"
:class="v.selected ? 'active' : ''">{{v.name}}</li>
<li class="addList" v-for="(v,k) in showDistrictList" :key="(v,k).index"
@click="getDistrictId(v.id, v.name, k)"
v-show="showDistrict"
:class="v.selected ? 'active' : ''">{{v.name}}</li>
</ul>
</section>
</section>
</section>
<x-textarea placeholder="街道、楼牌号等" :show-counter="false" :rows="1" autosize v-model="receptAddtess.detailAddress">
<p slot="label" style="margin-right:20px">
<font color="red">*</font>详细地址</p>
</x-textarea>
</div>
<!-- 是否默认地址 -->
<div class="recommededWrapper">
<x-switch title="设为默认地址" :value-map="[0, 1]" v-model="receptAddtess.defaultAddress" @on-change="ifDefault"></x-switch>
</div>
</div>
</template>
<script>
import VHeader from '@/components/v-header/v-header'
import { XInput, Group, Cell, XTextarea, XSwitch } from 'vux'
import axios from '@/api/axiosApi'
import info from '@/assets/json/address.json'
import { localUser } from '@/assets/js/local'
export default {
data () {
return {
pageTitle: '居住地址',
address: '',
showChose: false,
showProvince: true,
showCity: false,
showDistrict: false,
showCityList: false,
showDistrictList: false,
province: 1,
city: 3,
district: 57,
GetProvinceId: 2,
District: false,
Province: false,
City: false,
// areaProvince: '',
// areaCity: '',
// areaDistrict: '',
// v-for循环判断是否为当前
selected: false,
info,
receptAddtess: {
userId: '',
receiptName: '',
receiptPhone: '',
detailAddress: '',
defaultAddress: 0,
receiptProvince: '',
receiptCity: '',
receiptArea: ''
}
}
},
mounted () {
},
created () {
},
methods: {
handleSaveInfo () {
if (this.receptAddtess.receiptName === '') {
this.$vux.toast.text('收货人不能为空', 'middle')
return
}
if (this.receptAddtess.receiptPhone === '') {
this.$vux.toast.text('电话号码不能为空', 'middle')
return
}
if (this.receptAddtess.receiptProvince === '') {
this.$vux.toast.text('所属地区不能为空', 'middle')
return
}
if (this.receptAddtess.detailAddress === '') {
this.$vux.toast.text('详细地址不能为空', 'middle')
return
}
this.handleAddReceptAddress()
},
ifDefault (value) {
this.receptAddtess.defaultAddress = value
},
// 添加收货地址,每个用户不超过20个地址
handleAddReceptAddress () {
this.receptAddtess.userId = localUser.get('id')
axios.post(this, '/v1/receiptAddress', this.receptAddtess, (data) => {
this.$vux.confirm.show({
title: '温馨提示',
content: '添加地址成功'
})
})
},
choseAdd () {
this.showChose = true
},
closeAdd () {
this.showChose = false
},
_filter(add, name, code) {
let result = []
for (let i = 0; i < add.length; i++) {
if (code === add[i].id) {
result = add[i][name]
}
}
return result
},
getProvinceId: function(code, input, index) {
this.province = code
this.Province = input
this.showProvince = false
this.showCity = true
this.showDistrict = false
this.showCityList = this._filter(this.info, 'city', this.province)
// 点击选择当前
this.info.map(a => { a.selected = false })
this.info[index].selected = true
this.receptAddtess.receiptProvince = input
},
provinceSelected: function() {
// 清除市级和区级列表
this.showCityList = false
this.showDistrictList = false
// 清除市级和区级选项
this.City = false
this.District = false
// 选项页面的切换
this.showProvince = true
this.showCity = false
this.showDistrict = false
},
getCityId: function(code, input, index) {
this.city = code
this.City = input
this.showProvince = false
this.showCity = false
this.showDistrict = true
this.showDistrictList = this._filter(this.showCityList, 'district', this.city)
// 选择当前添加active
this.showCityList.map(a => { a.selected = false })
this.showCityList[index].selected = true
this.receptAddtess.receiptCity = input
},
citySelected: function() {
this.showProvince = false
this.showCity = true
this.showDistrict = false
},
getDistrictId: function(code, input, index) {
this.district = code
this.District = input
// 选择当前添加active
this.showDistrictList.map(a => { a.selected = false })
this.showDistrictList[index].selected = true
// 选取市区选项之后关闭弹层
this.showChose = false
this.receptAddtess.receiptArea = input
},
districtSelected: function() {
this.showProvince = false
this.showCity = false
this.showDistrict = true
}
},
components: {
VHeader,
XInput,
Group,
Cell,
XTextarea,
axios,
XSwitch,
localUser
}
}
</script>
<style lang="stylus" scoped>
@import '~@/assets/css/variable.styl'
.modifyAddress {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: $color-background;
z-index: 101;
height:100%;
}
.inputWrapper {
background-color white
}
// 省市区三级联动CSS
.myAddress .cont{
border-bottom: 1px solid rgba(245,245,245,0.8);
}
.myAddress .cont span{
display: inline-block;
font-size: 0.28rem;
color: #333;
line-height: 0.88rem;
margin-left: 0.32rem;
}
.myAddress .cont section{
float:left;
}
.myAddress .cont p{
display: inline-block;
font-size: 0.28rem;
color: #333333;
line-height: 0.88rem;
margin-left: 1rem;
}
.myAddress .cont .pic2{
float: right;
width: 0.14rem;
height: 0.24rem;
margin: 0.32rem 0.32rem 0.32rem 0;
}
.myAddress .cont p.text{
margin-left: 0.72rem;
}
.showChose{
width:100%;
height:100%;
position:fixed;
top:0;
left:0;
z-index:120;
background:rgba(77,82,113,0.8);
}
.address{
.titleTop {
display inline
text-align center
.titleTopLeft {
padding-top 5px
padding-bottom 5px
span {
font-size 18px
}
}
.titleTopRight {
span {
position absolute
right 10px
top -5px
font-size 30px
color: #929292
}
}
}
position:absolute;
bottom:0;
left:0;
z-index:121;
background:#fff;
width:100%;
height: 430px
}
.title {
padding-top 4px
padding-bottom 5px
}
.title h4{
display:inline-block;
font-size:18px;
font-weight:normal;
}
.area{
display:inline-block;
font-size:15px;
margin-left:25px;
}
.addList{
width:85%;
padding-left:0.32rem;
font-size:15px;
line-height:32px;
}
/* 修改的格式 */
.address ul{
width:95%;
height:78%;
overflow:auto;
}
.address ul li{
margin-left:20px;
}
.address .title .active{
color:red;
border-bottom:0.02rem solid red;
}
.address ul .active{
color:red;
}
.recommededWrapper {
margin-top 10px
background-color white
}
</style>
<style>
.modifyAddress .require .vux-label:before {
content: '*';
display: inline-block;
color: red;
}
</style>

哈哈,效果就实现了

vue 实现仿京东、淘宝省市区三级联动相关推荐

  1. 菜鸟窝-仿京东淘宝项目学习笔记(二)ToolBar的基本使用

    本篇知识点均来自于菜鸟窝-仿京东淘宝实战项目视频中 今天继续仿京东淘宝项目的学习,第二天,学习ToolBar的基本使用,本篇记录视频中一些重要的笔记 笔记一:ToolBar的一些重要属性 xml st ...

  2. 微信小程序仿京东淘宝商品排序

    微信小程序仿京东淘宝商品排序 效果图如下所示 仿京东微信小程序视频请加QQ:1010753897 下载地址:https://download.csdn.net/download/qq_43764578 ...

  3. 仿京东淘宝等首页广告弹窗广告 dialog

    记录贴 防止以后忘记. 上图 1.dialog布局 图片随便找的 <?xml version="1.0" encoding="utf-8"?> &l ...

  4. Android 仿京东淘宝 商品详情页 商品图片效果

    最近重构商品,产品要求,按照淘宝京东来.... 成品如图这个效果 思路就是监听外边ScrollView的滑动监听,然后给上边图片设置margin,二话不说上代码 简单的界面布局 <?xml ve ...

  5. Android 仿京东淘宝拼多多的商品分类,双列表联动,RecyclerView嵌套

    淘宝京东的相对简单很多,两个RecyclerView就可实现了. 现在要做的是右边滑动的时候左边跟着联动,如下图: 思路:左右肯定都是RecyclerView了,至于中间的图片嘛当然也是Recycle ...

  6. Android 仿京东淘宝多规格选择

    上图直接点,下次在修改理论,因为要下班了 这是淘宝的规格选择,我随便选择了一个,将就着看吧 然后再来看看我的效果 这个我是在CSDN上看的一篇文章 我把地址贴出来这是原文地址我是在他的基础改的 我做了 ...

  7. 仿京东淘宝放大镜特效 jqzoom.js

    效果图如下: HTML 文本源码: 1 <!DOCTYPE html> 2 <htmllang="en"> 3 <head> 4 <met ...

  8. JQ或JS仿京东淘宝属性规格SKU样式

    <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8" ...

  9. 安卓高仿京东淘宝的筛选功能,全网最简单方便

    最近需要实现一个筛选的功能.但是在网上找了半天都写得特别乱,要不就是收费,今天做一个.实现效果图如下. 点击按钮直接弹出.可以放在任何控件下面.下面是使用代码: 首先需要添加依赖: 在build.gr ...

最新文章

  1. AVL的LL,RR,LR,RL调整
  2. 云计算革命对国际关系的影响
  3. placeholder如何实现换行
  4. Linux内核设计与实现---页高速缓存和页回写
  5. 程序随笔——C++实现的一个线程池
  6. 关于单链表,二叉树,图,查找和排序的软件编程
  7. Java @responsebody,springMVC 使用注解@ResponseBody 不能返回JSON数据
  8. centos6.5安装Chrome
  9. linux pandas教程_这7种Python的全新玩法,你们一定不知道!(附赠Python教程)
  10. 成像反了_宋国荣, 窦致夏:快速超声 C 扫描成像中的信号频域分析法及其应用...
  11. 【MyEcplise SVN】myEcplise上安装SVN的多种方式
  12. 计算机大学生职业规划书word模板,大学生职业规划书范文word模板
  13. java语言判断101到200之间素数
  14. 阿里云服务器搭建k8s
  15. jQuery 样式操作
  16. python大数据书籍推荐-清华大学出版社-图书详情-《从零开始学Python大数据与量化交易》...
  17. 大数据测试英语水平测试
  18. [RK3399][Android7.1] 移植笔记 --- 9.7寸eDP显示屏添加
  19. html5学习笔记之十(微数据)
  20. Idea 打包JAVA项目

热门文章

  1. mybatis-plus巨坑--死锁
  2. 全选主元的Gauss-Jordan消元法
  3. VUE组件封装Tips
  4. 在Veristand中使用GE的内存反射卡
  5. 毕业3年,从中软外包跳槽到京东集团,年薪翻倍,我经历了什么?
  6. C语言qsort函数的实现
  7. 揭开中国人使用计算机互联网的序幕的人,_____发出了中国第一封电子邮件,从此揭开了中国人使用Internet的.._简答题试题答案...
  8. 你知道中国第一封电子邮件送达用了多久吗?绝对想不到
  9. docker安装orcale-12c
  10. FPGA之CRC校验