本文转自:https://godbasin.github.io/2017/06/02/angular2-free-4-create-sidebar/

因为项目原因又玩上了Angular2(v4.0+),《玩转Angular2》系列用于探索一些灵活或者新的用法。
本文记录制作左侧菜单,并使用路由自动定位的过程。

调整配置


上一篇有些配置不是很合适,故这里我们先进行调整。

全局注入jQuery

上篇我们是这样注入jQuery的:

1
2
// jquery
window['$'] = window['jQuery'] = require('./assets/js/jquery.min.js');

这样的全局注入其实可能会导致一些问题(不知道是不是配置不正确,导致本骚年的其他jQuery插件失效),所以我们还是用webpack来注入。
首先安装jQuery的依赖:

1
npm install jquery --save

然后在webpack的插件配置plugins中添加:

1
2
3
4
5
6
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
})
]

就可以挪掉上面不够优雅的注入方式了。

开启source-map

之前我们的webpack配置中也添加了devtool: 'source-map',但是这个需要配合source-map-loader才能生效:

1
npm install -D source-map-loader

然后在webpack中添加loader:

1
2
3
4
5
6
7
8
9
10
11
rules: [
{
test: /\.js$/,
use: ["source-map-loader"],
enforce: "pre",
exclude: [
path.join(__dirname, 'node_modules', '@angular/compiler'),
path.join(__dirname, 'node_modules', 'rxjs')
]
}
]

这里我们需要排除@angular/compiler以及rxjs,可能还有其他一些依赖,不然会有webpack的warning。详细也可以查看类似的issue-Warnings displayed by webpack when using source-map-loader。

压缩代码

webpack自带了一个压缩插件UglifyJsPlugin,我们添加以下配置就可以生效:

1
2
3
4
5
6
7
plugins: [
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
})
]

压缩后的代码体积大大减小,但会消耗一定的编译速度,故一般打包到生产环境才会使用。

分离代码

如果说我们需要分离其他的代码,像一些依赖的代码,或者是css代码,也可以通过配置实现。

  1. 抽离依赖vender.js文件
1
2
3
4
5
6
7
new CommonsChunkPlugin({
name: 'vendors',
filename: 'vendors.js',
minChunks: function(module) {
return isExternal(module);
}
})

关于isExternal()函数,用了很简单的方式进行:

1
2
3
4
5
6
7
function isExternal(module) {
var userRequest = module.userRequest;
if (typeof userRequest !== 'string') {
return false;
}
return userRequest.indexOf('node_modules') >= 0; // 是否位于node_modules里
}
  1. 将样式从js中抽出,生成单独的.css样式文件。即把所以的css打包合并:
1
2
3
new ExtractTextPlugin('style.css', {
allChunks: true // 提取所有的chunk(默认只提取initial chunk,而上面CommonsChunkPlugin已经把部分抽离了)
})

这些大家下来可以配置,本骚年就不在项目这使用了。

创建左侧菜单


添加配置文件

这里我们为了方便拓展,使用配置的方式来自定义菜单,这样每次我们需要修改的时候只需要调整配置文件就好了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// sidebar.config.ts
export const menus = [{
icon: 'fa-home', // icon用于储存菜单对应的图标
text: '页面管理', // text用于储存该菜单显示名称
childMenus: [{
link: '/home/page-setting', // link用于设定该菜单跳转路由
text: '页面配置' // text用于储存该菜单显示名称
}, {
link: '/home/page-rebuild',
text: '页面重现'
}]
}, {
icon: 'fa-cubes',
text: '使用说明',
link: '/home/page-handbook'
}];

这里暂时限定我们最多为二级菜单,跟之前搭建管理项目的方式一致。

添加html文件

这里我们可以遍历配置文件生成菜单:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<div class="col-md-3 left_col menu_fixed">
<div class="left_col scroll-view">
<!-- 其他省略,重点在下面 -->
<!-- sidebar menu -->
<div class="main_menu_side hidden-print main_menu">
<div class="menu_section">
<!-- 其他省略,重点在下面 -->
<ul class="nav side-menu metismenu" id="sidebar-menu">
<li class="topper-menu" *ngFor="let menu of menus;" [ngClass]="menu.link && isActive(menu.link) ? 'active' : ''">
<a *ngIf="menu.link" [routerLink]="menu.link"><i class="fa" [ngClass]="menu.icon"></i> {{menu.text}}</a>
<a *ngIf="!menu.link" class="has-arrow"><i class="fa" [ngClass]="menu.icon"></i> {{menu.text}}</a>
<ul class="nav child_menu slide">
<li *ngFor="let childMenu of menu.childMenus;" class="slide-item" routerLinkActive="current-page">
<a [routerLink]="childMenu.link">{{ childMenu.text }}</a>
</li>
</ul>
</li>
</ul>
</div>
</div>
<!-- /sidebar menu -->
</div>
</div>

这里可以看到,我们使用*ngFor来进行遍历,然后我们大致可以得到我们的component需要以下功能:

  • [routerLink]: 链接跳转
  • routerLinkActive: 路由激活时样式
  • isChildMenuActived: 判断该菜单下是否有子菜单的路由处于激活状态

这里我们需要注意的是:

  1. 使用angular自带的常用指令,像*ngForngClass等,需要在注册@NgModule时引入CommonModule
  2. 使用angular里面路由常用指令,像[routerLink]routerLinkActive等,需要在注册@NgModule时引入RouterModule
  3. 使用angular里面表单常用指令,像[(ngModel)]等,需要在注册@NgModule时引入FormModule

像我们的HomeModule

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
import { CommonModule } from '@angular/common';
import { HomeRoutes } from './home.routes';
import { HomeComponent } from './home.component';
import { SidebarComponent } from './sidebar/sidebar.component';
@NgModule({
declarations: [
HomeComponent,
SidebarComponent
],
imports: [
FormsModule,
CommonModule,
RouterModule.forChild(HomeRoutes)
],
providers: []
})
export class HomeModule { }

添加component

组件使用了简单的jQuey插件metisMenu,详细说明请参考文档,这里我们只需要知道调用$().metisMenu()的时候,若有<li class="active">则自动将该<li>设置为激活形式,此时我们在路由跳转结束的时候就可以获取对应激活路由然后初始化菜单状态了。

我们直接在代码中说明吧:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import {Component, ElementRef} from '@angular/core';
import {ActivatedRoute, Router, NavigationEnd} from '@angular/router';
import {menus} from './sidebar.config';
import 'rxjs/Rx';
@Component({
selector: 'home-sidebar',
templateUrl: './sidebar.component.html',
})
export class SidebarComponent {
menus: any[] = menus;
constructor(private route: ActivatedRoute, private router: Router, el: ElementRef) {
this.router.events.subscribe(event => {
// 判断路由结束
if (event instanceof NavigationEnd) {
const $menu = $(el.nativeElement).find('#sidebar-menu');
this.menus.forEach((menu, index) => {
if (this.isChildMenuActived(menu)) {
// 将被激活的路由对应的li添加“active”的class
$menu.find('li.topper-menu').eq(index).addClass('active');
}
});
// 初始化菜单状态
$menu.metisMenu();
}
});
}
// 判断路由是否激活状态
isActive(url: string): boolean {
return this.router.isActive(url, false);
}
// 判断菜单是否有子路由处于激活状态
isChildMenuActived(menu: any): boolean {
let hasOneActive = false;
if (menu.childMenus) {
// 遍历子路由看是否被激活
menu.childMenus.forEach(child => {
hasOneActive = hasOneActive || this.isActive(child.link);
});
}
return hasOneActive;
}
}

在Angular2-release版本里,一般路由的状态是通过事件监听获取的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 使用`ActivatedRoute`的API获取路由信息。
import { ActivatedRoute } from '@angular/router';
@Component({
... // 略
})
export class SidebarComponent {
constructor(private route: ActivatedRoute) {}
ngOnInit() {
this.route.params
.subscribe((params) => {
this.id = parseInt(params['id']); // 获取params
... // 其余代码
});
}
... // 其余代码
}

这里我们也可以使用filter()来过滤监听我们想要的事件:

1
2
// 监听导航事件变更完毕
router.events.filter(event => event instanceof NavigationEnd).subscribe(event => {});

更多有关路由的我们上节也说过,可以点击回顾《玩转Angular2(3)–启用路由和添加静态资源》。

最终效果图:

结束语


这节主要讲了一些基础环境配置的调整,以及制作路由自动定位左侧菜单的过程,主要涉及的可能还是路由相关。
看菜单列表的内容,大家猜猜本骚年接下来想要做什么?就不告诉你,哈哈。
此处查看项目代码
此处查看页面效果

查看Github有更多内容噢:https://github.com/godbasin

转载于:https://www.cnblogs.com/freeliver54/p/10411039.html

[转]玩转Angular2(4)--制作左侧自动定位菜单相关推荐

  1. html如何做左侧导航条,如何使用HTMLCSS制作左侧滑动导航条

    初始状态 点击菜单展开 HTML代码 使用HTML&CSS制作左侧滑动导航条 Cloud App Dashborad Shortcuts Overview Events About Servi ...

  2. 【chrome插件】公众号后台,固定侧边栏,自动定位菜单位置。

    完整教程:[chrome插件]公众号后台,固定侧边栏 下载地址github: https://github.com/qingmvc/weixin.sidebar 欢迎关注公众号<科幻宇宙> ...

  3. 用EasyBoot制作光盘启动菜单

    EasyBoot是一款集成化的中文启动光盘制作工具,它可以制作光盘启动菜单.自动生成启动文件,并生成可启动ISO文件,利用其内置的刻录功能,马上就能制作出一张完全属于你自己的启动光盘 一.功能篇 先看 ...

  4. html 显示视频列表,dvd光碟制作节目轨菜单布局,不要视频缩略图,只显示文件列表...

    "如何在刻录视频光盘时自定义制作菜单?实现的效果就是当光盘插入DVD影碟机播放时,首先会出现一个所有视频文件列表的菜单(节目轨菜单),就相似于音乐CD曲目表一样,不需要有视频缩略图,可通过遥 ...

  5. easyui左侧导航菜单右侧载入百度地图项目框架

    代码下载 http://pan.baidu.com/s/1cDht7K 一个左侧是导航菜单,右侧是百度地图的应用: 一 左侧菜单 使用jquery easyui框架:网上下的资源:运行后如下: 二 修 ...

  6. jq中查找上级_必备实用技能:在EXCEL中制作下拉菜单

    发出去表格统计信息,收回来时却发现填得乱糟糟?小白通教你制作下拉菜单,填表人只能规规矩矩从你给的选项中填.认真学习,这个是必备技能哦. 单级下拉菜单 1. 选择需要编辑的单元格,选择"数据- ...

  7. jquery-11 如何制作鼠标右键菜单

    jquery-11 如何制作鼠标右键菜单 一.总结 一句话总结:核心原理:找到右键菜单事件contextmenu,return false去掉默认事件,然后判断用户是否点的右键,然后在鼠标的位置显示菜 ...

  8. excel添加列下拉框票价_excel表格下拉表格添加数据-excel2017表格中怎么制作下拉菜单列表框...

    在Excel表中,如何将增加下拉菜单的选项? excel中的下拉菜单选项,就是筛选的功能,具体操作如下: 1.首先选中a.b两列数据,在"开始"选项卡上选择"筛选&quo ...

  9. layui自定义ajax左侧三级菜单

    HTML代码: 需引入layui.css代码 <!-- 左侧的菜单 --> <div class="layui-side layui-bg-black" id=& ...

最新文章

  1. java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderL,spring获取context...
  2. 免费学python的网站-python自学网站
  3. TCP和UDP的区别(转)
  4. 高级开发必须理解的Java中SPI机制
  5. 推荐一款好工具:16进制字节搜索工具 C#的效率
  6. 字符串排序 墨迹了半天的自闭题目
  7. 使用Freemarker来页面静态化,与Spring整合使用
  8. 模拟ssh, hashlib模块, struct模块, subprocess模块
  9. CF1540B Tree Array(期望,dp)
  10. 【EOlymp - 2908】SumThem All(数位统计,tricks)
  11. 20165236 2017-2018-2 《Java程序设计》结对编程练习_四则运算
  12. mysql批量删除进程_小程序批量删除云数据库里的数据
  13. FireEye 红队失窃工具大揭秘之:分析复现 Confluence路径穿越漏洞 (CVE-2019-3398)
  14. 【Java】UDP Socket编程案例——文件传输聊天工具
  15. 判断图同构大杀器---nauty算法
  16. Linux操作系统 —— 普通用户无权限执行命令怎么办
  17. 浅谈屏幕适配 dp dip sp dpi ppi px sp
  18. OpenSSL自建CA和签发二级CA及颁发SSL证书
  19. Android Broadcast用法
  20. c语言通讯录按字母排序,c语言程序设计通讯录.docx

热门文章

  1. 【爬虫】百度新闻采集
  2. Win10 在 Visual Studio 2019 环境下配置 CUDA 10.1 + TensorFlow-GPU
  3. qpixmap mysql_将blob图像数据加载到QPixmap
  4. 服务器端脚本语言的比较
  5. OpenJudge 1058 Guideposts | BZOJ 3328 PYXFIB
  6. 有关“树上剩余几只鸟”的问题的思考及解答
  7. 多个视频时,利用函数实现播放一个,其他自动暂停
  8. 操作系统-读者写者问题(写者优先)
  9. android apk 的信息,Android中获取apk基本信息
  10. c语言socket+全双工,用Winsock实现语音全双工通信使用