Maison  >  Article  >  interface Web  >  Analyse de l'encapsulation du composant de liste déroulante dans Angular 6

Analyse de l'encapsulation du composant de liste déroulante dans Angular 6

不言
不言original
2018-07-23 11:35:581789parcourir

Le contenu partagé avec vous dans cet article concerne l'analyse de l'encapsulation du composant de liste déroulante dans Angular 6. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.

Préface

L'apprentissage doit être un processus de combinaison de input et output, c'est la raison pour laquelle j'ai écrit cet article.
Les listes déroulantes sont souvent utilisées dans les applications Web à affichage grand écran. Après plusieurs tentatives, j'ai opté pour une plutôt bonne idée.

Exigences

  • La partie tête de l'en-tête de liste est stationnaire, tandis que la partie corps défile vers le haut.

  • Une fois le défilement de la partie du corps terminé, les données doivent être actualisées. L'effet final est d'afficher toutes les données pertinentes dans la base de données sous une forme de défilement vers le haut.

Analyse

Si la quantité de données est relativement faible, nous pouvons extraire toutes les données en même temps et les mettre dans le DOM pour un défilement circulaire. En fait, cela ressemble à l’effet d’un carrousel.

Mais s'il y a beaucoup de données, cela peut provoquer une fuite de mémoire. Naturellement, on peut penser à paginer les données de la liste. Mon idée initiale était de placer un table comme conteneur dans la couche externe de p, puis table d'augmenter périodiquement la valeur de top Lorsque table est à mi-chemin de l'exécution, demandez des données au backend. et créez-le dynamiquement. Un composant tbody est inséré dans table, puis lorsque le tbody précédent a disparu (hors de vue), le composant est supprimé. L’idée semblait réalisable, mais elle s’est heurtée à des difficultés dans la pratique. Lorsque supprime le composant précédent, la hauteur de table sera réduite et la table tombera instantanément. Ce n’est évidemment pas ce que nous souhaitons, et les effets secondaires sont assez graves.

Dans ce cas, j'ai séparé tbody en deux table, et les deux table boucles. Lorsqu'il n'y a aucune donnée sous le table précédent, le deuxième table commence à marcher Lorsque le premier table sort complètement de p, réinitialisez sa position au bas de p et mettez à jour le. data , puis répétez les actions entre les deux. C'est un peu compliqué à réaliser, mais l'effet est passable et satisfaisant. Le problème est que les deux minuteries sont instables. Lorsque j'ouvre un autre logiciel et que je reviens, les deux tables s'exécutent de manière incohérente. Cette maladie congénitale setInterval n'est pas assez précise et les deux minuteries sont sujettes à une mauvaise coordination.

Enfin, en rentrant du travail, j’ai pensé à une méthode qui ne nécessitait pas deux tables. Utilisez une seule table minuterie pour monter. À mi-chemin, effacez la minuterie, réinitialisez la position et mettez à jour la moitié des données. C'est-à-dire que la première moitié des données du tableau est supprimée et les nouvelles données extraites de l'arrière-plan sont fusionnées sur le tableau. De cette façon, les données peuvent être continuellement actualisées, et table il semble qu'elles continuent d'augmenter.

Code

scroll-table.component.html

<p class="table-container">
  <table class="head-show">
    <thead>
      <tr>
        <th style="width:12.8%;">字段1</th>
        <th style="width:12.8%;">字段2</th>
        <th>字段3</th>
        <th style="width:12.8%;">字段4</th>
      </tr>
    </thead>
  </table>
  <p class="scroller-container">
    <table #scroller class="scroller">
      <tbody>
        <tr *ngFor="let ele of tbody">
          <td style="width:12.8%;">{{ele.field01}}</td>
          <td style="width:12.8%;">{{ele.field02}}</td>
          <td><p>{{ele.field03}}</p></td>
          <td style="width:12.8%;">{{ele.field04}}</td>
        </tr>
      </tbody>
    </table>
  </p>
</p>

scroll-table.component.ts

import { Component, OnInit, ViewChild, ElementRef, Input } from '@angular/core';
import { HttpService } from '../http.service';

@Component({
  selector: 'app-scroll-table',
  templateUrl: './scroll-table.component.html',
  styleUrls: ['./scroll-table.component.scss']
})
export class ScrollTableComponent implements OnInit {
  tbody: any = [];
  @Input() url; //将地址变成组件的一个参数,也就是输入属性
  //控制滚动的元素
  @ViewChild('scroller') scrollerRef: ElementRef;
  timer: any;

  freshData: any;

  pageNow = 1;//pageNow是当前数据的页码,初始化为1

  constructor(private http: HttpService) {}

  ngOnInit() {
    //初始化拿到native
    let scroller: HTMLElement = this.scrollerRef.nativeElement;
    this.http.sendRequest(this.url).subscribe((data :any[]) => {
      
      this.tbody = data.concat(data);
    });
    //开启定时器
    this.timer = this.go(scroller);
  }

  getFreshData() {
  //每次请求数据时,pageNow自增1
    this.http.sendRequest(`${this.url}?pageNow=${++this.pageNow}`).subscribe((data:any[]) => {
      if(data.length<10) {
        //数据丢弃,pageNow重置为1
        this.pageNow = 1;
      }
      this.freshData = data;
    });
  }
  
  go(scroller) {
    var
      moved = 0,
      step = -50,
      timer = null,
      task = () => {
        let style = document.defaultView.getComputedStyle(scroller, null);
        let top = parseInt(style.top, 10);
        if (moved < 10) {
          if(moved===0) {
            this.getFreshData();
          }
          scroller.style.transition = "top 0.5s ease";
          moved++;
          scroller.style.top = top + step + 'px';

        } else {
          //重置top,moved,清除定时器
          clearInterval(timer);
          moved = 0;
          scroller.style.transition = "none";
          scroller.style.top = '0px';
          //更新数据
          this.tbody = this.tbody.slice(10).concat(this.freshData);
          timer = setInterval(task,1000);
        }
      };
    timer = setInterval(task, 1000);
  }
}

scroll-table.component L'effet de .scss

.table-container {
    width: 100%;
    height: 100%;
}
.head-show {
    border-top: 1px solid #4076b9;
    height: 11.7%;
}
.scroller-container {
    border-bottom: 1px solid #4076b9;
    //border: 1px solid #fff;
    width: 100%;
    //height: 88.3%;
    height: 250px;
    box-sizing: border-box;
    overflow: hidden;
    position:relative;
    .scroller {
        position: absolute;
        top:0;
        left:0;
        transition: top .5s ease;
    }
}
table {
    width: 100%;
    border-collapse: collapse;
    table-layout: fixed;
    //border-bottom:1px solid #4076b9;
    th {
        
        border-bottom:1px dashed #2d4f85;
        color:#10adda;
        padding:8px 2px;
        font-size: 14px;
    }
    td {
        border-bottom: 1px dashed #2d4f85;
        font-size: 12px;
        
        color:#10adda;
        position: relative;
        height: 49px;
        p{
            padding:0 2px;
            box-sizing: border-box;
            text-align:center;
            display: table-cell;
            overflow: hidden;
            vertical-align: middle;
        }
        //border-width:1px 0 ;
    }
}

est que le composant n'a besoin de transmettre qu'un seul paramètre url, puis toutes les opérations, y compris la mise à jour des données, sont effectuées par le composant lui-même. Cela complète l’encapsulation des composants et facilite la réutilisation.

Résumé et réflexions

1. Les données de mise à jour doivent être mises à jour à la source, c'est-à-dire ne pas ajouter et supprimer d'éléments DOM. Cette opération est gênante et les performances sont faibles. Le mettre à la source signifie faire tout un plat du tableau qui stocke les données d'affichage dans la classe de composants.
2. Les nouvelles données demandées en arrière-plan doivent être préparées à l'avance et placées dans un autre tableau temporaire. C'est l'équivalent d'un cache et d'un registre temporaire.
3. J'imagine le composant comme une fonction. Il n'a qu'un seul paramètre, qui est l'adresse de la donnée. Tant que ce paramètre est présent, le composant peut fonctionner normalement et ne dépend d'aucune autre valeur. Accouplement lâche.
4. Renforcer l'idée de programmation fonctionnelle. Bien que ce soit la caractéristique de React, j'ai toujours l'impression que angular peut aussi être utilisé.

Recommandations associées :

Comment les directives personnalisées AngularJs peuvent être définies et la convention de dénomination des directives personnalisées

Dans AngularJs Quoi est la relation entre le modèle, le contrôleur et la vue ? (Photos et texte)

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn