vue 组件延时加载

    科技2025-03-23  23

    vue 组件延时加载

    “Before software can be reusable it first has to be usable.”

    “在软件可重用之前,首先必须要可用。”

    — Ralph Johnson

    —拉尔夫·约翰逊

    Lazy loading, by definition, is the technique of loading something on demand.

    根据定义,延迟加载是按需加载某些内容的技术。

    Lazy loading can be applied to different levels of your application-development process, from modules to components. Module-level lazy loading is quite famous in the Angular world, but component-level lazy loading is something less spoken about. In this article, we’ll create an accordion component and lazy load the content.

    延迟加载可以应用于从模块到组件的应用程序开发过程的不同级别。 模块级的延迟加载在Angular世界中非常有名,但是组件级的延迟加载却很少有人谈论。 在本文中,我们将创建一个手风琴组件并延迟加载内容。

    为什么要全部使用Lazyload组件? (Why Lazyload Components at All?)

    Photo by Dave Willhite on Unsplash Dave Willhite在 Unsplash上 拍摄的照片

    So you’ve published your production-ready Angular application!

    因此,您已经发布了可用于生产的Angular应用程序!

    You made sure to use best practices while writing the code, reusing components, lazyloading modules, and whatnot. After weeks of live usage, users have started complaining about application performance — specifically, about the initial loading time of some pages. For this reason, you started losing users, and the statistics keep coming down.

    您确保在编写代码,重用组件,延迟加载模块等等时使用最佳实践。 经过数周的现场使用,用户开始抱怨应用程序性能-特别是某些页面的初始加载时间。 因此,您开始失去用户,并且统计数据不断下降。

    You did a round of analysis and found you have a component that’s making multiple API calls that aren’t necessary (or less important) for the initial user experience. It can be a modal, an accordion, or even a slider. This particular API call is slowing down your application and making user experience sluggish.

    您进行了一轮分析,发现您有一个组件正在进行多个API调用,这些调用对于初始用户体验不是必需的(或不太重要)。 它可以是模式乐曲,手风琴甚至是滑块。 此特定的API调用减慢了您的应用程序的速度,并使用户体验缓慢。

    The better approach here (taking the accordion as the example) clearly would be to load content inside the accordion only when the user opens the particular accordion.

    此处更好的方法(以手风琴为例)显然是仅在用户打开特定手风琴时才将内容加载到手风琴中。

    This above is a perfect use case to implement lazy loading.

    以上是实现延迟加载的理想用例。

    Let’s get to it.

    让我们开始吧。

    初始版本 (The Initial Version)

    For the sake of practicality, let’s assume an application scenario where we have a list of blog posts that we want to show under an accordion.

    出于实用性考虑,让我们假设一个应用场景,其中有一个我们希望在手风琴下显示的博客文章列表。

    Before we refactor and implement lazy loading, the below typical application setup is what we have.

    在重构和实现延迟加载之前,下面是典型的应用程序设置。

    We have two components:

    我们有两个组成部分:

    Post component loading data of the blog post)

    发布博客文章的组件加载数据) Accordion component

    手风琴部分

    We’re using these two components to render the blog post to users in our app-component.

    我们正在使用这两个组件在我们的app-component向用户呈现博客文章。

    <app-accordion> <div> <app-post accordionBody></app-post> </div> </app-accordion>

    We’re using the app-accordion component and passing the app-post component to it for content projection.

    我们正在使用app-accordion组件,并将app-post组件传递给它进行内容投影。

    And for the accordion implementation:

    对于手风琴的实现:

    <div class="accordion"> <div class="accordion-head"> <button (click)="isOpen = !isOpen">{{ isOpen ? "-" : "+" }}</button> </div> <hr /> <div *ngIf="isOpen" class="accordion-content"> <ng-content select="[accordionBody]"></ng-content> </div> </div>

    Inside our post component, we’re making an HTTP call to jsonplaceholder, getting a fake blog post, and displaying it on the template.

    在我们的post组件内部,我们正在对jsonplaceholder进行HTTP调用,获取了虚假的博客文章,并将其显示在模板上。

    // ... @Component({ selector: 'app-post', template: ` <div> <h3>{{ post?.title }}</h3> <p>{{ post?.body }}</p> </div>`, }) export class PostComponent implements OnInit { constructor(private api: ApiService) {} post: any; ngOnInit(): void { this.http.get('https://jsonplaceholder.typicode.com/posts/1').subscribe((res) => { this.post = res; }); } }

    This will result in something like the following:

    这将导致如下所示:

    Initial application before lazy loading 延迟加载之前的初始应用

    As you can clearly see, the data is now loading on the page’s initial load, which isn’t ideal in some cases, such as the one we discussed above.

    正如您可以清楚地看到的那样,数据现在是在页面的初始加载时加载的,在某些情况下,例如上面我们所讨论的那样,这并不理想。

    实施延迟加载 (Implementing Lazy Loading)

    Here’s our plan to get the content loaded lazily.

    这是我们计划延迟加载内容的计划。

    We’ll be using @ContentChild from @angular/core to grab the accordion body using the directive syntax on a <ng-template> (we’re replacing the content-projection technique in the earlier version). We use <ng-template> and not a <div> because of the special nature of it, which we can make use of.

    我们将使用@ ContentChild angular / core中的@ ContentChild来在<ng-template>上使用指令语法来获取手风琴主体(我们将替换早期版本中的content-projection技术)。 我们使用<ng-template>而不是<div>是因为可以使用它的特殊性质。

    From the docs:

    从文档:

    “The <ng-template> is an Angular element for rendering HTML. It is never displayed directly. In fact, before rendering the view, Angular replaces the <ng-template> and its contents with a comment. If there is no structural directive and you merely wrap some elements in a <ng-template>, those elements disappear.”

    “ <ng-template>是用于呈现HTML的Angular元素。 它永远不会直接显示。 实际上,在渲染视图之前,Angular用注释替换了<ng-template>及其内容。 如果没有结构指令,而只是将某些元素包装在<ng-template> ,那么这些元素就会消失。”

    To start with, let’s create a new directive for the accordion body.

    首先,让我们为手风琴主体创建一个新指令。

    ng generate directive accordion

    Let’s rename the selector to [accordion-body]. The purpose of this directive is to only act as a selector for our <ng-template>, which holds our accordion body. The only change we’re making to this directive is renaming it.

    让我们将选择[accordion-body]命名为[accordion-body] 。 该指令的目的只是充当<ng-template>的选择器,该选择器保留了我们的手风琴琴体。 我们对该指令进行的唯一更改是重命名它。

    // ... @Directive({ selector: '[accordion-body]', }) export class AccordionDirective {}

    Let’s now add the [accordion-body] directive into our app-component.

    现在,将[accordion-body]指令添加到我们的app-component 。

    <app-accordion> <ng-template accordion-body> <app-post></app-post> </ng-template> </app-accordion>

    If you now navigate to our application, you’ll see the app-post component not displayed at all — thus, our API isn’t triggered either.

    如果现在导航到我们的应用程序,您将看到根本不显示app-post组件-因此,我们的API也不被触发。

    Great!

    大!

    The only part remaining now is to refactor the app-accordion component.

    现在剩下的唯一部分是重构app-accordion组件。

    // ... @Component({ selector: 'app-accordion', templateUrl: './accordion.component.html', }) export class AccordionComponent implements OnInit { isOpen: boolean = false; @ContentChild(AccordionBodyDirective, { read: TemplateRef }) accordionBodyRef: TemplateRef<unknown>; }

    We’re extending our already existing accordion component. We’ve used @ContentChild to access the first child of app-accordion having AccordionDirective (i.e., [accordion-body]) in it. Note that we used read: TemplateRef, as we’re accessing a template reference. You can read about more options in the documentation.

    我们将扩展现有的手风琴组件。 我们已经使用@ContentChild访问其中包含AccordionDirective (即[accordion-body] )的app-accordion的第一个子app-accordion 。 请注意,在访问模板引用时,我们使用read: TemplateRef 。 您可以在文档中阅读更多选项。

    Now we can simply use this in our app-accordion component template.

    现在,我们可以在app-accordion组件模板中简单地使用它。

    <div class="accordion"> <div class="accordion-head"> <button (click)="isOpen = !isOpen">{{ isOpen ? "-" : "+" }}</button> </div> <hr /> <div *ngIf="isOpen" class="accordion-content"> <ng-container *ngTemplateOutlet="accordionBodyRef"></ng-container> </div> </div>

    It’s as easy as that!

    就这么简单!

    Note the use of *ngTemplateOutlet, which is used to insert an embedded view from a prepared TemplateRef(accordionBodyRef).

    请注意使用* ngTemplateOutlet ,该方法用于从准备好的TemplateRef (accordionBodyRef)插入嵌入式视图。

    That’s all of it! You now have a lazy-loaded an accordion component and have a faster-loading application.

    仅此而已! 现在,您有了一个延迟加载的手风琴组件,并拥有一个加载速度更快的应用程序。

    After the lazy-loading implementation 延迟加载实现后

    扩展解决方案以支持急切加载(Extending the Solution to Support Eager Loading)

    The present implementation of our accordion only supports lazy loading. There’s no way you can eagerly load (on initial load of application content) with the present implementation. But at times, you might have cases where you need the accordion to support eagerly loading content. In that case, you might have to create another component to achieve this.

    我们的手风琴的当前实现仅支持延迟加载。 您无法通过本实现急切地加载(在应用程序内容的初始加载时)。 但是有时,您可能需要手风琴来支持急切加载内容的情况。 在这种情况下,您可能必须创建另一个组件才能实现此目的。

    Let’s make our existing accordion component truly reusable by adding both lazy- and eager-loading capabilities.

    通过添加延迟加载和渴望加载功能,使我们现有的手风琴组件真正可重用。

    This can be done easily by adding another *ngIf condition inside our accordion template.

    通过在手风琴模板中添加另一个*ngIf条件,可以轻松完成此操作。

    <div class="accordion"> <div class="accordion-head"> <button (click)="isOpen = !isOpen">{{ isOpen ? "-" : "+" }}</button> </div> <hr /> <div *ngIf="isOpen" class="accordion-content"> <ng-container *ngIf="accordionBodyRef; else eagerBody"> <ng-container *ngTemplateOutlet="accordionBodyRef"></ng-container> </ng-container> <ng-template #eagerBody> <ng-content select="[accordionBody]"></ng-content> </ng-template> </div> </div>

    We’re checking if the accordionBodyRef template exists or not. If it does, we’re showing the component, and the content would load lazily. If not, we’re simply picking the accordionBody using content projection.

    我们正在检查accordionBodyRef模板是否存在。 如果是这样,我们将显示该组件,并且内容将延迟加载。 如果没有,我们只是使用内容投影来选择accordionBody主体。

    Now on app-component:

    现在在app-component :

    <app-accordion> <!-- to lazy load --> <ng-template accordionBody> <app-post></app-post> </ng-template> <!-- to eager load --> <div accordionBody> <app-post></app-post> </div> </app-accordion>

    There you go! You can now use the same app-accordion component to render contents lazily or eagerly as required.

    你去! 现在,您可以使用相同的app-accordion组件根据需要懒惰或急切地呈现内容。

    You can find the completed project here on GitHub.

    您可以在GitHub上找到完成的项目。

    Happy hacking!

    骇客骇客!

    翻译自: https://medium.com/better-programming/why-and-how-to-lazy-load-components-in-angular-b4aff3797c6d

    vue 组件延时加载

    相关资源:微信小程序源码-合集6.rar
    Processed: 0.010, SQL: 8