如何在Angular 5项目中引入Materialize并初始化侧边栏等组件?
在Angular生产环境中使用Materialize CSS的最佳实践
嘿,我来分享下在Angular生产环境中用Materialize CSS的最佳方案,刚好之前我也碰到过组件里没法在index.html初始化侧边栏的问题,下面分两部分给你说清楚:
一、推荐的引入方式:通过npm安装(而非CDN)
生产环境下,用npm管理Materialize依赖比CDN靠谱太多了——版本可控、方便构建优化,还能避免外部CDN挂掉影响你的项目。具体步骤很简单:
- 先安装Materialize和它的依赖(jQuery和Popper.js,Materialize底层依赖这俩)
npm install materialize-css jquery popper.js
- 配置Angular项目
- 全局引入的话,直接改
angular.json:找到build->options里的styles和scripts数组,把Materialize的样式和脚本加进去:"styles": [ "node_modules/materialize-css/dist/css/materialize.min.css", "src/styles.css" ], "scripts": [ "node_modules/jquery/dist/jquery.min.js", "node_modules/popper.js/dist/umd/popper.min.js", "node_modules/materialize-css/dist/js/materialize.min.js" ] - 要是你想按需在组件里导入样式,也可以在组件的CSS文件里加这句:
@import "~materialize-css/dist/css/materialize.min.css";
- 全局引入的话,直接改
二、Materialize组件的正确姿势:在组件生命周期里初始化
因为Angular组件有自己的渲染周期,你在index.html的script里初始化的话,导航栏组件的DOM还没渲染出来,肯定没用。所以得在组件的ngAfterViewInit钩子里面做——这个钩子触发的时候,组件的视图已经完全渲染好了,DOM元素都能拿到。
1. 侧边栏(Sidenav)初始化
方式一:原生DOM查询(简单场景够用)
在你的导航栏组件(比如navbar.component.ts)里这么写:
import { Component, AfterViewInit } from '@angular/core'; declare var M: any; // 声明全局的M对象,避免TypeScript报错 @Component({ selector: 'app-navbar', templateUrl: './navbar.component.html', styleUrls: ['./navbar.component.css'] }) export class NavbarComponent implements AfterViewInit { ngAfterViewInit(): void { // 找到侧边栏元素,初始化 const elem = document.querySelector('.sidenav'); const instance = M.Sidenav.init(elem, { // 这里可以加配置项,比如侧边栏从哪边滑出来、动画时长 edge: 'left', inDuration: 300 }); } }
方式二:用Angular的ViewChild(更符合Angular风格)
这种方式不用全局查DOM,更可控,推荐用:
import { Component, AfterViewInit, ViewChild, ElementRef } from '@angular/core'; declare var M: any; @Component({ selector: 'app-navbar', template: ` <ul class="sidenav" #sidenavRef> <!-- 侧边栏的菜单内容 --> <li><a href="#!">首页</a></li> <li><a href="#!">关于我们</a></li> </ul> <!-- 触发按钮 --> <a href="#" data-target="sidenavRef" class="sidenav-trigger"><i class="material-icons">menu</i></a> ` }) export class NavbarComponent implements AfterViewInit { @ViewChild('sidenavRef') sidenavRef!: ElementRef; ngAfterViewInit(): void { // 用ViewChild拿到的元素初始化 const instance = M.Sidenav.init(this.sidenavRef.nativeElement, { edge: 'left' }); // 要是以后需要操作这个实例(比如手动打开/关闭),可以把instance存成组件属性 // this.sidenavInstance = instance; } }
2. 轮播(Carousel)初始化
和侧边栏思路一样,在包含轮播的组件里用ngAfterViewInit:
import { Component, AfterViewInit, ViewChild, ElementRef } from '@angular/core'; declare var M: any; @Component({ selector: 'app-carousel', template: ` <div class="carousel" #carouselRef> <a class="carousel-item" href="#one!"><img src="assets/image1.jpg"></a> <a class="carousel-item" href="#two!"><img src="assets/image2.jpg"></a> <a class="carousel-item" href="#three!"><img src="assets/image3.jpg"></a> </div> ` }) export class CarouselComponent implements AfterViewInit { @ViewChild('carouselRef') carouselRef!: ElementRef; ngAfterViewInit(): void { const instance = M.Carousel.init(this.carouselRef.nativeElement, { // 配置项示例:全屏显示、显示指示器、切换动画时长 fullWidth: true, indicators: true, duration: 200 }); } }
额外小技巧
- 要是遇到TypeScript报类型错误,直接装个Materialize的类型定义包就行:
装完之后就不用写npm install @types/materialize-css --save-devdeclare var M: any;了,直接导入:import * as M from 'materialize-css'; - 生产构建的时候,Angular的打包工具会自动优化这些依赖,不用担心体积太大的问题。
内容的提问来源于stack exchange,提问作者Manjunath Shenoy
相关产品推荐
相关产品推荐

