vue2+Element-ui中使用级联选择器选择地区
效果
一、准备工作
"china-division" : "^2.7.0"
yarn add china- division
二、代码
①:级联选择
< el-cascader
v-model = " valueData"
:props = " cascaderProps"
:options = " options"
placeholder = " 请选择家庭住址"
:disabled = " false"
:clearable = " true"
expandTrigger = " hover"
separator = ' /'
ref = " Cascader" `在这里插入代码片`
style = " width : 100%; "
@change = " handleChange"
@expand-change = " expandChange"
> </ el-cascader>
②:页面引入数据
import provinces from 'china-division/dist/provinces.json' ;
import cities from 'china-division/dist/cities.json' ;
import areas from 'china-division/dist/areas.json' ;
import streets from 'china-division/dist/streets.json' ;
import villages from 'china-division/dist/villages.json' ;
③:页面data数据(响应数据)
valueData : [ ] ,
cascaderProps : {
value : 'code' ,
label : 'name' ,
children : 'children' ,
emitPath : true ,
lazy : true ,
lazyLoad : this . lazyLoad,
checkStrictly : true ,
} ,
options : [ ] ,
④:页面方法
loadProvinces ( ) {
const provincesData = provinces. map ( province => ( {
code : province. code,
name : province. name,
} ) ) ;
this . options = provincesData;
} ,
lazyLoad ( node, resolve ) {
const { level, value} = node;
console. log ( level, value)
let children = [ ] ;
switch ( level) {
case 1 :
children = this . formatData ( cities. filter ( city => city. provinceCode === value) ) ;
break ;
case 2 :
children = this . formatData ( areas. filter ( area => area. cityCode === value) ) ;
break ;
case 3 :
children = this . formatData ( streets. filter ( street => street. areaCode === value) ) ;
break ;
case 4 :
children = this . formatData ( villages. filter ( street => street. streetCode === value) ) ;
break ;
}
if ( children && children. length > 0 ) {
resolve ( children) ;
} else {
resolve ( )
}
} ,
formatData ( data ) {
return data. map ( item => {
const formattedItem = {
code : item. code,
name : item. name,
} ;
if ( item. children && item. children. length > 0 ) {
formattedItem. children = [ ] ;
}
return formattedItem;
} ) ;
} ,
handleChange ( value ) {
let checkedNode = this . $refs. Cascader. getCheckedNodes ( ) [ 0 ] ;
value. forEach ( ( val, index ) => {
let label = checkedNode. pathLabels[ index] ;
console. log ( { name : label, code : val} )
} )
} ,
expandChange ( value ) {
} ,
三、完整代码
①:Vue页面
< template>
< el-dialog :title = " title"
v-loading = " loading" :visible.sync = " open"
width = " 1000px" append-to-body :append-to-body = " false"
:modal-append-to-body = " false" :close-on-click-modal = " false" >
< el-form ref = " form" :rules = " rules" label-width = " 110px" >
< el-divider> 基础信息</ el-divider>
< el-row :gutter = " 24" >
< el-col :span = " 8" >
< el-form-item label = " 姓名" prop = " realName" >
< el-input v-model = " form.realName" placeholder = " 请输入姓名" />
</ el-form-item>
</ el-col>
< el-col :span = " 7" >
< el-form-item label = " 性别" prop = " gender" >
< el-select v-model = " form.gender" style = " width : 150px" filterable placeholder = " 请选择性别" >
< el-option v-for = " item in gender_list" :label = " item.label" :value = " item.value" > </ el-option>
</ el-select>
</ el-form-item>
</ el-col>
< el-col :span = " 8" >
< el-form-item label = " 联系电话" prop = " phone" >
< el-input v-model = " form.phone" placeholder = " 请输入联系电话" />
</ el-form-item>
</ el-col>
</ el-row>
< el-row :gutter = " 24" >
< el-col :span = " 8" >
< el-form-item label = " 身份证号" prop = " identityNumber" >
< el-input v-model = " form.identityNumber" placeholder = " 请输入身份证号" />
</ el-form-item>
</ el-col>
< el-col :span = " 7" >
< el-form-item label = " 年龄" prop = " age" >
< el-input-number v-model = " form.age" style = " width : 150px" :min = " 1" :max = " 150"
placeholder = " 请输入年龄" > </ el-input-number>
</ el-form-item>
</ el-col>
< el-col :span = " 8" >
< el-form-item label = " 出生日期" prop = " birthDate" >
< el-date-picker style = " width : 196px" v-model = " form.birthDate" type = " date"
value-format = " yyyy-MM-dd"
:append-to-body = " false" :editable = " false" :clearable = " false"
placeholder = " 选择日期"
> </ el-date-picker>
</ el-form-item>
</ el-col>
</ el-row>
< el-row :gutter = " 24" >
< el-col :span = " 23" >
< el-form-item label = " 家庭住址" prop = " valueData" >
< el-cascader
v-model = " valueData"
:props = " cascaderProps"
:options = " options"
placeholder = " 请选择家庭住址"
:disabled = " false"
:clearable = " true"
expandTrigger = " hover"
separator = ' /'
ref = " Cascader"
style = " width : 100%; "
@change = " handleChange"
@expand-change = " expandChange"
> </ el-cascader>
</ el-form-item>
</ el-col>
</ el-row>
< el-row :gutter = " 24" >
< el-col :span = " 23" >
< el-form-item label = " 详细地址" prop = " addr" >
< el-input type = " textarea" maxlength = " 1000" show-word-limit :autosize = " { minRows: 1, maxRows: 3}"
v-model = " form.addr"
placeholder = " 请输入详细地址"
> </ el-input>
</ el-form-item>
</ el-col>
</ el-row>
< el-divider> 急救信息</ el-divider>
< el-row :gutter = " 24" >
< el-col :span = " 7" >
< el-form-item label = " 紧急联系人姓名" prop = " emergencyName" >
< el-input v-model = " form.emergencyName" placeholder = " 请输入姓名" />
</ el-form-item>
</ el-col>
< el-col :span = " 8" >
< el-form-item label = " 紧急联系人电话" prop = " emergencyPhone" >
< el-input v-model = " form.emergencyPhone" placeholder = " 请输入联系电话" />
</ el-form-item>
</ el-col>
< el-col :span = " 8" >
< el-form-item label = " 居委会电话" prop = " communityPhone" >
< el-input v-model = " form.communityPhone" placeholder = " 请输入居委会电话" />
</ el-form-item>
</ el-col>
</ el-row>
< el-row :gutter = " 24" >
</ el-row>
</ el-form>
< div slot = " footer" class = " dialog-footer" >
< el-button type = " primary" @click = " submitForm" > 确 定</ el-button>
< el-button @click = " cancel" > 取 消</ el-button>
</ div>
</ el-dialog>
</ template>
< script>
import { validIdentityNumber} from "@/utils/utils" ;
import provinces from 'china-division/dist/provinces.json' ;
import cities from 'china-division/dist/cities.json' ;
import areas from 'china-division/dist/areas.json' ;
import streets from 'china-division/dist/streets.json' ;
import villages from 'china-division/dist/villages.json' ;
export default {
name : "AddElder" ,
data ( ) {
return {
title : "" ,
open : false ,
loading : false ,
form : { } ,
gender_list : [ { label : '男性' , value : 'M' } , { label : '女性' , value : 'F' } ] ,
valueData : [ ] ,
cascaderProps : {
value : 'code' ,
label : 'name' ,
children : 'children' ,
emitPath : true ,
lazy : true ,
lazyLoad : this . lazyLoad,
checkStrictly : true ,
} ,
options : [ ] ,
rules : {
realName : [
{ required : true , message : "姓名不能为空" , trigger : "blur" }
] ,
gender : [
{ required : true , message : "性别不能为空" , trigger : "blur" }
] ,
phone : [
{ required : true , message : "联系电话不能为空" , trigger : "blur" }
] ,
identityNumber : [ { validator : this . validID, trigger : 'blur' } ] ,
age : [
{ required : true , message : "年龄不能为空" , trigger : "blur" }
] ,
}
}
} ,
mounted ( ) {
this . loadProvinces ( ) ;
} ,
methods : {
handleAdd ( ) {
this . reset ( ) ;
this . open = true ;
this . title = "新增长者信息" ;
} ,
cancel ( ) {
this . open = false ;
this . reset ( ) ;
} ,
reset ( ) {
this . form = {
realName : null ,
gender : 'M' ,
phone : null ,
age : null ,
identityNumber : null ,
birthDate : null ,
addr : null ,
emergencyName : null ,
emergencyPhone : null ,
communityPhone : null ,
deptCheckStrictly : true ,
remark : undefined ,
} ;
} ,
async validID ( rule, value, callback ) {
let reg = / (^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$) / ;
if ( reg. test ( value) ) {
let res = await validIdentityNumber ( value, value. length) ;
if ( res) {
if ( ! this . form. age || this . form. age === 1 ) this . form. age = res. age
if ( ! this . form. birthDate) this . form. birthDate = res. birthDate
if ( ! this . form. gender) this . form. gender = res. gender
}
callback ( )
} else {
callback ( new Error ( '身份证号码不正确' ) )
}
} ,
loadProvinces ( ) {
const provincesData = provinces. map ( province => ( {
code : province. code,
name : province. name,
} ) ) ;
this . options = provincesData;
} ,
lazyLoad ( node, resolve ) {
const { level, value} = node;
console. log ( level, value)
let children = [ ] ;
switch ( level) {
case 1 :
children = this . formatData ( cities. filter ( city => city. provinceCode === value) ) ;
break ;
case 2 :
children = this . formatData ( areas. filter ( area => area. cityCode === value) ) ;
break ;
case 3 :
children = this . formatData ( streets. filter ( street => street. areaCode === value) ) ;
break ;
case 4 :
children = this . formatData ( villages. filter ( street => street. streetCode === value) ) ;
break ;
}
if ( children && children. length > 0 ) {
resolve ( children) ;
} else {
resolve ( )
}
} ,
formatData ( data ) {
return data. map ( item => {
const formattedItem = {
code : item. code,
name : item. name,
} ;
if ( item. children && item. children. length > 0 ) {
formattedItem. children = [ ] ;
}
return formattedItem;
} ) ;
} ,
handleChange ( value ) {
let checkedNode = this . $refs. Cascader. getCheckedNodes ( ) [ 0 ] ;
value. forEach ( ( val, index ) => {
let label = checkedNode. pathLabels[ index] ;
console. log ( { name : label, code : val} )
} )
} ,
expandChange ( value ) {
} ,
submitForm : function ( ) {
} ,
}
}
</ script>
< style scoped lang = " scss" >
</ style>
②:Js代码(util.js)
import { saveAs} from 'file-saver' ;
import axios from 'axios' ;
export async function validIdentityNumber ( idEn, val ) {
let sex = null ;
let birth = null ;
let myDate = new Date ( ) ;
let month = myDate. getMonth ( ) + 1 ;
let day = myDate. getDate ( ) ;
let age = 0 ;
if ( val === 18 ) {
age = myDate. getFullYear ( ) - idEn. substring ( 6 , 10 ) - 1 ;
sex = idEn. substring ( 16 , 17 ) ;
birth = idEn. substring ( 6 , 10 ) + "-" + idEn. substring ( 10 , 12 ) + "-" + idEn. substring ( 12 , 14 ) ;
if ( idEn. substring ( 10 , 12 ) < month || idEn. substring ( 10 , 12 ) === month && idEn. substring ( 12 , 14 ) <= day) age++ ;
}
if ( val === 15 ) {
age = myDate. getFullYear ( ) - idEn. substring ( 6 , 8 ) - 1901 ;
sex = idEn. substring ( 13 , 14 ) ;
birth = "19" + idEn. substring ( 6 , 8 ) + "-" + idEn. substring ( 8 , 10 ) + "-" + idEn. substring ( 10 , 12 ) ;
if ( idEn. substring ( 8 , 10 ) < month || idEn. substring ( 8 , 10 ) === month && idEn. substring ( 10 , 12 ) <= day) age++ ;
}
return {
gender : sex % 2 === 0 ? 'F' : 'M' ,
age : age,
birthDate : birth
}
}
let shanghai_code = '31' ;
export let shanghai_area, shanghai_street, shanghai_village = [ ]
fetchShanghaiArea ( '/json/shanghai_area.json' ) . then ( res => {
shanghai_area = res;
} )
fetchShanghaiArea ( '/json/shanghai_street.json' ) . then ( res => {
shanghai_street = res;
} )
fetchShanghaiArea ( '/json/shanghai_village.json' ) . then ( res => {
shanghai_village = res;
} )
export function get_china_division_formatData ( flag, data ) {
return data. map ( item => {
return {
code : item. code,
name : item. name,
provinceCode : item. provinceCode,
cityCode : item. cityCode,
areaCode : item. areaCode,
streetCode : item. streetCode,
leaf : flag,
} ;
} ) ;
}
export function auto_remove_children_formatData ( data ) {
return data. map ( item => {
const formattedItem = {
code : item. code,
name : item. name,
} ;
if ( item. children && item. children. length > 0 ) {
formattedItem. children = item. children;
}
return formattedItem;
} ) ;
}
export function get_shanghai_division_by_levelAndCode ( level, code ) {
let children = [ ] ;
console. log ( 'level' , level, 'code' , code)
switch ( level) {
case 1 :
children = get_china_division_formatData ( false , shanghai_street. filter ( street => street. areaCode === code) ) ;
break ;
case 2 :
children = get_china_division_formatData ( true , shanghai_village. filter ( village => village. streetCode === code) ) ;
break ;
}
return children;
}
function saveToFile ( data, filename ) {
const json = JSON . stringify ( data) ;
const blob = new Blob ( [ json] , { type : 'application/json' } ) ;
saveAs ( blob, filename) ;
}
export async function fetchShanghaiArea ( path ) {
try {
const response = await axios. get ( path) ;
return response. data;
} catch ( error) {
console. error ( '获取文件时出错:' , error) ;
return null ;
}
}