ng-content @ContentChild @ContentChildren学习

本文介绍了如何在Angular中实现自定义标签的嵌套,并详细解释了如何利用ng-content指令和ContentChild装饰器来实现内容的精准定位和元素的获取。

参考博客:https://segmentfault.com/a/1190000008707828

我们在写HTML时经常使用到标签嵌套,比如:

<div>
    <p>嵌套</p>
</div>

在angular自定义标签里面能否实现标签的嵌套呢?答案是肯定的.

/* parent.component.ts */
import { Component } from '@angular/core';

@Component({
    selector: 'exe-greet',
    template: `
    <div class="border">
        <p>Greet Component</p>  
        <ng-content></ng-content>
    </div>
    `,
    styles: [` .border { border: 2px solid #eee; } `]
})
export class GreetComponent { }
/* parent.component.ts */
import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `
    <h4>Welcome to Angular World</h4>
    <exe-greet>
      <p>Hello Semlinker</p>
    </exe-greet>
  `,
})
export class AppComponent { }

效果如下:
image.png
在页面里即有child组件的内容,也有parent组件child子组件嵌套的内容,也就是说parent组件child子组件嵌套的内容
映射到了 ng-content 标签上了,将代码稍微改一下:

<exe-greet>
    <p>Hello Semlinker</p>
    <p>Hello Bob</p>
</exe-greet>

页面上的效果就变成这样了
image.png

如果需要下面的效果
image.png
可以写成这样

/*parent.component.ts*/
import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `
    <h4>Welcome to Angular World</h4>
    <exe-greet>
      <div style="border: 1px solid #666; margin: 4px;">
         <div style="border: 1px solid red; margin: 5px;">Card Header</div>
         <div style="border: 1px solid green; margin: 5px;">Card Body</div>
         <div style="border: 1px solid blue; margin: 5px;">Card Footer</div>
      </div>
    </exe-greet>
  `,
})
export class AppComponent { }

虽然效果实现了,假设在另一个页面,也需要使用GreetComponent组件,那么还需要再次设置预设的样式.我们能不能把卡片风格的各个部分的默认样式定义在GreetComponent组件中,使用组件时我们只需关心自定内容区域的样式,当然也可以,调整后的代码

/*greet.component.ts*/
import { Component } from '@angular/core';

@Component({
    selector: 'exe-greet',
    template: `
    <div class="border">
        <p>Greet Component</p>  
        <div style="border: 1px solid #666;margin: 4px;">
            <div style="border: 1px solid red;margin: 5px;">
                <ng-content></ng-content>
            </div>
            <div style="border: 1px solid green;margin: 5px;">
                <ng-content></ng-content>
            </div>
            <div style="border: 1px solid blue;margin: 5px;">
                 <ng-content></ng-content>
            </div>
        </div>
    </div>
    `,
    styles: [` .border { border: 2px solid #eee; } `]
})
export class GreetComponent{ }

现在遇到的问题是怎样将父组件映射的内容与 ng-content 进行一一对应,好在 ng-content 支持 select 属性,它支持我们常用的选择器类型,如:

  • 标签选择器、
  • 类选择器、
  • ID选择器、
/*greet.component.ts*/
<div style="border: 1px solid #666;margin: 4px;">
     <div style="border: 1px solid red;margin: 5px;">
         <ng-content select="header"></ng-content>
     </div>
     <div style="border: 1px solid green;margin: 5px;">
         <ng-content select=".card_body"></ng-content>
     </div>
     <div style="border: 1px solid blue;margin: 5px;">
         <ng-content select="footer"></ng-content>
     </div>
</div>
/*parent.component.ts*/
import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `
    <h4>Welcome to Angular World</h4>
    <exe-greet>
      <header>Card Header</header>
          <div class="card_body">Card Body</div>
      <footer>Card Footer</footer>
    </exe-greet>
  `,
})
export class AppComponent { }

ContentChild
以前面的例子为例,我们在 AppComponent 组件中定义的内容,通过 ng-content 指令提供的选择器,成功投射到 GreetComponent 组件中。

但是我们只能让greet的元素显示,而不能获取到class中的属性,我想要class中的属性该怎么办呢?

了解完 Content Projection,接下来我们来介绍 ContentChild。

ContentChild 是属性装饰器,用来从通过 Content Projection 方式设置的视图中获取匹配的元素。

我们需要借助 @ContentChild 装饰器来处理

/*child.component.ts*/
import { Component } from '@angular/core';

@Component({
    selector: 'exe-child',
    template: `
      <p>Child Component</p>  
    `
})
export class ChildComponent {
    name: string = 'child-component';
}
/*parent.component.ts*/
import { Component, ContentChild, AfterContentInit } from '@angular/core';
import { ChildComponent } from './child.component';

@Component({
    selector: 'exe-parent',
    template: `
      <p>Parent Component</p>  
      <ng-content></ng-content>
    `
})
export class ParentComponent implements AfterContentInit {
    @ContentChild(ChildComponent)
    childCmp: ChildComponent;

    ngAfterContentInit() {
        console.dir(this.childCmp);
    }
}
/*app.component.ts*/
import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `
    <h4>Welcome to Angular World</h4>
    <exe-parent>
      <exe-child></exe-child>
    </exe-parent>
  `,
})
export class AppComponent { }

ContentChildren 属性装饰器用来从通过 Content Projection 方式设置的视图中获取匹配的多个元素,返回的结果是一个 QueryList 集合。

/*parent.component.ts*/
import { Component, ContentChildren, QueryList, AfterContentInit } from '@angular/core';
import { ChildComponent } from './child.component';

@Component({
    selector: 'exe-parent',
    template: `
      <p>Parent Component</p>  
      <ng-content></ng-content>
    `
})
export class ParentComponent implements AfterContentInit {

    @ContentChildren(ChildComponent)
    childCmps: QueryList<ChildComponent>;

    ngAfterContentInit() {
        console.dir(this.childCmps);
    }
}
/*app.component.ts*/
import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `
    <h4>Welcome to Angular World</h4>
    <exe-parent>
      <exe-child></exe-child>
      <exe-child></exe-child>
    </exe-parent>
  `,
})
export class AppComponent { }
<think>我们面临的问题是:ng-zorro-antd@17.0.0与@angular/core@17.3.12之间的依赖冲突。 根据引用[1]和引用[2]中的信息,ng-zorro-antd的版本必须与Angular的版本相匹配。因此,我们需要检查ng-zorro-antd@17.0.0所支持的Angular版本范围,并确认当前使用的@angular/core@17.3.12是否在支持范围内。 步骤: 1. 查看ng-zorro-antd的官方文档(或通过npm查看)中关于版本兼容性的说明。 2. 如果当前Angular版本不在ng-zorro-antd@17.0.0的支持范围内,则需要升级ng-zorro-antd或调整Angular版本(通常推荐调整ng-zorro-antd版本,因为Angular版本升级可能涉及更多内容)。 然而,根据引用[1]中的提示:“安装ng-zorro-antd的有一个重要的点就是一定要注意版本号!!!我的angular是7版本的,所以如果安装高版本的ng-zorro-antd会出问题”。 因此,我们需要检查ng-zorro-antd@17.0.0所要求的Angular版本。通常,ng-zorro-antd的主版本号与Angular的主版本号是对应的。例如,ng-zorro-antd v17.x.x 应该支持 Angular 17.x.x。 但是,当前我们的Angular版本是17.3.12(属于17.x.x),所以理论上应该是兼容的。那么为什么会出现依赖冲突呢? 可能的原因: 1. 其他依赖包版本不兼容(例如,Angular的其他包版本不一致,或者有peerDependencies冲突)。 2. 安装过程中出现了问题。 解决方案: 步骤1:检查package.json中所有Angular相关包的版本是否一致 确保所有@angular/*包的版本都是17.3.12(或至少17.x.x)。可以使用以下命令检查: ```bash npm list @angular/core # 或者 npm list @angular/common # 等等 ``` 步骤2:检查ng-zorro-antd的peerDependencies 查看ng-zorro-antd@17.0.0的peerDependencies要求,可以通过npm查看: ```bash npm view ng-zorro-antd@17.0.0 peerDependencies ``` 步骤3:解决版本冲突 如果发现peerDependencies要求的Angular版本范围不包括17.3.12,那么我们需要调整ng-zorro-antd的版本或升级Angular到要求的版本。 但根据通常情况,ng-zorro-antd@17.0.0应该要求Angular的版本是^17.0.0。所以,如果我们的Angular是17.3.12,应该是满足的。 步骤4:清理node_modules并重新安装 有时候,版本冲突可能是由于node_modules中的旧版本缓存导致的。我们可以尝试删除node_modules和package-lock.json(或yarn.lock)后重新安装。 ```bash rm -rf node_modules package-lock.json npm cache clean --force npm install ``` 步骤5:如果问题仍然存在,考虑使用`--force`或`--legacy-peer-deps`(npm)或`--force`(yarn)来强制安装(不推荐,因为可能会引入其他问题)。 步骤6:如果以上步骤无效,考虑降级ng-zorro-antd到与Angular17.3.12完全兼容的版本。 根据引用[4]中提到的,ng-zorro-antd的版本发布时会修复一些bug,但同时也可能引入新的问题。因此,我们可以尝试安装ng-zorro-antd的17.x.x的某个补丁版本,例如17.0.1(如果有)或者查看官方文档中是否有关于17.0.0与17.3.12兼容性的说明。 步骤7:查看ng-zorro-antd的更新日志(changelog)或GitHub issues,看是否有类似的问题报告。 步骤8:如果所有方法都无效,考虑升级Angular到最新版本(如果ng-zorro-antd要求更高版本的Angular)或者降级Angular到ng-zorro-antd@17.0.0要求的精确版本。 但是,由于我们目前Angular版本是17.3.12,而ng-zorro-antd@17.0.0应该是支持Angular17的,所以更可能是其他依赖问题。 另外,根据引用[3]中提到的,在旧版本中需要在.angular-cli.json中配置样式,但在Angular17中,配置方式已经改变(现在是在angular.json中配置)。所以,如果配置不正确,也可能导致问题。 因此,我们还需要检查angular.json中的配置: 在angular.json的styles数组中,需要添加ng-zorro-antd的样式: ```json "styles": [ "node_modules/ng-zorro-antd/ng-zorro-antd.min.css" ] ``` 总结: 1. 确保Angular所有包版本一致(17.3.12)。 2. 清理node_modules并重新安装。 3. 检查angular.json中的样式配置。 4. 如果以上步骤无效,尝试安装ng-zorro-antd的其他17.x.x版本(比如17.0.1, 17.0.2等)。 如果问题仍然无法解决,请提供具体的错误信息,以便进一步分析。 相关问题: 1. 如何检查npm包的peerDependencies? 2. 如何解决Angular项目中多个依赖包之间的版本冲突? 3. ng-zorro-antd在Angular17中需要哪些额外的配置? 4. 如何升级或降级ng-zorro-antd的版本?</think>### 解决 ng-zorro-antd@17.0.0 与 @angular/core@17.3.12 依赖冲突 #### 核心问题分析 1. **版本不匹配**:ng-zorro-antd 17.x 需要完全匹配 Angular 17.x 的次要版本[^1] 2. **peerDependencies 冲突**:ng-zorro-antd 17.0.0 可能要求精确的 Angular 17.0.x 版本 3. **依赖树不一致**:项目中的其他依赖包可能使用了不同版本的 Angular 核心库 #### 分步解决方案 ##### 1. 验证版本兼容性 ```bash # 检查当前安装的 Angular 版本 ng version # 查看 ng-zorro-antd 的 peerDependencies npm view ng-zorro-antd@17.0.0 peerDependencies ``` 输出应类似: ``` { "@angular/common": "^17.0.0", "@angular/core": "^17.0.0", ... } ``` 如果显示 `^17.0.0`,表示需要 Angular 17.x 的最新补丁版本 ##### 2. 统一 Angular 核心包版本 ```bash # 更新所有 Angular 包到 17.3.12 npm install @angular/core@17.3.12 @angular/common@17.3.12 @angular/forms@17.3.12 @angular/router@17.3.12 ``` ##### 3. 强制解决依赖冲突 ```bash # 使用 npm 强制安装(推荐) npm install ng-zorro-antd@17.0.0 --force # 或使用 yarn 的 resolutions 字段 # 在 package.json 中添加: "resolutions": { "@angular/core": "17.3.12", "@angular/common": "17.3.12" } ``` ##### 4. 验证依赖树 ```bash # 检查依赖关系 npm ls @angular/core npm ls ng-zorro-antd # 应看到类似输出 project@0.0.0 ├── @angular/core@17.3.12 └── ng-zorro-antd@17.0.0 └── @angular/core@17.3.12 deduped ``` ##### 5. 清理并重建项目 ```bash # 清除缓存和旧构建 rm -rf node_modules package-lock.json npm cache clean --force npm install ng serve --force ``` #### 关键配置调整 在 `package.json` 中添加 resolutions 字段: ```json { "name": "your-project", "dependencies": { "ng-zorro-antd": "^17.0.0" }, "resolutions": { "@angular/core": "17.3.12", "@angular/common": "17.3.12", "@angular/forms": "17.3.12", "@angular/router": "17.3.12" } } ``` #### 备选方案 如果仍存在冲突,可尝试: 1. **升级 ng-zorro-antd**: ```bash npm install ng-zorro-antd@17.3.0 # 匹配 Angular 17.3.x ``` 2. **降级 Angular**(不推荐): ```bash ng update @angular/core@17.0.0 @angular/cli@17.0.0 ``` #### 验证配置 在 `app.module.ts` 中确认正确导入: ```typescript import { NgZorroAntdModule } from 'ng-zorro-antd'; @NgModule({ imports: [ NgZorroAntdModule ] }) export class AppModule { } ``` 在 `angular.json` 中添加样式: ```json "styles": [ "node_modules/ng-zorro-antd/ng-zorro-antd.min.css" ] ``` #### 相关问题 1. **如何检查 ng-zorro-antd 的版本兼容性?** 访问 [NG-ZORRO 版本支持文档](https://ng.ant.design/docs/angular/faq/zh#%E7%89%88%E6%9C%AC%E5%85%BC%E5%AE%B9%E6%80%A7) 查看对应关系[^1] 2. **Angular 17 项目中如何正确安装 ng-zorro-antd?** 使用 `ng add ng-zorro-antd@17.3.0` 确保版本匹配[^2] 3. **如何解决 "Unmet peer dependencies" 警告?** 在 `package.json` 中添加 resolutions 字段强制统一版本[^3] 4. **ng-zorro-antd 组件不渲染可能是什么原因?** 检查样式导入和模块注册,确保在 `angular.json` 中添加了 CSS 文件[^3] 5. **如何升级整个 Angular 项目到兼容版本?** 使用 `ng update @angular/core@17.3 @angular/cli@17.3` 统一更新所有包 > **关键提示**:NG-ZORRO 的每个主版本都设计为与 Angular 的对应主版本完全兼容,但需要确保次要版本和补丁版本一致[^1][^4]。当出现依赖冲突时,统一核心包版本通常是最高效的解决方案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值