Ant Design Transfer Twin Tree Shuttle box "make Wheels"

Les traces du temps 2021-09-15 04:50:51
ant design transfer twin tree


Le travail ne s'arrête pas,Plus que le Code,J'ai encore un double.

La boîte de navette de liste et la boîte de navette d'arbre unique ont été implémentées auparavant,Cette fois, il s'agit principalement de réaliser un cadre de navette arborescent complet,Structure arborescente à gauche et à droite du cadre de la navette,Et les noeuds parents - enfants sont liés,Ou pour le choix de la ville.

L'effet de réalisation est montré dans la figure:

ic_transfer_1.png

Principaux points fonctionnels:

  1. Côté gauche du cadre de navette、Les données sur la structure de l'arbre sont à droite
  2. Les noeuds parents - enfants sont liés,Sélection complète possible、Demi - choix、Pas du tout.
  3. Les données sélectionnées sont déplacées vers la droite,Ne pas afficher à gauche
  4. Essentiellement le traitement des données
  5. Pour le choix de la ville,Bien que la présentation de la structure des données,Mais ce sont les données de la ville qui sont retournées

Dans la présentation de code suivante,.Le traitement à gauche et à droite du cadre de navette est essentiellement le même,Prenons l'exemple de la boîte de données source gauche seulement

UI Terminé.

UI En gros, le style du site officiel imité,Les noms de style sont également directement tirés du site officiel,Pratique et rapide...

  1. Boîte de données source:Barre de tête(checkbox),Barre de recherche(input),Barre de données(tree)
  2. Boîte de données cible:Barre de tête(checkbox),Barre de recherche(input),Barre de données(tree)
  3. Barre d'action: Déplacer le bouton à gauche (button), Déplacer le bouton à droite (button)

Le Code d'implémentation est le suivant:

<template>
<div class="tree-transfer ant-transfer ant-transfer-customize-list">
<!-- Boîte de données source -->
<div class="ant-transfer-list">
<!-- Barre de tête -->
<div class="ant-transfer-list-header">
<a-checkbox :indeterminate="from_is_indeterminate" v-model="from_check_all" @change="fromAllBoxChange" />
<span class="ant-transfer-list-header-selected">
<span >{{ from_check_keys.length || 0 }}/{{ from_all_keys.length }} {{
locale.itemUnit }}</span
>
<span class="ant-transfer-list-header-title">{{ fromTitle }}</span>
</span>
</div>
<!-- Contenu principal -->
<div class="ant-transfer-list-body ant-transfer-list-body-with-search">
<!-- Boîte de recherche -->
<div v-if="filter" class="ant-transfer-list-body-search-wrapper">
<div>
<a-input v-model="filterFrom" :placeholder="locale.searchPlaceholder" class="ant-transfer-list-search" />
<a class="ant-transfer-list-search-action">
<a-icon type="close-circle" theme="filled" v-if="filterFrom && filterFrom.length > 0" @click="filterFrom = ''" />
<a-icon type="search" v-else />
</a>
</div>
</div>
<!-- Liste des arbres -->
<div class="ant-transfer-list-body-customize-wrapper">
<a-tree ref="from-tree" class="tt-tree from-tree" blockNode checkable :checked-keys="from_check_keys" :expanded-keys="from_expand_keys" :tree-data="self_from_data" @check="fromTreeChecked" @expand="fromTreeExpanded" :style="{ height: treeHeight + 'px' }" />
</div>
</div>
</div>
<!-- Barre d'action -->
<div class="ant-transfer-operation">
<a-button type="primary" @click="addToAims(true)" shape="circle" :disabled="from_disabled" icon="right" ></a-button>
<a-button type="primary" @click="removeToSource" shape="circle" :disabled="to_disabled" icon="left" ></a-button>
</div>
<!-- Boîte de données cible -->
<!-- Omis ici, Comme les données sources -->
</div>
</template>
Copier le Code

L'effet de réalisation est montré dans la figure:

ic_transfer_2.png

Traitement des données

Affichage à gauche et à droite du cadre de navette ,Essentiellement le traitement des données, Ensuite, concentrez - vous sur la façon dont les données sont traitées .

  1. Paramètres entrants: Principalement des sources de données dataSource Et de la zone de données cible targetKeysEnsemble(Ici.targetKeys Seulement pour les villes id, À l'exclusion des provinces id)
  2. Paramètres de rappel:targetKeys( Sélectionnez à droite key Ensemble)

Paramètres entrants(props)

Nom du paramètre Type Est - ce nécessaire? Remarques
dataSource Array Y Source des données
targetKeys Array Y Données de la boîte de droite key Ensemble
titles Array N Titre de la tête ,Par défaut[" Liste des sources ", "Liste des objectifs"]
locale Object N Éléments de configuration
filter Boolean N Afficher la boîte de recherche
replaceFields Object N Remplacer treeData Champ correspondant dans

Paramètres internes du composant

data() {
return {
data_source: [...this.dataSource], // Source des données
target_keys: [], // Données de la boîte de droite key Ensemble
from_is_indeterminate: false, // Si les données sources sont à moitié sélectionnées 
from_check_all: false, // Si toutes les données sources sont sélectionnées 
to_is_indeterminate: false, // Si les données cibles sont à moitié sélectionnées 
to_check_all: false, // Si toutes les données cibles sont sélectionnées 
from_disabled: true, // Si le bouton Ajouter est désactivé 
to_disabled: true, // Si le bouton Supprimer est désactivé 
from_check_keys: [], // Données sources sélectionnées keyTableau Associer le bouton navette à cette propriété , Sélection générale 、 Demi - sélection 
to_check_keys: [], // Données cibles sélectionnées keyTableau Associer le bouton navette à cette propriété , Sélection générale 、 Demi - sélection 
from_expand_keys: [], // Expansion des données sources keyTableau
to_expand_keys: [], // Expansion des données cibles keyTableau
from_all_keys: [], // Données sources toutes les key
to_all_keys: [], // Données cibles toutes les key
filterFrom: "", // Filtrage des données sources 
filterTo: "", // Filtrage des données cibles 
};
}
Copier le Code

Traitement des données

  1. Traitement du filtrage des données Selon target_keys Et filterFromFiltrer les données. (1) Filtre de données source contenant target_keysDonnées. (2) Les données cibles ne sont conservées que pour contenir target_keysDonnées
computed: {
// Données sources
self_from_data() {
// Filtrage des données sources 
let from_array = filterSourceTree(
this.data_source,
this.target_keys,
this.filterFrom,
this.replaceFields
);
// === Pour sélectionner tout 、 Traitement de l'état semi - sélectionné ====
// Obtenir les données de la source tous les keyEnsemble
this.from_all_keys = this.getAllKeys(from_array);
// Obtenir toutes les données sources sélectionnées keyEnsemble
this.from_check_keys = this.from_check_keys.filter((key) =>
this.from_all_keys.includes(key)
);
return from_array;
},
// Nom du menu de données source 
fromTitle() {
let [text] = this.titles;
return text;
}
}
Copier le Code
  1. Traiter toutes les sélections 、 Statut semi - sélectionné ou non sélectionné
watch: {
/* Gauche Surveillance de l'état */
from_check_keys(val) {
if (val.length > 0) {
// Si le bouton navette est désactivé 
this.from_disabled = false;
// Demi - sélection totale ouverte 
this.from_is_indeterminate = true;
// Sélection totale ouverte ou non : Selon que le nombre de noeuds racine dans le noeud sélectionné est égal à la longueur des données source 
// Obtenir toutes les provinces keyEnsemble
let allParentKeys = this.self_from_data.map(
(item) => item[this.replaceFields.key]
);
// Obtenir tous les keyEnsemble
let allCheck = val.filter((item) => allParentKeys.includes(item));
// 1. Afficher toutes les sélections lorsqu'elles sont égales 
if (allCheck.length == this.self_from_data.length) {
// Éteignez les demi - sélections Activer la sélection complète 
this.from_is_indeterminate = false;
this.from_check_all = true;
} else {
// 2. Sinon, Sélection partielle 
this.from_is_indeterminate = true;
this.from_check_all = false;
}
} else {
// 3. Quand elle n'est pas sélectionnée , Statut non sélectionné 
this.from_disabled = true;
this.from_is_indeterminate = false;
this.from_check_all = false;
}
}
}
Copier le Code

Définition de l'événement

Sélectionner tous les événements

  1. Sélectionnez tout: Traverser pour tout key
  2. Annuler tout :key Vide.
/* Données sources Sélection générale checkbox */
fromAllBoxChange(val) {
if (this.self_from_data.length == 0) {
return;
}
if (val.target.checked) {
this.from_check_keys = this.getAllKeys(this.self_from_data);
} else {
this.from_check_keys = [];
}
this.$emit("left-check-change", this.from_check_all);
}
Copier le Code

Accès aux données tous les key

getAllKeys(data) {
let result = [];
data.forEach((item) => {
result.push(item[this.replaceFields.key]);
if (item.children && item.children.length) {
item.children.forEach((o) => {
result.push(o[this.replaceFields.key]);
});
}
});
return result;
}
Copier le Code

Case à cocher Événements

Déclenché lorsque la case à cocher est cliquée ,Utilisation directeTreeDe@checkGestion des événements

fromTreeChecked(checkedKeys, e) {
this.from_check_keys = checkedKeys;
}
Copier le Code

Déploiement/ Rangez l'événement

Déploiement/ Déclenché lorsque le noeud est arrimé ,Utilisation directeTreeDe@expandGestion des événements

fromTreeExpanded(expandedKeys) {
this.from_expand_keys = expandedKeys;
}
Copier le Code

Traitement analogique des données

Données de base

[
{
id: "1000",
pid: "0",
value: "Province de Hubei",
label: "Province de Hubei",
children: [
{ id: "1001", pid: "1000", label: "Wuhan" },
{ id: "1020", pid: "1000", label: "Xianning" },
{ id: "1022", pid: "1000", label: "Sens de la piété filiale" },
{ id: "1034", pid: "1000", label: "Xiangyang" },
{ id: "1003", pid: "1000", label: "Yichang" },
],
},
{
id: "1200",
pid: "0",
value: "Province du Jiangsu",
label: "Province du Jiangsu",
children: [
{ id: "1201", pid: "1200", label: "Nanjing" },
{ id: "1202", pid: "1200", label: "Suzhou" },
{ id: "1204", pid: "1200", label: "Yangzhou" },
],
},
];
Copier le Code

Traitement des données de source

Les données déjà sélectionnées n'apparaissent pas dans la zone de données source , Filtrez - le juste

const filterSourceTree = ( tree = [], targetKeys = [], keyword = "", replaceFields ) => {
if (!tree.length) {
return [];
}
const result = [];
for (let item of tree) {
if (item[replaceFields.title].includes(keyword)) {
if (item.children && item.children.length) {
let ele = { ...item, children: [] };
for (let o of item.children) {
if (targetKeys.includes(o[replaceFields.key])) continue;
ele.children.push(o);
}
if (ele.children.length) {
result.push(ele);
}
}
} else {
if (item.children && item.children.length) {
let node = { ...item, children: [] };
for (let o of item.children) {
if (
!(
!targetKeys.includes(o[replaceFields.key]) &&
o[replaceFields.title].includes(keyword)
)
)
continue;
node.children.push(o);
}
if (node.children.length) {
result.push(node);
}
}
}
}
return result;
};
let leftSource = filterSourceTree(
this.provinceData,
// Wuhan,Xianning,Nanjing
["1001", "1020", "1201"],
"",
this.replaceFields
);
console.log(leftSource);
Copier le Code

ic_transfer_3.png

Traitement des données cibles

Les données déjà sélectionnées n'apparaîtront que dans la zone de données cible

const filterTargetTree = ( tree = [], targetKeys = [], keyword = "", replaceFields ) => {
if (!tree.length) {
return [];
}
const result = [];
for (let item of tree) {
if (item[replaceFields.title].includes(keyword)) {
if (item.children && item.children.length) {
let ele = { ...item, children: [] };
for (let o of item.children) {
if (!targetKeys.includes(o[replaceFields.key])) continue;
ele.children.push(o);
}
if (ele.children.length) {
result.push(ele);
}
}
} else {
if (item.children && item.children.length) {
let node = { ...item, children: [] };
for (let o of item.children) {
if (
!(
targetKeys.includes(o[replaceFields.key]) &&
o[replaceFields.title].includes(keyword)
)
)
continue;
node.children.push(o);
}
if (node.children.length) {
result.push(node);
}
}
}
}
return result;
};
// Traitement des données cibles
let rightSource = filterTargetTree(
this.provinceData,
["1001", "1020", "1201"],
"",
this.replaceFields
);
console.log(rightSource);
this.provinceData = rightSource;
Copier le Code

ic_transfer_4.png

Modification de la fonction

Fonctions précédentes filterSourceTree,filterTargetTree Les mots clés et les données cibles sont filtrés simultanément , Plus grossier , Et seulement pour la structure de l'arbre secondaire ,Faible extensibilité. Ensuite, il a été optimisé .

Les fonctions spécifiques sont visibles : Résumé des opérations courantes pour les données de structure de l'arbre frontal

Traitement des données de source

computed: {
// Données sources
self_from_data() {
// Filtre de données sélectionné 
let from_array = filterSourceTreeFn(this.data_source, this.target_keys);
// Filtrage des mots clés
if (this.filterFrom) {
from_array = filterKeywordTreeFn(from_array, this.filterFrom);
}
return from_array;
},
}
Copier le Code

ic_transfer_8.png

Traitement des données cibles

computed: {
// Données cibles 
self_to_data() {
// Conservation des données sélectionnée 
let to_array = filterTargetTreeFn(this.data_source, this.target_keys);
// Filtrage des mots clés
if (this.filterTo) {
to_array = filterKeywordTreeFn(to_array, this.filterTo);
}
return to_array;
},
}
Copier le Code
版权声明
本文为[Les traces du temps]所创,转载请带上原文链接,感谢
https://qdmana.com/2021/09/20210914174203469k.html

  1. Front and back end data interaction (V) -- what is Axios?
  2. Windows configures nginx to boot automatically
  3. Des questions d'entrevue communes à Tomcat pour discuter de votre compréhension de la technologie de verrouillage distribué,
  4. JS handscrap, Classic interview question, web front end Development Process
  5. Android 400 questions d'entrevue pour vous aider à entrer dans l'usine, un tour pour vous apprendre à comprendre netty
  6. Développement et projet d'application Web statique côté PC
  7. Recommandé pour le tutoriel Spring Framework, 2021 dernière question d'entrevue d'embauche de la société aiqiyi Java,
  8. La dernière revue scientifique de l'académicien Luo Liqun: architecture de la boucle neuronale pour stimuler la nouvelle Ia
  9. [partage d'expérience de travail], 2021 les dernières questions d'entrevue Java de Baidu, Headlines, etc.
  10. Lisez l'analyse de 497 questions pour l'entrevue d'ingénieur principal Android et vérifiez les lacunes.
  11. Grâce à cette collection de questions d'entrevue d'automne, le salaire de saut d'emploi et l'entrevue de développement audio et vidéo ont doublé.
  12. Prenez d'un coup l'offre de Tencent meituan et jetez un coup d'oeil à cette copie de l'entrevue de printemps!
  13. L'expérience et l'expérience d'un Maverick Java en matière d'entrevue sur les MTD, l'expérience de l'entrevue d'embauche du printemps Java en 2021,
  14. Vue中自定义列表复选框和全选框-案例
  15. Vue bidirectional binding (V-model bidirectional binding,. Sync bidirectional binding,. Sync transfer object)
  16. CSS text overflow ellipsis summary, as you wish
  17. C'est la mode la plus étrange que j'ai jamais vue.
  18. Cases à cocher et toutes les cases à cocher de la liste personnalisée en vue - CAS
  19. Vue bidirectional binding (V-model bidirectional binding,. Sync bidirectional binding,. Sync transfer object)
  20. Vue3.0 using Gaode map to obtain longitude and latitude information
  21. Front end interview daily 3 + 1 - day 877
  22. Vue bidirectional binding (V-model bidirectional binding,. Sync bidirectional binding,. Sync transfer object)
  23. React realizes the function of copying pictures with one click
  24. White space, word break and word wrap are the three most basic and confusing attributes in CSS - thoroughly understand
  25. Trois ans d'expérience d'entrevue avec une femme de programmation diplômée, une réflexion sur la cohérence de l'expiration des données de redis Master slave Node,
  26. Résumé de l'entrevue Android de Dachang, carte technique Android
  27. Un plan de carrière Java correct, découvrez les questions que vous devez poser lors de l'entrevue d'embauche du printemps Java de cette année.
  28. Le résumé de l'entrevue Android de Dachang est en retard
  29. Un article vous a appris à gérer les entrevues sur le Web, à partager 350 vraies questions d'entrevue Java,
  30. Jquery Tools Methodology collation, Sharing a little interview Experience
  31. Jquery plug - in urianchor, app front end Development
  32. $in jquery, Visualized Web Development Tool
  33. Le développement Java doit être fait. Les entrevues https demandent souvent une analyse complète.
  34. vue v-if未生效问题
  35. vue动态改变组件外部元素样式
  36. Jdk's Past Life: The Classic Features of Thin Number - java5 - - - 15 -, webfront Development
  37. Résumé des questions d'entrevue pour les ingénieurs en développement Java, analyse des questions d'entrevue à haute fréquence Dubbo,
  38. The new front-end lady asked: there was a 404 problem refreshing the page in Vue routing history mode
  39. A Simple Css Meun
  40. Vue modifier dynamiquement le style de l'élément externe du composant
  41. Vue V - si problème non valable
  42. N'osez pas vous opposer à l'intervieweur et obtenir des commentaires personnels des stagiaires d'offer Ali après cinq rondes d'entrevue.
  43. Améliorer continuellement leur capacité à créer des primes, et les questions d'entrevue Java d'Alibaba Huawei Tencent et d'autres grandes usines sont sautées en octets.
  44. The new front-end lady asked: there was a 404 problem refreshing the page in Vue routing history mode
  45. Who doesn't want to make a scratch music by himself? Scratch music is realized by native JS
  46. Learn XPath to help climb the data of major e-commerce platforms in the Mid Autumn Festival
  47. vue動態改變組件外部元素樣式
  48. vue v-if未生效問題
  49. Je ne comprends pas comment la machine virtuelle JVM peut encore interviewer, et j'ai terminé ce dictionnaire d'entrevue Java de 1307 pages.
  50. Dongxh, mid autumn festival gifts 🥮, [CSS starry sky realization, Mid Autumn Festival poem]
  51. What if you want to see the moon and don't want to go out
  52. Mid Autumn Festival, Chang'e looks at the moon
  53. [Pixi] super beautiful! How to make mid autumn festival scene level animation!!
  54. Echarts realizes the rotation of the moon (super simple, you can see it at a glance)
  55. Dart mixin full resolution
  56. Some suggestions on Vue code readability | comments are rewarded
  57. 120 lines of code to achieve pure web video editing
  58. Yang yangsun took a selfie to celebrate his 30th birthday, and Wang Yanlin sent blessings.
  59. Comment passer une entrevue avec une entreprise Internet de première ligne, Android Classic Getting started tutoriel
  60. Comment essayer un développeur Android vraiment niveau, 【 résumé de l'entrevue 】