English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
En Vue.js, un componente recursivo se llama a sí mismo, por ejemplo:
Vue.component('recursive-component', { template: `<!--Invocándome a mí mismo!--> <recursive-component></recursive-component> });
Los componentes recursivos se utilizan a menudo para mostrar comentarios en blogs, menús anidados o básicamente tipos de padre e hijo idénticos, aunque el contenido específico sea diferente. Por ejemplo:
Ahora le mostraré cómo usar efectivamente el componente recursivo, creando un componente/Vamos a proceder paso a paso con un menú de árbol colapsado.
Estructura de datos
Un componente de UI en forma de árbol es una expresión visual de estructuras de datos recursivas. En este tutorial, utilizaremos una estructura de árbol donde cada nodo es un objeto:
Una propiedad label.
Si tiene nodos hijos, una propiedad nodes, es un array de uno o más nodos.
Como cualquier estructura de árbol, debe tener un nodo raíz, pero puede ser infinitamente profunda.
let tree = { label: 'root' nodes: [ { label: 'item'1', nodes: [ { label: 'item'1.1' }, { label: 'item'1.2', nodes: [ { label: 'item'1.2.1' } ] } ] }, { label: 'item'2' } ] }
Componente recursivo
Hagamos un componente recursivo para mostrar nuestra estructura de datos denominada TreeMenu. Mostrará solo la etiqueta del nodo actual y se llamará a sí mismo para mostrar cualquier nodo hijo. El nombre del archivo es TreeMenu.vue y su contenido es el siguiente:
<plantilla> <div class="árbol-menú> <div>{{ label }}</div> <árbol-menú v-for="node in nodes" :nodes="node.nodes" :label="node.label" > </tree-menu> </div> </template> <script> export default { props: [ 'label', 'nodes' ], name: 'tree-menu' } </script>
Si utilizas una recursión de componentes, debes hacer una definición global de Vue.component primero, o, dale un atributo name. De lo contrario, cualquier subcomponente no podrá llamarlo y obtendrás un mensaje de error de "undefined component".
Evento básico
Como cualquier función recursiva, necesitas un evento básico para terminar la recursión, de lo contrario, la renderización continuará indefinidamente y finalmente causará un desbordamiento de pila.
En el menú de árbol, cuando alcanzamos un nodo sin nodos hijos, queremos detener la recursión. ¿Puedes hacerlo a través de v-if logra hacer esta función, pero elegimos usar v-for implícitamente lo implementará por nosotros; si el array nodes no tiene una definición adicional de tree-El componente menu será llamado. El archivo template.vue es el siguiente:
<plantilla> <div class="árbol-menú> ... <!--Si `nodes` está undefined, esto no se renderizará--> <árbol-menu v-for="node in nodes"></tree-menu> </template>
Uso
¿Cómo utilizamos este componente ahora? Primero, declaramos una instancia de Vue con una estructura de datos que incluye la propiedad data y el componente treemenu definido. El archivo app.js es el siguiente:
import TreeMenu from '.'/TreeMenu.vue' let tree = { ... } new Vue({ el: '#app', data: { tree }, components: { TreeMenu } )
Recuerda que nuestra estructura de datos tiene un nodo raíz. Comenzamos la llamada recursiva al componente TreeMenu en el plantilla principal, utilizando la propiedad props nodes raíz:
<div id="app"> <árbol-menú :label="árbol.label" :nodes="árbol.nodes"></tree-menu> </div>
Aquí está su aspecto actual:
Postura correcta
Es bueno identificar visualmente la "profundidad" de los componentes hijos, para que el usuario pueda obtener una sensación de la estructura de datos desde la UI. Vamos a sangrar cada nodo hijo de una capa para lograr este objetivo.
Esto se logra mediante la adición de un prop depth definido, que se implementa a través de TreeMenu. Usaremos este valor para enlazar dinámicamente estilos en línea: usaremos la regla CSS transform: translate para cada etiqueta del nodo, creando así sangría. Se modificará template.vue de la siguiente manera**:**
<plantilla> <div class="árbol-menú> <div :style="indent">{{ label }}</div> <árbol-menú v-for="node in nodes" :nodes="node.nodes" :label="node.label" :depth="depth + 1" > </tree-menu> </div> </template> <script> export default { props: [ 'label', 'nodes', 'depth' ], name: 'tree-menu', computed: { indent() { return { transform: `translate(${this.depth * 50}px)` } } } } </script>
La propiedad depth comienza en cero en el plantilla principal. En el plantilla del componente superior, puedes ver que este valor aumenta cada vez que se pasa a cualquier nodo hijo.
<div id="app"> <árbol-menú :label="árbol.label" :nodes="árbol.nodes" :depth="0" ></tree-menu> </div>
Nota: recuerda v-bindeo el valor depth para asegurarme de que sea un tipo de número JavaScript en lugar de una cadena.
Expandir/Contraer
Dado que la estructura de datos recursiva puede ser muy grande, una buena técnica UI para mostrarlas es ocultar todos los nodos excepto el nodo raíz, para que el usuario pueda expandir o contraer los nodos según sea necesario.
Por lo tanto, agregaremos una propiedad local.showChildren. Si su valor es False, los nodos hijos no se renderizarán. Este valor debe cambiarse mediante el clic en el nodo, por lo que necesitamos utilizar un método de escucha de eventos de clic toggleChildren para gestionarlo. Se modificará el archivo template.vue de la siguiente manera**:**
<plantilla> <div class="árbol-menú> <div :style="indent" @click="toggleChildren">{{ label }}</div> <árbol-menú v-if="showChildren"" v-for="node in nodes" :nodes="node.nodes" :label="node.label" :depth="depth + 1" > </tree-menu> </div> </template> <script> export default { props: [ 'label', 'nodes', 'depth' ], data() { return { showChildren: false } }, name: 'tree-menu', computed: { indent() { return { transform: `translate(${this.depth * 50}px)` } } }, methods: { toggleChildren() { this.showChildren = !this.showChildren; } } } </script>
Resumen
De esta manera, tenemos un menú de árbol operativo. Un método para resaltar es agregar un signo más (+)/El icono de guión, de esta manera, puede hacer que la visualización de UI sea más clara. Además, he mejorado la tipografía y el rendimiento de cálculo en la base de showChildren.
Declaración: Este artículo se ha obtenido de la red, es propiedad del autor original, el contenido se ha subido de manera autónoma por los usuarios de Internet, este sitio web no posee los derechos de propiedad, no ha sido editado artificialmente y no asume la responsabilidad de las responsabilidades legales relacionadas. Si encuentra contenido sospechoso de violación de derechos de autor, por favor envíe un correo electrónico a: notice#w para denunciar, y proporcione evidencia relevante.3Declaración: El contenido de este artículo se ha obtenido de la red, es propiedad del autor original, el contenido se ha subido de manera autónoma por los usuarios de Internet, este sitio web no posee los derechos de propiedad, no ha sido editado artificialmente y no asume la responsabilidad de las responsabilidades legales relacionadas. Si encuentra contenido sospechoso de violación de derechos de autor, por favor envíe un correo electrónico a: notice#w para denunciar, y proporcione evidencia relevante. Una vez confirmado, este sitio eliminará inmediatamente el contenido sospechoso de violación de derechos de autor.