Vue 여러 지역 선택 구성 요소 작성
효과 도
기능 점:
4.567917.도 시 를 제한 하지 않 고 지역 을 제한 하지 않 는 다.
4.567917.지역 을 한꺼번에 많이 선택 하면 모든 지역 을 선택 하면 자동 으로 무제 한 지역 으로 전 환 됩 니 다.4.567918.
4.567917.데이터 이동 화살표 의 판단..데 이 터 를 선택해 야 해당 하 는 단 추 를 누 를 수 있 습 니 다
!!!이것 은 독립 된 구성 요소 입 니 다.css 예비 처 리 는 scss 입 니 다.
쓰 는 과정 에서 발생 하 는 문제:
이 기능 은 여러 번 성 도 시 를 전환 해 야 하기 때문에 저 는 모든 데 이 터 를 한꺼번에 끌 어 와 서 localstorage 에 저장 합 니 다.그렇지 않 으 면 인터페이스 요청 횟수 가 너무 많 습 니 다.
처음에 도시 와 지역 에 제한 이 없 었 습 니 다.JSON(JSON 재 구성)에 합병 하고 싶 었 습 니 다.그런데 처리 번 거 로 움 을 줄 일 수 있 지만 데이터 가 더 복잡 해 졌 습 니 다.유지 하기 가 쉽 지 않 고 다른 구성 요소 가 이 JSON 을 호출 하 는 곳 도 있 습 니 다.(예 를 들 어 다른 구성 요소 가 주소 가 있 는 3 급 연동 도 이 JSON 에 의존 합 니 다)
*또 하 나 는 양쪽 에 제한 이 없 는 것 을 고려 해 야 할 때 존재 할 수 없 는 데 이 터 를 제거 해 야 한 다 는 것 이다.예 를 들 어 도 시 를 제한 하지 않 으 면 이 성의 모든 도 시 를 없 애 야 하고 제한 하지 않 는 지역 도 비슷 하 다.
좌우 양쪽 데 이 터 를 쓰 는 대비 가 가장 징 그 러 운 데 왜 그렇게 말 합 니까?
*왼쪽 3 단 계 는 연결 되 어 있 고 모든 하위 항목 은 자신의 id 와 name 이 있 습 니 다.선택 한 것 은 조합 한 것 입 니 다(GIF 그림 보기).중간 은 중간 에 선 을 그 어 분리 되 어 있 습 니 다.이것 은 밀어 내기 와 출시 에 있어 서 옮 겨 다 니 고 비교 합 니 다.
*우리 쪽 백 엔 드 사내 들 은 제한 되 지 않 는 id 가 모두 0(도시 나 지역)이 라 고 말 하기 때문에 이것 은 스스로 조합 해 야 한다.마지막 으로 동적 그림 의 ID 는 백 엔 드 에서 받 아들 이 는 것 이 고 여러 지역 에서 문자열 로 연결 하 는 것 이다.'3-13-2,2-44-3,4-0-0'이런 것 을 백 엔 드 에 제출 하 는 것 이다.
연동 JSON 데이터 형식
regionName:항목 이름
regionId:항목 의 ID
child:하위 항목 포함 여부
regionName,regionId,child 를 비 추 는 props 를 쓰 려 고 했 습 니 다.그러나 역할 이 크 지 않 은 것 같 아 쓰 지 않 았 다.
뭐 공부 해요?
1:배열 의 비교,배열 의 옮 겨 다 니 기,배열 의 조합 과 응답 판단
2:vue 내 장 된 명령 사용
3:구성 요소 기능 의 세부 사항 을 고려 하여 지역 을 제한 하지 않 습 니 다.이 모든 단 추 는 어떤 상황 에서 클릭 할 수 있 습 니까?
4:데 이 터 를 비 운 후 각 상태의 회복 과 리 셋 등
코드
manyAreaSelect.vue
<template>
<div class="manyAreaSelect">
<div class="item">
<div class="item-title">
<span> </span>
</div>
<div class="item-content">
<ul>
<li v-for="(item,index) in chinaArea" :class="item.selected?'active':''" :key="index" @click="getCityList(item)">{{item.regionName}}</li>
</ul>
</div>
<div class="item-footer"></div>
</div>
<div class="item">
<div class="item-title">
<span> </span>
</div>
<div class="item-content">
<ul v-show="cityList.length===0">
<li>
<< </li>
</ul>
<ul v-show="!notLimitButton.notLimitCity &&cityList.length!==0">
<li v-for="(item,index) in cityList" :class="item.selected ? 'active':''" :key="index" @click="getDistricList(item)">{{item.regionName}}</li>
</ul>
</div>
<div class="item-footer">
<button class="button" :class="notLimitButton.notLimitCity?'success':''" @click="cityNotLitmit({regionName:' ',regionId:'0'})" size="mini" :disabled="!selectItem.province.regionName"> </button>
</div>
</div>
<div class="item">
<div class="item-title">
<span> </span>
</div>
<div class="item-content">
<ul v-show="districList.length===0">
<li>
<< </li>
</ul>
<ul v-show="!notLimitButton.notLimitCity && !notLimitButton.notLimitDistrict && districList.length!==0">
<li v-for="(item,index) in districList" :class="item.selected?'active':''" :key="index" @click="getAreaCombineID(item)">{{item.regionName}}</li>
</ul>
</div>
<div class="item-footer">
<button class="button" :class="notLimitButton.notLimitDistrict ?'success':''" @click="districNotLitmit({regionName:' ',regionId:'0'})" :disabled="!selectItem.city.regionName ||!selectItem.province.regionName || notLimitButton.notLimitCity "> </button>
</div>
</div>
<div class="trangle">
<div class="trangle-wrap">
<div class="left">
<button class="button" @click="transferToRight" :disabled="direactionStatusToRight">
<i :class="this.iconDirection.right"></i>
</button>
</div>
<div class="right">
<button class="button" @click="transferToLeft" :disabled="direactionStatusToLeft">
<i :class="this.iconDirection.left"></i>
</button>
</div>
</div>
</div>
<div class=" item ">
<div class="item-title ">
<span> </span>
</div>
<div class="item-content ">
<ul class="selectedContent">
<li v-for="(item,index) in selectedList" :class="item.selected?'active':''" :key="index" @click="selectedAreaSingle(item)">{{item.regionName}}</li>
</ul>
</div>
<div class="item-footer">
<button class="button" @click="selectedAllArea()" :disabled="rightDataList.length=== 0" :class="selectedAllButtonStatus?'success':''">{{selectedAllButtonStatus?' ':' '}}</button>
</div>
</div>
</div>
</template>
<script>
import _ from 'lodash';
export default {
name: 'manyAreaSelect',
data: function () {
return {
chinaArea: JSON.parse(window.localStorage.getItem('chinaArea')) || [], // JSON
notLimitButton: {
notLimitCity: false, //
notLimitDistrict: false, //
},
selectedAllButtonStatus: false, //
selectItem: {
province: {},
city: {},
distric: {}
},
cityList: [], //
districList: [], //
rightDataList: [], //
rightData: [], //
leftData: [], //
}
},
props: {
selectedData: {
type: [String, Object, Array]
},
iconDirection: {
type: Object,
default: function () { //
return {
left: 'fzicon fz-ad-you',
right: 'fzicon fz-ad-right'
}
}
}
},
computed: {
selectedList () { //
if (this.selectedData && this.selectedData !== '') {
this.rightDataList = this.selectedData;
return this.rightDataList;
} else {
return this.rightDataList;
}
},
direactionStatusToRight () { //
if (this.notLimitButton.notLimitCity || this.notLimitButton.notLimitDistrict) {
if (this.notLimitButton.notLimitCity) {
this.removeAllSelected(this.cityList);
this.removeAllSelected(this.districList);
return false;
} else {
if (this.notLimitButton.notLimitDistrict) {
this.removeAllSelected(this.districList);
return false;
}
}
return false;
} else {
if (this.selectItem.distric.regionName) {
return false;
}
return true;
}
},
direactionStatusToLeft () { //
if (this.rightData.length === 0) {
return true
} else {
return false
}
}
},
methods: {
mapSelect (list, value, type) { //
if (type) {
return list.map(pitem => {
if (pitem.regionId === value.regionId) {
if (value.selected && value.selected === true) {
this.$delete(pitem, 'selected');
} else {
this.$set(pitem, 'selected', true)
}
}
})
} else {
return list.map(pitem => {
if (pitem.regionId === value.regionId) {
if (value.selected && value.selected === true) {
this.$delete(pitem, 'selected');
} else {
this.$set(pitem, 'selected', true)
}
} else {
this.$delete(pitem, 'selected');
}
})
}
},
resetToDefault () {
this.leftData = []; //
this.notLimitButton = { //
notLimitCity: false, //
notLimitDistrict: false, //
};
this.selectItem.city = {};
this.selectItem.distric = {}
this.removeAllSelected(this.cityList); //
this.removeAllSelected(this.districList); //
this.cityList = [];
this.districList = [];
},
getCityList (item) {
this.resetToDefault();
if (item) {
this.cityList = item.child; //
this.selectItem.province = item; //
this.mapSelect(this.chinaArea, item); // ,
}
},
getDistricList (item) {
this.leftData = []; //
this.notLimitButton.notLimitDistrict = false; //
this.removeAllSelected(this.districList); //
this.selectItem.distric = {};
this.districList = [];
if (item) {
this.districList = item.child; //
this.selectItem.city = item; //
this.mapSelect(this.cityList, item); // ,
}
},
getAreaCombineID (item) { // ID
if (item) {
this.selectItem.distric = item;
this.mapSelect(this.districList, item, 'manySelect'); // ,
this.leftData.push({
regionName: this.selectItem.province.regionName + '-' + this.selectItem.city.regionName + '-' + item.regionName,
regionId: this.selectItem.province.regionId + '-' + this.selectItem.city.regionId + '-' + item.regionId
})
this.leftData = _.uniqBy(this.leftData, 'regionId');
if (this.leftData.length === this.districList.length) {
this.leftData = [];
this.notLimitButton.notLimitDistrict = true; //
this.leftData.push({
regionName: this.selectItem.province.regionName + '-' + this.selectItem.city.regionName + '- ',
regionId: this.selectItem.province.regionId + '-' + this.selectItem.city.regionId + '-0'
})
}
}
},
cityNotLitmit (item) { //
this.leftData = []; //
this.notLimitButton.notLimitCity = !this.notLimitButton.notLimitCity; //
this.leftData.push({
regionName: this.selectItem.province.regionName + '- - ',
regionId: this.selectItem.province.regionId + '-0-0'
})
},
districNotLitmit (item) { //
this.leftData = []; //
this.notLimitButton.notLimitDistrict = !this.notLimitButton.notLimitDistrict; //
this.leftData.push({
regionName: this.selectItem.province.regionName + '-' + this.selectItem.city.regionName + '- ',
regionId: this.selectItem.province.regionId + '-' + this.selectItem.city.regionId + '-0'
})
},
transferToRight () { //
if (this.leftData && this.leftData.length !== 0) {
if (this.leftData.length === 1) { // 1,
let limitId = this.leftData[0].regionId.split('-'); // ,
this.rightDataList.map(item => {
let id = item.regionId.split('-');
if (limitId[0] === id[0]) {
if (limitId[1] === '0') { //
this.rightDataList = this.rightDataList.filter(ritem => {
let rid = ritem.regionId.split('-');
if (limitId[0] !== rid[0]) {
return ritem;
}
})
} else {
if (limitId[2] === '0') { //
this.rightDataList = this.rightDataList.filter(ritem => {
let rid = ritem.regionId.split('-');
if ((limitId[0] === rid[0] && limitId[1] === rid[1])) {
if (ritem[2] === '0') {
return ritem;
}
} else {
if (limitId[0] !== rid[0] || limitId[1] !== rid[1]) {
return ritem;
}
}
})
} else {
this.rightDataList = this.rightDataList.filter(ritem => {
let rid = ritem.regionId.split('-');
if (limitId[0] === rid[0]) {
if (limitId[1] === rid[1]) {
if (!(rid[2] === '0')) {
return ritem;
}
} else {
if (!(rid[1] === '0')) {
return ritem
}
}
} else {
return ritem
}
})
}
}
}
})
} else {
let limitId = this.leftData[0].regionId.split('-'); // ,
this.rightDataList = this.rightDataList.filter(ritem => {
let rid = ritem.regionId.split('-');
if (limitId[0] === rid[0]) {
if (limitId[1] === rid[1]) {
if (!(rid[2] === '0')) {
return ritem;
}
} else {
if (!(rid[1] === '0')) {
return ritem
}
}
} else {
return ritem
}
})
}
this.leftData.map(item => {
this.rightDataList.push(item);
})
this.rightDataList = _.uniqBy(this.rightDataList, 'regionId');
this.resetToDefault();
}
},
selectedAreaSingle (item) { //
if (item) {
this.rightData = [];
this.mapSelect(this.rightDataList, item, 'manySelect'); // ,
this.rightDataList.map(item => {
if (item.selected) {
this.rightData.push(item)
}
})
}
},
selectedAllArea () { //
if (this.selectedAllButtonStatus) {
this.removeAllSelected(this.rightDataList);
this.rightData = [];
} else {
this.rightDataList.map(item => this.$set(item, 'selected', true));
this.rightData = this.rightDataList;
}
this.selectedAllButtonStatus = !this.selectedAllButtonStatus;
},
transferToLeft () { //
if (this.rightData && this.rightData.length !== 0) {
this.rightDataList = this.rightDataList.filter(item => {
if (!item.selected) {
return item;
}
})
this.rightData = [];
}
},
removeAllSelected (list) { //
list.map(item => this.$delete(item, 'selected'));
}
},
watch: {
'rightDataList' (newValue, oldValue) { //
if (newValue.length !== this.rightData.length) {
this.selectedAllButtonStatus = false;
} else {
if (newValue.length === 0) {
this.selectedAllButtonStatus = false;
} else {
this.selectedAllButtonStatus = true;
}
}
this.$emit('update:selectedData', newValue);
}
}
}
</script>
<style scoped lang="scss">
ul {
padding: 0;
margin: 0;
max-height: 100%;
overflow-y: auto;
li {
cursor: pointer;
text-align: center;
padding: 5px;
&.active,
&:hover {
background: #e4e8f1;
color: #48576a;
}
}
}
.manyAreaSelect {
position: relative;
z-index: 2005;
.item {
border: 1px solid #d1dbe5;
background: #fff;
box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04);
display: inline-block;
vertical-align: middle;
min-width: 180px;
box-sizing: border-box;
position: relative;
height: 100%;
min-height: 260px;
}
.item-title {
height: 36px;
line-height: 36px;
background: #fbfdff;
margin: 0;
border-bottom: 1px solid #d1dbe5;
box-sizing: border-box;
color: #1f2d3d;
text-align: center;
}
.trangle {
background: transparent;
display: inline-block;
vertical-align: middle;
width: 40px;
box-sizing: border-box;
height: 100%;
position: relative;
.trangle-wrap {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.left,
.right {
margin: 10px 5px;
}
;
}
.item-content {
font-size: 13px;
height: 190px;
padding: 8px 2px;
}
.item-footer {
padding: 5px 0;
height: 40px;
text-align: center;
}
}
.selectedContent {
li {
text-align: left;
padding-left: 25px;
}
}
.button {
display: inline-block;
line-height: 1;
white-space: nowrap;
cursor: pointer;
background: #fff;
border: 1px solid #c4c4c4;
color: #1f2d3d;
margin: 0;
border-radius: 4px;
padding: 4px;
font-size: 12px;
border-radius: 4px;
-webkit-appearance: button;
outline: none;
&.success {
background: #42d885;
border-color: #42d885;
color: #fff;
}
&:disabled {
color: #bfcbd9;
cursor: not-allowed;
background-image: none;
background-color: #eef1f6;
border-color: #d1dbe5;
}
}
</style>
사용법
<!--selectedData .sync 2.3 -->
<!-- iconDirection iconfont,Object-->
<many-area-select :selectedData.sync="manyAreaValue"></many-area-select>
총결산이 조립품 은 용광로 에서 나 와 오랫동안 고생 했다.
쓰 는 과정 에서 3 판(3 일 3 개 버 전)을 넘 어 뜨 렸 습 니 다.모두 생각 이 맞 고 정리 되 지 않 았 습 니 다.쓰 고 있 으 면 쓰 지 못 했 습 니 다.
이 구성 요소 의 현재 기능 은 제 가 원 하 는 것 을 만족 시 키 는 것 입 니 다.더 좋 은 실현 방식 이 있 으 면 메 시 지 를 남 길 수 있 습 니 다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Vue Render 함수로 DOM 노드 코드 인스턴스 만들기render에서createElement 함수를 사용하여 DOM 노드를 만드는 것은 직관적이지 않지만 일부 독립 구성 요소의 디자인에서 특수한 수요를 충족시킬 수 있습니다.간단한 렌더링 예는 다음과 같습니다. 또한 v...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.