zoukankan      html  css  js  c++  java
  • 【Angular】动态组件

    使用场景
    我们先明确下动态组件的使用场景,在代码运行时要动态加载组件,换成普通人话,代码需要根据具体情况(比如用户的操作,向后台请求结果)确定在某些地方加载某些组件,这些组件不是静态的(不是固定的)。

    官网的举例就是,构建动态广告条,广告组件不断会推出新的,再用只支持静态组件结构的模板显然是不现实的。

    再举一个常见的例子,动态弹出框,弹出的组件是不确定的、不断更新的,这里那里弹出个购买框,那那那又需要弹出样式选择框,静态组件结构模板是不能满足群众日渐增长的需求。

    怎么实现
    然后我们来找个把手,看实现动态组件需要什么。

    一、动态组件放在哪

    我们需要知道把动态组件加在哪里,也就是锚点。那什么东西可以用来加载组件呢?

    你可能会想说,组件不就加载锚点上吗,锚点不就是DOM节点吗?那当然是加载DOM节点里啊。

    我们先来回顾下Angular操作DOM的常见方法,原生JS操作DOM的方法你就不要想了,你觉得它能返回给你能加载Angular组件的对象吗?

    Angular 提供了一种叫做 DOM Query 的技术,主要来源于 @ViewChild 和 @ViewChildren 装饰器(decorators),两者基本功能相同 。

    @ViewChild: 返回单个引用,在视图的 DOM 中查找能匹配上该选择器的第一个元素或指令。

    @ViewChildren :返回由 QueryList 对象包装好的多个引用,在视图的 DOM 中查找能匹配上该选择器的所有元素或指令。

    基本语法:

    @ViewChild([reference from template], {read: [reference type]});


    DOM Query 的技术查找出来的对象分为三类:

    ElementRef:如果它挂载的是类似 span 的简单 html 元素;
    TemplateRef: 如果它挂载的是 template 元素;
    ViewContainerRef: 无法推断,一般要程序员要在read中指明,任何DOM元素都可以被用作为视图容器。
    我们通过官网查询API可以看到只有ViewContainerRef才是可以将一个或多个视图附着到组件中的容器,也就是只有它才可以加载组件。不过要注意的是,它是一个可以将新的组件作为其兄弟(节点)的DOM元素(容器),是兄弟,不是父子额。

    好的,我们确定了使用ViewContainerRef来加载容器,获取ViewContainerRef有两种方式:

    第一种就是上面的通过DOM Query查询@ViewChild获取

    <ng-container #addComp></ng-container>
    
    
    @ViewChild('addComp', {read: ViewContainerRef}) adComp:ViewContainerRef;

    第二种就是官网里的例子,用依赖注入

    import { Directive, ViewContainerRef } from '@angular/core';
    
    @Directive({
    selector: '[ad-host]',
    })
    export class AdDirective {
    constructor(public viewContainerRef: ViewContainerRef) { }
    }

    锚点设置ng-template上,通过指令注入获取ViewContainerRef

    template: `
    <div class="ad-banner-example">
    <h3>Advertisements</h3>
    <ng-template ad-host></ng-template>
    </div>
    `


    二、怎么获取组件的实例

    组件加载到视图中去,不是简单一个new就实例化,再append、insert之类就能附加上去的就可以的。动态组件需要编译器事先编译存放好起来,再以ComponentFactory封装起来,之后的Component实例要通过ComponentFactory 来创建。大家可以看下这篇文章[译] 关于 Angular 动态组件你需要知道的,不过它提及的使用 SystemJsNgModuleLoader 模块加载器已经被淘汰了。

    ComponentFactoryResolver一个简单的注册表,映射Components到ComponentFactory可用于创建组件实例的生成的类。它可用于获取给定组件类型的工厂,然后使用工厂的create()方法创建该类型的组件。

    我们来看下官网实例代码,以下不是完整代码

    //注入ComponentFactoryResolver
    constructor(private componentFactoryResolver: ComponentFactoryResolver) { }
    
    loadComponent() {
    ......
    // 拿到可用于创建广告组件实例的生成的ComponentFactory
    const componentFactory = this.componentFactoryResolver.resolveComponentFactory(adItem.component);
    
    //获取加载组件的容器
    const viewContainerRef = this.adHost.viewContainerRef;
    viewContainerRef.clear();
    
    // 把组件放到容器里,再传一些参数给它
    const componentRef = viewContainerRef.createComponent(componentFactory);
    (<AdComponent>componentRef.instance).data = adItem.data;
    }


    你以为这就完了,你以为这样写出的代码就能运行吗?太年轻,让前浪来给你说一下要注意的几个点:

    Angular 中的组件、指令、管道都是是被封装在模块中,以组件为例,如果要使用其别的模块组件,必须别的模块有export这个组件,而且你在自己模块也要import其他模块。所以官网例子的指令记得导入导出。
    如果是动态组件,必须把组件注册在模块中 entryComponents 属性,但是就不用了export,import模块还是需要的。

    原文链接: https://blog.csdn.net/from_the_star/article/details/106443293

  • 相关阅读:
    ASP.NET CORE 使用Consul实现服务治理与健康检查(2)——源码篇
    ASP.NET CORE 使用Consul实现服务治理与健康检查(1)——概念篇
    Asp.Net Core 单元测试正确姿势
    如何通过 Docker 部署 Logstash 同步 Mysql 数据库数据到 ElasticSearch
    Asp.Net Core2.2 源码阅读系列——控制台日志源码解析
    使用VS Code 开发.NET CORE 程序指南
    .NetCore下ES查询驱动 PlainElastic .Net 升级官方驱动 Elasticsearch .Net
    重新认识 async/await 语法糖
    EF添加
    EF修改部分字段
  • 原文地址:https://www.cnblogs.com/mailyuan/p/14718140.html
Copyright © 2011-2022 走看看