Vue 여러 지역 선택 구성 요소 작성

19487 단어 Vue선택 하 다.
효과 도 보기:
효과 도
这里写图片描述
기능 점:
4.567917.도 시 를 제한 하지 않 고 지역 을 제한 하지 않 는 다.
4.567917.지역 을 한꺼번에 많이 선택 하면 모든 지역 을 선택 하면 자동 으로 무제 한 지역 으로 전 환 됩 니 다.4.567918.
4.567917.데이터 이동 화살표 의 판단..데 이 터 를 선택해 야 해당 하 는 단 추 를 누 를 수 있 습 니 다
  • 선택 한 위치의 데이터 가 호출 에 동기 화 되 는 곳 은 물론 외부 에서 도 들 어 올 수 있 습 니 다.(추가 전송,편집 의존 전송 재 조합)
  • 4.567917.화살 표 는 iconformant 입 니 다.외부 전송 을 지원 합 니 다.기본 값 은 제 쪽 cdn 입 니 다.
    !!!이것 은 독립 된 구성 요소 입 니 다.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 개 버 전)을 넘 어 뜨 렸 습 니 다.모두 생각 이 맞 고 정리 되 지 않 았 습 니 다.쓰 고 있 으 면 쓰 지 못 했 습 니 다.
    이 구성 요소 의 현재 기능 은 제 가 원 하 는 것 을 만족 시 키 는 것 입 니 다.더 좋 은 실현 방식 이 있 으 면 메 시 지 를 남 길 수 있 습 니 다.
    이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

    좋은 웹페이지 즐겨찾기