一.v-distpicker 的用法
1.安装:npm install v-distpicker
二。改造直辖市
这个组件在选择四个直辖市的时候有点问题,比如选择北京,就是北京市,北京市,···区,这样显示感觉想出错了一样:如果
1.第一种,将直辖市,改成北京,北京市,XX区,淘宝手机地址更换就是这样的,看起来也比北京市,北京市好。
比较推荐这种方式,因为改动小,简单。
唯一的问题就是,在引用的时候,如果是通过npm install 安装引用的,更改node_module中的文件时没效果的,
解决方式:更改引用插件的源码,使其生效,需要我们把插件下载下来,放到项目中,已组件的形式引用,这样改过的源码才会生效。但是这样做有一个问题就是不能时时更新这个插件,比如这个级联插件在git上又有代码迭代,想要获取新的代码,就要重新下载新的版本,把自己之前的改动放上去,再重新引入。好在这个省市区级联的问题,更新的内容不大,所以下载后引用的方式影响不大。
步骤:
找v-distPicekr到需要的版本下载下来
解压后找到src下面的三个文件
复制三个文件,到一个文件夹,比如我的areaPicker,放到项目中作为组件引用
作为正常组件引用即可
此事修改这个areaPicker里面的districts.js文件就可以了,去掉省级单位中直辖市的市字就生效了。
这种方案改动小,而且简单,也好于“北京市北京市”这种的
第二种,当选择直辖市事,去掉中间的市,直接显示区,如图:
回显是,city传空即可。
这种修改也需要修改源码,所以改动是在第一种方法下载引用的文件中修改。
引用和回显都没问题,由于是帮别人改的代码,效果实现了,但没有过多测试。
直接附上修改的 Distpicker.vue代码,其他文件没有改动。
<template>
<div :class="wrapper">
<template v-if="type !== 'mobile'">
<label>
<select
@change="getCities"
v-model="currentProvince"
:disabled="disabled || provinceDisabled"
>
<option :value="placeholders.province">
{{ placeholders.province }}
</option>
<option v-for="(item, index) in provinces" :value="item" :key="index">
{{ item }}
</option>
</select>
</label>
<template v-if="!onlyProvince">
<label>
<select
@change="getAreas"
v-model="currentCity"
:disabled="disabled || cityDisabled"
v-if="!isDirectlyCity"
>
<option :value="placeholders.city">
{{ placeholders.city }}
</option>
<option
v-for="(item, index) in cities"
:value="item"
:key="index"
>
{{ item }}
</option>
</select>
</label>
<label>
<select
v-if="!hideArea"
v-model="currentArea"
:disabled="disabled || areaDisabled"
>
<option :value="placeholders.area">
{{ placeholders.area }}
</option>
<option v-for="(item, index) in areas" :value="item" :key="index">
{{ item }}
</option>
</select>
</label>
</template>
</template>
<template v-else>
<div :class="addressHeader">
<ul>
<li :class="{ active: tab === 1 }" @click="resetProvince">
{{
currentProvince && !staticPlaceholder
? currentProvince
: placeholders.province
}}
</li>
<template v-if="!onlyProvince">
<li
v-if="showCityTab"
:class="{ active: tab === 2 }"
@click="resetCity"
>
{{
currentCity && !staticPlaceholder
? currentCity
: placeholders.city
}}
</li>
<li
v-if="showAreaTab && !hideArea"
:class="{ active: tab === 3 }"
>
{{
currentArea && !staticPlaceholder
? currentArea
: placeholders.area
}}
</li>
</template>
</ul>
</div>
<div :class="addressContainer">
<ul v-if="tab === 1">
<li
v-for="(item, index) in provinces"
:class="{ active: item === currentProvince }"
@click="chooseProvince(item)"
:key="index"
>
{{ item }}
</li>
</ul>
<template v-if="!onlyProvince">
<ul v-if="tab === 2">
<li
v-for="(item, index) in cities"
:class="{ active: item === currentCity }"
@click="chooseCity(item)"
:key="index"
>
{{ item }}
</li>
</ul>
<ul v-if="tab === 3 && !hideArea">
<li
v-for="(item, index) in areas"
:class="{ active: item === currentArea }"
@click="chooseArea(item)"
:key="index"
>
{{ item }}
</li>
</ul>
</template>
</div>
</template>
</div>
</template>
<script>
import DISTRICTS from "./districts";
const DEFAULT_CODE = 100000;
export default {
name: "v-distpicker",
props: {
province: { type: [String, Number], default: "" },
city: { type: [String, Number], default: "" },
area: { type: [String, Number], default: "" },
type: { type: String, default: "" },
hideArea: { type: Boolean, default: false },
onlyProvince: { type: Boolean, default: false },
staticPlaceholder: { type: Boolean, default: false },
placeholders: {
type: Object,
default() {
return {
province: "省",
city: "市",
area: "区",
};
},
},
districts: {
type: [Array, Object],
default() {
return DISTRICTS;
},
},
disabled: { type: Boolean, default: false },
provinceDisabled: { type: Boolean, default: false },
cityDisabled: { type: Boolean, default: false },
areaDisabled: { type: Boolean, default: false },
addressHeader: { type: String, default: "address-header" },
addressContainer: { type: String, default: "address-container" },
wrapper: { type: String, default: "distpicker-address-wrapper" },
},
data() {
return {
tab: 1,
showCityTab: false,
showAreaTab: false,
isDirectlyCity: false,
provinces: [],
cities: [],
areas: [],
currentProvince:
this.determineType(this.province) || this.placeholders.province,
currentCity: this.determineType(this.city) || this.placeholders.city,
currentArea: this.determineType(this.area) || this.placeholders.area,
};
},
created() {
if (this.type != "mobile") {
this.provinces = this.getDistricts();
if (this.province) {
if (
this.province == "北京市" ||
this.province == "上海市" ||
this.province == "天津市" ||
this.province == "重庆市"
) {
this.isDirectlyCity = true;
this.areas = this.getDistricts(
this.getAreaCode(this.determineType(this.province), this.area)
);
return false;
} else {
this.cities = this.getDistricts(
this.getAreaCode(this.determineType(this.province))
);
}
} else {
this.cities = [];
}
this.areas = this.city
? this.getDistricts(
this.getAreaCode(this.determineType(this.city), this.area)
)
: [];
// this.provinces = this.getDistricts();
// this.cities = this.province
// ? this.getDistricts(this.getAreaCode(this.determineType(this.province)))
// : [];
// let directCity = this.isDirectCity(this.province, this.city);
// this.areas = this.city
// ? this.getDistricts(
// this.getAreaCode(
// this.determineType(this.city),
// directCity ? this.determineType(this.city) : this.area
// )
// )
// : [];
} else {
if (this.area && !this.hideArea && !this.onlyProvince) {
this.tab = 3;
this.showCityTab = true;
this.showAreaTab = true;
let directCity = this.isDirectCity(this.province, this.city);
this.areas = this.getDistricts(
this.getAreaCode(
this.determineType(this.city),
directCity ? this.determineType(this.city) : this.area
)
);
} else if (this.city && this.hideArea && !this.onlyProvince) {
this.tab = 2;
this.showCityTab = true;
this.cities = this.getDistricts(
this.getAreaCode(this.determineType(this.province))
);
} else {
this.provinces = this.getDistricts();
}
}
},
watch: {
currentProvince(vaule) {
this.$emit("province", this.setData(vaule, "province"));
if (this.onlyProvince) {
this.emit("selected");
}
},
currentCity(value) {
this.$emit("city", this.setData(value, "city", this.currentProvince));
if (value != this.placeholders.city && this.hideArea) {
this.emit("selected");
}
},
currentArea(value) {
this.$emit("area", this.setData(value, "area", this.currentProvince, true));
if (value != this.placeholders.area) {
this.emit("selected");
}
},
province(value) {
this.currentProvince = this.province || this.placeholders.province;
this.cities = this.determineValue(
"province",
this.currentProvince,
this.placeholders.province
);
},
city(value) {
this.currentCity = this.city || this.placeholders.city;
this.areas = this.determineValue(
"city",
this.currentCity,
this.placeholders.city,
this.currentProvince
);
},
area(value) {
this.currentArea = this.area || this.placeholders.area;
},
},
methods: {
setData(value, type, check = "", isArea = false) {
let code;
if (isArea) {
code = this.getCodeByArea(value);
} else {
code = this.getAreaCode(value, check, type);
}
return {
code: code,
value: value,
};
},
getCodeByArea(value) {
let areas_map = {};
let arr_keys = Object.keys(this.areas);
for (let i = 0; i < arr_keys.length; i++) {
let arr_key = arr_keys[i];
let arr_value = this.areas[arr_key];
areas_map[arr_value] = arr_key;
}
return areas_map[value];
},
emit(name) {
let data = {
province: this.setData(this.currentProvince, "province"),
};
if (!this.onlyProvince) {
this.$set(
data,
"city",
this.setData(this.currentCity, "city", this.currentProvince)
);
}
if (!this.onlyProvince || this.hideArea) {
this.$set(
data,
"area",
this.setData(this.currentArea, "area", this.currentProvince, true)
);
}
this.$emit(name, data);
},
getCities() {
this.currentCity = this.placeholders.city;
this.currentArea = this.placeholders.area;
if (
this.currentProvince == "北京市" ||
this.currentProvince == "天津市" ||
this.currentProvince == "上海市" ||
this.currentProvince == "重庆市"
) {
this.cities = [];
this.isDirectlyCity = true;
this.getAreas(this.isDirectlyCity);
} else {
this.isDirectlyCity = false;
this.cities = this.determineValue(
"province",
this.currentProvince,
this.placeholders.province
);
this.cleanList("areas");
}
if (this.cities.length === 0) {
this.emit("selected");
this.tab = 1;
this.showCityTab = false;
}
},
getAreas(isDirectlyCity) {
this.currentArea = this.placeholders.area;
if (isDirectlyCity === true) {
this.areas = this.determineValue(
"city",
this.currentProvince,
this.placeholders.province,
this.currentProvince
);
return false;
} else {
this.areas = this.determineValue(
"city",
this.currentCity,
this.placeholders.city,
this.currentProvince
);
}
if (this.areas.length === 0) {
this.emit("selected");
this.tab = 2;
this.showAreaTab = false;
}
},
resetProvince() {
this.tab = 1;
this.provinces = this.getDistricts();
this.showCityTab = false;
this.showAreaTab = false;
},
resetCity() {
this.tab = 2;
this.showCityTab = true;
this.showAreaTab = false;
this.getCities();
},
chooseProvince(name) {
this.currentProvince = name;
if (this.onlyProvince) return;
this.tab = 2;
this.showCityTab = true;
this.showAreaTab = false;
this.getCities();
},
chooseCity(name) {
this.currentCity = name;
if (this.hideArea) return;
this.tab = 3;
this.showCityTab = true;
this.showAreaTab = true;
this.getAreas();
},
chooseArea(name) {
this.currentArea = name;
},
getAreaCodeByPreCode(name, preCode) {
let codes = [];
for (let x in this.districts) {
for (let y in this.districts[x]) {
if (name === this.districts[x][y]) {
codes.push(y);
}
}
}
if (codes.length > 1) {
let index;
codes.forEach((item, i) => {
if (
(preCode.length === 2 && item.slice(0, 2) === preCode) ||
(preCode.length === 4 && item.slice(0, 4) !== preCode)
) {
index = i;
}
});
return codes[index];
} else {
return codes[0];
}
},
getAreaCode(name, check = "", type = "") {
for (let x in this.districts) {
for (let y in this.districts[x]) {
if (name === this.districts[x][y]) {
if (check.length > 0) {
let code = y;
if (check) {
let preCode =
type === "city"
? this.getAreaCode(this.currentProvince).slice(
0,
2
)
: y.slice(0, 2);
code = this.getAreaCodeByPreCode(name, preCode);
}
if (!code || y.slice(0, 2) !== code.slice(0, 2)) {
continue;
} else {
return code;
}
} else {
return y;
}
}
}
}
},
getCodeValue(code) {
for (let x in this.districts) {
for (let y in this.districts[x]) {
if (code === parseInt(y)) {
return this.districts[x][y];
}
}
}
},
getDistricts(code = DEFAULT_CODE) {
return this.districts[code] || [];
},
determineValue(type, currentValue, placeholderValue, check = "") {
if (currentValue === placeholderValue) {
return [];
} else {
return this.getDistricts(this.getAreaCode(currentValue, check, type));
}
},
determineType(value) {
if (typeof value === "number") {
return this.getCodeValue(value);
}
return value;
},
cleanList(name) {
this[name] = [];
},
isDirectCity(province, city) {
if (province && city) {
return (
this.determineType(this.province) === this.determineType(this.city)
);
}
return false;
},
},
};
</script>
<style lang="scss">
.distpicker-address-wrapper {
color: #9caebf;
select {
padding: 0.5rem 0.75rem;
height: 40px;
font-size: 1rem;
line-height: 1.25;
color: #464a4c;
background-color: #fff;
background-image: none;
-webkit-background-clip: padding-box;
background-clip: padding-box;
border: 1px solid rgba(0, 0, 0, 0.15);
border-radius: 0.25rem;
-webkit-transition: border-color ease-in-out 0.15s,
-webkit-box-shadow ease-in-out 0.15s;
transition: border-color ease-in-out 0.15s, -webkit-box-shadow ease-in-out 0.15s;
-o-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s,
-webkit-box-shadow ease-in-out 0.15s;
option {
font-weight: normal;
display: block;
white-space: pre;
min-height: 1.2em;
padding: 0px 2px 1px;
}
}
ul {
margin: 0;
padding: 0;
li {
list-style: none;
}
}
.address-header {
background-color: #fff;
ul {
display: flex;
justify-content: space-around;
align-items: stretch;
li {
display: inline-block;
padding: 10px 10px 7px;
&.active {
border-bottom: #52697f solid 3px;
color: #52697f;
}
}
}
}
.address-container {
background-color: #fff;
ul {
height: 100%;
overflow: auto;
li {
padding: 8px 10px;
border-top: 1px solid #f6f6f6;
&.active {
color: #52697f;
}
}
}
}
}
.disabled-color {
background: #f8f8f8;
}
</style>