ant-design-vue 에서 tree 추가 삭제 작업 방법

1.배경 사용
새 프로젝트 에 서 는 ant-design-vue 구성 요소 라 이브 러 리 를 사 용 했 습 니 다.이 구성 요소 라 이브 러 리 는 완전히 기본 데이터 가 양 방향 으로 연결 되 는 모드 로 구현 되 었 습 니 다.폼 구성 요소 만 소량의 방법 을 제공 합 니 다.따라서 ant-design-vue 을 사용 할 때 데이터 변경 측면 에서 UI 디 스 플레이 효 과 를 전환 해 야 합 니 다.그러나 트 리 제어 장치 a-tree 의 사용 에 있어 서 데이터 구동 만 고려 하면 체험 효과 가 좋 지 않 습 니 다.
2.현재 통 증
공식 도움말 문 서 를 읽 고 트 리 컨트롤 데이터 바 인 딩 을 해 야 합 니 다.데이터 구 조 를 children,title,key 속성 을 포함 하 는 큰 대상 으로 만들어 야 합 니 다.이러한 대상 은 백 엔 드 를 통 해 이러한 json 대상 을 구성 하거나 백 엔 드 를 통 해 전단 에 json 배열 을 만들어 야 합 니 다.전단 근 은 상하 관계 에 따라 이러한 트 리 대상 을 구축 합 니 다.데이터 바 인 딩 이 잘 되 어 있 습 니 다.우리 가 원 하 는 UI 효 과 를 성공 적 으로 표현 할 수 있 습 니 다.그런데 아 픈 점 은 어디 에 있 습 니까?
  • 트 리 로 딩 에 성공 한 후에 저 는 현재 트 리 에 같은 등급 과 하급 노드 를 추가 하려 고 합 니 다.
  • 트 리 로드 에 성공 한 후에 저 는 임의의 트 리 노드 를 어떻게 조작 해 야 하 는 지 수정 하려 고 합 니 다.
  • 트 리 로드 에 성공 한 후,나 는 트 리 노드 를 삭제 하려 면 어떻게 조작 해 야 합 니까(삭제)
  • 이상 의 작업 은 트 리 컨트롤 을 다시 불 러 오지 않 는 조건 에서 이 루어 져 야 합 니 다.테스트 를 통 해 세 가지 실행 가능 한 방안 을 정리 하 였 습 니 다.
  • 데이터 구동
  • 역할 영역 슬롯
  • 노드 사건

  • 3.데이터 구동 은 트 리 노드 의 삭제 와 수정 을 실현 한다.
    도움말 문서 에서 selectedKeys(.sync) 속성 을 찾 을 수 있 습 니 다.sync 은 이 속성 이 양 방향 동작 을 지원 한 다 는 것 을 표시 합 니 다.그러나 여기 서 얻 은 것 은 key 값 일 뿐 필요 한 바 인 딩 대상 이 아 닙 니 다.따라서 이 key 값 을 통 해 이 대상 을 찾 아야 합 니 다.이 대상 을 찾 아야 하 는 것 은 상당히 역 겨 운 일 입 니 다.
  • 백 엔 드 가 구 축 된 데이터 로 되 돌아 오 려 면 이 트 리 데 이 터 를 옮 겨 다 니 며 이 key 값 과 대응 하 는 대상 을 찾 아야 합 니 다.제 가 생각 할 수 있 는 것 은 맨 위 노드 를 통 해 재 귀적 으로 찾 는 것 입 니 다.그러나 컨트롤 이 모두 렌 더 링 되 었 고 모든 노드 의 데 이 터 를 알 고 있 습 니 다.제 가 왜 다시 찾 아야 합 니까?
  • 백 엔 드 가 하나의 배열 로 되 돌아 오 면 이 부분 데 이 터 를 다시 구축 해 야 한 다 는 언급 이 있 었 습 니 다.이렇게 대상 을 찾 으 면 두 가지 상황 으로 나 뉜 다.
  • a.목록 데이터 와 구축 후 트 리 대상 이 복 제 된 방식 을 사용한다 면 목록 의 대상 주소 와 트 리 의 같은 key 값 대상 의 주소 가 다 릅 니 다.방법 1 을 통 해 재 구성 한 트 리 데 이 터 를 옮 겨 다 녀 야 합 니 다.
    b.목록 데이터 의 대상 과 구축 후 대응 하 는 노드 가 같은 대상 주소 라면 이 목록 데 이 터 를 직접 찾 아 대응 하 는 대상 을 얻 을 수 있 습 니 다.
    그래서 징 그 러 운 부분 은 바로 나 무 를 구축 하 는 것 이다.나 는 이 나 무 를 옮 겨 다 니 며 특정한 노드 를 찾 거나 방안 b 라 는 공간 으로 시간 을 바 꾸 는 방법 을 사용 해 야 한다.
    여기 서 우 리 는 데이터 가 이미 트 리 로 구 축 된 데이터 형식 이 라 고 가정 합 니 다.데이터 구동 을 실현 하 는 가장 중요 한 임 무 는 두 가지 핵심 방법 을 완성 해 야 합 니 다.
  • 현재 노드 key 값 에 따라 노드 대상 getTreeDataByKey
  • 을 찾 습 니 다.
  • 현재 노드 key 값 에 따라 부모 급 노드 children 집합 getTreeParentChilds
  • 두 가지 방법 코드 는 각각 다음 과 같다.
    
    // author:herbert date:20201024 qq:464884492
    //   key           
    getTreeDataByKey(childs = [], findKey) {
     let finditem = null;
     for (let i = 0, len = childs.length; i < len; i++) {
      let item = childs[i]
      if (item.key !== findKey && item.children && item.children.length > 0) {
      finditem = this.getTreeDataByKey(item.children, findKey)
      }
      if (item.key == findKey) {
      finditem = item
      }
      if (finditem != null) {
      break
      }
     }
     return finditem
     },
    // author:herbert date:20201024 qq:464884492
    //   key      children  
    getTreeParentChilds(childs = [], findKey) {
     let parentChilds = []
     for (let i = 0, len = childs.length; i < len; i++) {
      let item = childs[i]
      if (item.key !== findKey && item.children && item.children.length > 0) {
      parentChilds = this.getTreeParentChilds(item.children, findKey)
      }
      if (item.key == findKey) {
      parentChilds = childs
      }
      if (parentChilds.length > 0) {
      break
      }
     }
     return parentChilds
    },
    3.1 동급 노드 추가
    같은 등급 의 노드 를 추가 하려 면 새로 추 가 된 데 이 터 를 현재 선택 한 노드 의 부모 급 children 배열 에 추가 해 야 합 니 다.따라서 노드 를 추가 하 는 난점 은 현재 선택 한 노드 의 바 인 딩 대상 의 부모 급 대상 을 어떻게 찾 는 지 입 니 다.페이지 코드 는 다음 과 같 습 니 다.
    
    <!-- author:herbert date:20201030 qq:464884492-->
    <a-card style="width: 450px;height:550px;float: left;">
    <div slot="title">
     <h2>    (     )<span style="color:blue">@herbert</span></h2>
     <div>
     <a-button @click="dataDriveAddSame">    </a-button>
     <a-divider type="vertical" />
     <a-button @click="dataDriveAddSub">    </a-button>
     <a-divider type="vertical" />
     <a-button @click="dataDriveModify">  </a-button>
     <a-divider type="vertical" />
     <a-button @click="dataDriveDelete">  </a-button>
     </div>
    </div>
    <a-tree :tree-data="treeData" :defaultExpandAll="true"
      :selectedKeys.sync="selectKeys" showLine />
    <img src="./assets/gamelogo.png" width="100%" style="margin-top:20px" />
    </a-card>
    페이지 코드 에서 알 수 있 듯 이 트 리 에 두 개의 속성 tree-data,selectedKeys 이 연결 되 어 있 습 니 다.여기 서 우 리 는 selectedKeys 바 인 딩 값 을 통 해 트 리 가 현재 선택 한 key 값 을 얻 을 수 있 습 니 다.그리고 사용 방법 getTreeParentChilds 을 사용 하면 같은 등급 의 추 가 를 실현 할 수 있 습 니 다.따라서 사용 하 는 dataDriveAddSame 코드 에 대해 다음 과 같이 실현 할 수 있 습 니 다.
    
    // author:herbert date:20201030 qq:464884492
    dataDriveAddSame() {
     let parentChilds = this.getTreeParentChilds(this.treeData, this.selectKeys[0])
     parentChilds.forEach(item => console.log(item.title));
     parentChilds.push({
      title: '    ,       ',
      key: new Date().getTime()
     })
    },
    3.2 다음 레벨 추가
    위의 기초 가 있 으 면 다음 단 계 를 추가 하 는 것 이 간단 합 니 다.유일 하 게 주의해 야 할 것 은 대상 children 속성 이 존재 하지 않 을 수 있 습 니 다.이때$set 방식 으로 속성 dataDriveAddSub 코드 를 추가 하여 다음 과 같이 실현 해 야 합 니 다.
    
    // author:herbert date:20201030 qq:464884492
    dataDriveAddSub() {
     let selectItem = this.getTreeDataByKey(this.treeData, this.selectKeys[0])
     if (!selectItem.children) {
      this.$set(selectItem, "children", [])
     }
     selectItem.children.push({
      title:     ,     ,
      key: new Date().getTime()
     })
     this.$forceUpdate()
     },
    3.3 수정 노드
    바 인 딩 대상 을 얻 을 수 있 고 노드 값 을 수정 하 는 것 도 간단 해 졌 습 니 다.하급 자 를 추가 하 는 것 과 같이 getTreeDataByKey 을 사용 하여 현재 대상 을 얻 은 다음 에 직접 값 을 수정 하면 됩 니 다.dataDriveModify 코드 는 다음 과 같 습 니 다.
    
    // author:herbert date:20201030 qq:464884492
    dataDriveModify() {
     let selectItem = this.getTreeDataByKey(this.treeData, this.selectKeys[0])
     selectItem.title = '       ,        '
    },
    3.4 노드 삭제
    같은 등급 을 추가 하 는 것 과 마찬가지 로 부모 급 노드 children 배열 을 찾 아야 합 니 다.현재 대상 이 부모 급 배열 에 대응 하 는 색인 입 니 다.dataDriveDelete 코드 는 다음 과 같 습 니 다.
    
    // author:herbert date:20201030 qq:464884492
    dataDriveDelete() {
     let parentChilds = this.getTreeParentChilds(this.treeData, this.selectKeys[0])
     let delIndex = parentChilds.findIndex(item => item.key == this.selectKeys[0])
     parentChilds.splice(delIndex, 1)
    },
    4.슬롯 방식 으로 트 리 노드 추가 삭제ant-tree api 에서 트 리 노드 속성 title 유형 은 문자열 일 수도 있 고 슬롯 일 수도 있 습 니 다.
    
    <!-- author:herbert date:20201030 qq:464884492-->
    <a-card style="width: 450px;height:550px;float: left;">
    <div slot="title">
     <h2>    (       )</h2>
     <div>
            ,           <span style="color:blue">@    </span>
     </div>
    </div>
    <a-tree ref="tree1" :tree-data="treeData1" :defaultExpandAll="true" :selectedKeys.sync="selectKeys1" showLine blockNode>
     <template v-slot:title="nodeData">
     <span>{{nodeData.title}}</span>
     <a-button-group style="float:right">
      <a-button size="small" @click="slotAddSame(nodeData)" icon="plus-circle" title="    "></a-button>
      <a-button size="small" @click="slotAddSub(nodeData)" icon="share-alt" title="    "></a-button>
      <a-button size="small" @click="slotModify(nodeData)" icon="form" title="  "></a-button>
      <a-button size="small" @click="slotDelete(nodeData)" icon="close-circle" title="  "></a-button>
     </a-button-group>
     </template>
    </a-tree>
    <img src="./assets/gamelogo.png" width="100%" style="margin-top:20px" />
    </a-card>
    4.1 동급 추가
    슬롯 방식 으로 대상 을 얻 을 수 있 습 니 다.사실은 현재 노드 에 대응 하 는 속성 값 이 고 얕 은 복사 본 입 니 다.소스 코드 string|slot|slot-scope 중의 vc-tree\src\TreeNode.jsx 에서 다음 과 같은 코드 를 찾 을 수 있 습 니 다.
    
    const currentTitle = title;
    let $title = currentTitle ? (
     <span class={`${prefixCls}-title`}>
     {typeof currentTitle === 'function'
      ? currentTitle({ ...this.$props, ...this.$props.dataRef }, h)
      : currentTitle}
     </span>
    ) : (
     <span class={`${prefixCls}-title`}>{defaultTitle}</span>
    );
    이 코드 에서 dataRef 를 볼 수 있 습 니 다.그러나 공식 도움말 문서 에 서 는 이러한 속성 에 대한 소개 가 전혀 없습니다.소스 코드 를 보 려 는 학생 에 게 주 는 복지 인지 아 닌 지 모 르 겠 습 니 다.코드 차원 에서 보 든 디 버 깅 결 과 를 보 든 역할 영역 을 통 해 얻 은 대상 은 부모 속성 이 없 기 때문에 같은 등급 의 추 가 를 실현 할 수 없습니다.renderSelector 코드 는 다음 과 같 습 니 다.
    
    // author:herbert date:20201030 qq:464884492
    slotAddSame(nodeItem) {
    console.log(nodeItem)
    this.$warn({ content: "      ,       ,    !    ,       " })
    },
    4.2 다음 레벨 추가
    대상 을 얻 었 지만 던 전 하나 입 니 다.그래서 slotAddSame 을 설치 해도 소 용 없습니다!!
    
    // author:herbert date:20201030 qq:464884492
    slotAddSub(nodeItem) {
    if (!nodeItem.children) {
     console.log('         ,         ')
     this.$set(nodeItem, "children", [])
    }
    nodeItem.children.push({
     title: this.addSubTitle,
     key: new Date().getTime(),
     scopedSlots: { title: 'title' },
     children: []
    })
    },
    4.3 수정 노드
    수정 도 마찬가지 로 실현 할 수 없 지만 위 에 children 이 언급 되 어 있 습 니 다.여기 서 간단하게 사용 하면 title 값 을 수정 할 수 있 습 니 다.
    
    // author:herbert date:20201030 qq:464884492
    slotModify(nodeItem) {
     console.log(nodeItem)
     console.log('nodeItem     Treenode           ,    Title   ')
     nodeItem.title = '         ,         '
     //       dataRef   
     nodeItem.dataRef.title = nodeItem.title
     },
    4.4 노드 삭제
    삭제 도 안 되 는 게 분명 해.
    
    // author:herbert date:20201030 qq:464884492
    slodDelete(nodeItem) {
    console.log(nodeItem)
    this.$warn({ content: "      ,       ,    !   ,         " })
    delete nodeItem.dataRef
    },
    5.트 리 이벤트 결합 dataRef 구현
    위 에 서 는 슬롯 방식 을 통 해 수정 기능 만 실 현 했 습 니 다.특히 실 망 스 럽 습 니 다.하지만 디자인 의 측면 에서 볼 때 대상 에 게 사용자 정의 렌 더 링 을 도와 주 는 것 만으로 도 좋 습 니 다.공식 Api 를 계속 읽 고 사건 중의 dataRef 사건 이 제공 하 는 값 을 찾 아 우리 에 게 큰 발휘 공간 을 주 었 습 니 다.얼마나 큰 지,원본 코드 를 찾 아 보 겠 습 니 다.우선 select 이벤트 코드 를 찾 았 습 니 다.select 파일 에서 구체 적 인 코드 는 다음 과 같 습 니 다.
    
    onSelect(e) {
     if (this.isDisabled()) return;
     const {
      vcTree: { onNodeSelect },
     } = this;
     e.preventDefault();
     onNodeSelect(e, this);
    },
    코드 에서 볼 수 있 듯 이 components\vc-tree\src\TreeNode.jsx onSelect 는 TreeNode 중의 onNode Selected 방법 을 호출 하 는 것 입 니 다.Tree 까지 해당 하 는 코드 를 찾 으 면 다음 과 같 습 니 다.
    
    onNodeSelect(e, treeNode) {
     let { _selectedKeys: selectedKeys } = this.$data;
     const { _keyEntities: keyEntities } = this.$data;
     const { multiple } = this.$props;
     const { selected, eventKey } = getOptionProps(treeNode);
     const targetSelected = !selected;
     // Update selected keys
     if (!targetSelected) {
      selectedKeys = arrDel(selectedKeys, eventKey);
     } else if (!multiple) {
      selectedKeys = [eventKey];
     } else {
      selectedKeys = arrAdd(selectedKeys, eventKey);
     }
    
     // [Legacy] Not found related usage in doc or upper libs
     const selectedNodes = selectedKeys
      .map(key => {
      const entity = keyEntities.get(key);
      if (!entity) return null;
    
      return entity.node;
      })
      .filter(node => node);
    
     this.setUncontrolledState({ _selectedKeys: selectedKeys });
    
     const eventObj = {
      event: 'select',
      selected: targetSelected,
      node: treeNode,
      selectedNodes,
      nativeEvent: e,
     };
     this.__emit('update:selectedKeys', selectedKeys);
     this.__emit('select', selectedKeys, eventObj);
    },
    두 가지 방법 을 결합 하면 Tree 노드 eventObj 대상 에서 알 수 있 듯 이 구성 요소 components\vc-tree\src\Tree.jsx 은 Tree 노드 를 TreeNode 캐 시 데이터 select 과 실제 적 인 TreeNode 노드 selectedNodes 을 호출 자 에 게 제공 할 뿐만 아니 라 이 node 속성 이 있 으 면 우 리 는 해당 노드 의 상하 관 계 를 얻 을 수 있다.
    다음은 이 재 도움말 문서 에 나타 나 지 않 은 node 이 어떤 귀신 인지 말씀 드 리 겠 습 니 다.
    파일 dataRef 이 대응 하 는 components\tree\Tree.jsx 함수 에서 우 리 는 Tree 가 vc-tree 구성 요소 에 render 속성 을 전달 해 야 한 다 는 것 을 알 수 있 습 니 다.우리 가 최종 적 으로 사용 하 는 전달 노드 데이터 도 이 속성 명 입 니 다.두 단락 의 관건 코드 는 다음 과 같 습 니 다.
    
    render(){
     ...
     let treeData = props.treeData || treeNodes;
     if (treeData) {
      treeData = this.updateTreeData(treeData);
     }
     ...
     if (treeData) {
      vcTreeProps.props.treeData = treeData;
     }
     return <VcTree {...vcTreeProps} />;
    }
    위의 코드 를 통 해 알 수 있 듯 이 구성 요소 의 바 텀 호출 방법 treeData 은 우리 가 들 어 온 데 이 터 를 처리 했다.이 방법 은 관건 적 인 코드 가 다음 과 같다.
    
    updateTreeData(treeData) {
     const { $slots, $scopedSlots } = this;
     const defaultFields = { children: 'children', title: 'title', key: 'key' };
     const replaceFields = { ...defaultFields, ...this.$props.replaceFields };
     return treeData.map(item => {
      const key = item[replaceFields.key];
      const children = item[replaceFields.children];
      const { on = {}, slots = {}, scopedSlots = {}, class: cls, style, ...restProps } = item;
      const treeNodeProps = {
      ...restProps,
      icon: $scopedSlots[scopedSlots.icon] || $slots[slots.icon] || restProps.icon,
      switcherIcon:
       $scopedSlots[scopedSlots.switcherIcon] ||
       $slots[slots.switcherIcon] ||
       restProps.switcherIcon,
      title:
       $scopedSlots[scopedSlots.title] ||
       $slots[slots.title] ||
       restProps[replaceFields.title],
      dataRef: item,
      on,
      key,
      class: cls,
      style,
      };
      if (children) {
      // herbert 20200928             
      if (this.onlyLeafEnable === true) {
       treeNodeProps.disabled = true;
      }
      return { ...treeNodeProps, children: this.updateTreeData(children) };
      }
      return treeNodeProps;
     });
     },
    }
    이 방법 에서 우 리 는 updateTreeData 속성 에서 treeNodeProps 속성 을 찾 았 습 니 다.그 값 은 바로 우리 가 dataRef 에 들 어 온 데이터 항목 입 니 다.그래서 이 속성 은 양 방향 연결 을 지원 합 니 다.이 treeData 은 최종 적 으로 treeNodeProps,구성 요소 로 렌 더 링 됩 니 다.
    이 두 가지 지식 을 알 게 된 후에 우리 가 해 야 할 조작 은 간단 해 졌 다.사건 구동 페이지 코드 는 다음 과 같다.
    
    <!-- author:herbert date:20201101 qq:464884492 -->
    <a-card style="width: 450px;height:550px;float: left;">
     <div slot="title">
      <h2>    (  dataRef)<span style="color:blue">@464884492</span></h2>
      <div>
      <a-button @click="eventAddSame">    </a-button>
      <a-divider type="vertical" />
      <a-button @click="eventAddSub">    </a-button>
      <a-divider type="vertical" />
      <a-button @click="eventModify">  </a-button>
      <a-divider type="vertical" />
      <a-button @click="eventDelete">  </a-button>
      </div>
     </div>
     <a-tree :tree-data="treeData2" @select="onEventTreeNodeSelected" :defaultExpandAll="true" :selectedKeys.sync="selectKeys2" showLine />
     <img src="./assets/gamelogo.png" width="100%" style="margin-top:20px" />
    </a-card>
    이벤트 구동 을 통 해 이 루어 진 이상,우 리 는 먼저 응당 받 아야 할 이벤트 에 등록 해 야 한다.코드 는 다음 과 같다.
    
    // author:herbert date:20201101 qq:464884492 
    onEventTreeNodeSelected(seleteKeys, e) {
     if (e.selected) {
      this.eventSelectedNode = e.node
      return
     }
     this.eventSelectedNode = null
    },
    이벤트 에서 저 희 는 현재 선택 한 TreeNode 를 저장 하여 추가 수정 과 삭 제 를 편리 하 게 합 니 다.
    5.1 동급 추가
    vue 가상 dom 을 이용 하여 부모 레벨 을 찾 습 니 다.
    
    // author:herbert date:20201101 qq:464884492 
    eventAddSame() {
     //     
     let dataRef = this.eventSelectedNode.$parent.dataRef
     if (!dataRef.children) {
      this.$set(dataRef, 'children', [])
     }
     dataRef.children.push({
      title: '      ,    ',
      key: new Date().getTime()
     })
     },
    5.2 다음 단계 추가
    직접 사용 대상 components\vc-tree\src\TreeNode.jsx,dataRef 사용 children 방법 주의
    
    // author:herbert date:20201101 qq:464884492
    eventAddSub() {
     let dataRef = this.eventSelectedNode.dataRef
     if (!dataRef.children) {
      this.$set(dataRef, 'children', [])
     }
     dataRef.children.push({
      title: '    ,    bug    ',
      key: new Date().getTime(),
      scopedSlots: { title: 'title' },
      children: []
     })
     }, 
    5.3 수정 노드$set 에 대응 하 는 값 을 직접 수정 합 니 다.
    
    // author:herbert date:20201101 qq:464884492 
    eventModify() {
     let dataRef = this.eventSelectedNode.dataRef
     dataRef.title = '    ,     bug'
     },
    5.4 노드 삭제
    vue 가상 dom 을 통 해 부모 급 dataRef 을 찾 아 dataRef 에서 선택 항목 을 제거 하면 됩 니 다.
    
    // author:herbert date:20201101 qq:464884492 
     eventDelete() {
     let parentDataRef = this.eventSelectedNode.$parent.dataRef
     //        
     const children = parentDataRef.children
     const currentDataRef = this.eventSelectedNode.dataRef
     const index = children.indexOf(currentDataRef)
     children.splice(index, 1)
     }
    6.총화
    이 지식 포 인 트 는 demo 에서 최종 완성 까지 앞 뒤 가 빠 른 한 달 이 걸 립 니 다.그 동안 소스 코드 를 찾 고 테스트 를 하 는 데 시간 이 걸 립 니 다.하지만 이 점 을 분명하게 말 하면 가치 가 있다 고 생각 합 니 다!데모 소스 코드 가 필요 하 다 면 아래 의 QR 코드 를 스 캔 하 십시오.공중 번호[작은 마당 이 작 지 않 습 니 다]에 관심 을 가지 고 children 에 답 하여 얻 으 십시오.ant-tree 이라는 구성 요소 라 이브 러 리 에 대해 서 는 제 가 예전 에 사 용 했 던 ant-desgin-vue 구성 요소 라 이브 러 리 에 비해 웹 페이지 전시 에 적합 한 것 같 습 니 다.배경 시스템 을 만 들 려 면 대량의 조작 이 필요 합 니 다.아직 힘 이 부족 합 니 다.
    ant-design-vue 에서 tree 를 삭제 하고 고 치 는 방법 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 ant-design-vue 에서 tree 를 삭제 하고 고 치 는 내용 은 예전 의 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 많은 응원 부탁드립니다!

    좋은 웹페이지 즐겨찾기