You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular使用innerHTML插入NG-ZORRO菜单时出现多余空属性如何解决

问题根本原因
  • 你用innerHTML插入的是纯静态HTML内容,nz-menu、nz-submenu、nz-menu-item、nzTitle都是NG-ZORRO封装的Angular指令,必须经过Angular的编译流程才能被识别,绑定对应的交互逻辑和样式,单纯写在innerHTML里的属性不会被Angular处理,就算属性没有被转义,菜单也无法正常工作。
  • 你观察到的属性被转成全小写、无值属性自动追加=""是浏览器原生处理innerHTML的默认行为,HTML本身对属性大小写不敏感,这个行为无法通过常规的innerHTML插入方式规避。
可行解决方案

方案1:动态编译组件(适合模板完全动态拼接的场景)

如果你确实无法使用模板语法实现,可以通过Angular的动态组件能力,将你要渲染的菜单模板放到临时组件中编译后再插入到页面,示例代码如下:
首先写组件逻辑:

import { Component, ViewChild, ViewContainerRef, OnInit } from '@angular/core';
import { NzMenuModule } from 'ng-zorro-antd/menu';

// 定义承载菜单的临时组件
@Component({
  standalone: true, // 非standalone项目可以删掉这行,把组件加到对应模块的declarations中
  imports: [NzMenuModule],
  template: `
    <ul nz-menu>
      <li nz-submenu nzTitle='Parent'>
        <ul>
          <li nz-submenu nzTitle="Item 1">
            <ul>
              <li nz-menu-item>Option 1</li>
              <li nz-menu-item>Option 2</li>
            </ul>
          </li>
        </ul>
      </li>
    </ul>
  `
})
class DynamicMenuComponent {}

@Component({
  // 你现有组件的原有配置
})
export class YourComponent implements OnInit {
  // 页面中预留的菜单容器
  @ViewChild('menuContainer', { read: ViewContainerRef }) menuContainer!: ViewContainerRef;

  ngOnInit(): void {
    // 直接渲染动态组件到容器(Angular 13+支持,低版本需要用ComponentFactoryResolver)
    this.menuContainer.createComponent(DynamicMenuComponent);
  }
}

然后在你的组件模板中添加容器节点:

<ng-template #menuContainer></ng-template>

如果你的菜单内容需要动态调整,可以给DynamicMenuComponent添加@Input()属性,渲染的时候传入动态值即可。

方案2:递归渲染菜单(推荐,适合动态菜单数据的场景)

如果你的菜单是通过后端数据动态生成的,直接使用NG-ZORRO适配的递归模板方案性能更好、也更易维护:
首先定义菜单的JSON结构:

menuItems = [
  {
    title: 'Parent',
    children: [
      {
        title: 'Item 1',
        children: [
          { title: 'Option 1' },
          { title: 'Option 2' }
        ]
      }
    ]
  }
]

然后在模板中写递归渲染逻辑:

<ul nz-menu>
  <ng-container *ngFor="let item of menuItems">
    <ng-container *ngIf="item.children?.length; else itemTpl">
      <li nz-submenu [nzTitle]="item.title">
        <ul>
          <ng-container *ngTemplateOutlet="subMenuTpl; context: { $implicit: item.children }"></ng-container>
        </ul>
      </li>
    </ng-container>
    <ng-template #itemTpl>
      <li nz-menu-item>{{ item.title }}</li>
    </ng-template>
  </ng-container>
</ul>

<!-- 递归子菜单模板 -->
<ng-template #subMenuTpl let-childList>
  <ng-container *ngFor="let item of childList">
    <ng-container *ngIf="item.children?.length; else itemTpl">
      <li nz-submenu [nzTitle]="item.title">
        <ul>
          <ng-container *ngTemplateOutlet="subMenuTpl; context: { $implicit: item.children }"></ng-container>
        </ul>
      </li>
    </ng-container>
  </ng-container>
</ng-template>

这个方案不需要处理编译逻辑,支持任意层级的菜单渲染,是官方推荐的动态菜单实现方式。

内容的提问来源于stack exchange,提问作者Rares P

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 04:18:04