[转]玩转Angular2(4)--制作左侧自动定位菜单
本文转自: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代码,也可以通过配置实现。
- 抽离依赖
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里
}
|
- 将样式从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: 判断该菜单下是否有子菜单的路由处于激活状态
这里我们需要注意的是:
- 使用angular自带的常用指令,像
*ngFor、ngClass等,需要在注册@NgModule时引入CommonModule。 - 使用angular里面路由常用指令,像
[routerLink]、routerLinkActive等,需要在注册@NgModule时引入RouterModule。 - 使用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
[转]玩转Angular2(4)--制作左侧自动定位菜单的更多相关文章
- MVC4做网站后台:栏目管理3、删除栏目与左侧列表菜单
一.左侧列表菜单 打开视图Menu.cshtml,增加部分见红框 在category中添加脚本 //栏目菜单加载完毕函数 function CategoryMenu_Ready() { $('#cat ...
- Ecshop 后台增加一个左侧列表菜单menu菜单的方法
Ecshop 后台增加一个左侧列表菜单menu菜单需要修改三个文件:/admin/includes/inc_menu.php/admin/includes/inc_priv.php/languages ...
- 后台增加一个左侧列表菜单menu菜单的方法
Ecshop 后台增加一个左侧列表菜单menu菜单需要修改三个文件:/admin/includes/inc_menu.php/admin/includes/inc_priv.php/languages ...
- jQuery+Superfish制作下拉菜单
superfish制作下拉菜单真的很方便而好很好用,而且还可以通过Superfish提供的参数来控制下拉菜单的不同效果,而且他没有层级限制,换句话说可以通过Superfish来写你想要的层级菜单. 官 ...
- jquery仿天猫商城左侧导航菜单
之前看到有博友写了一个仿天猫商城左侧导航菜单,可惜不提供免费下载,也没有代码.以前自己也写过类似的效果,只是都是一小块一小块的,现在重新拼凑.我将一步一步的实现拼凑过程,希望对你有所帮助. Demo在 ...
- 制作下拉菜单(PopupList)
怎样判断是否应当使用下拉菜单 下拉菜单,就是将一系列的选项隐藏,通过单击某一个控件将会弹出一个包含这些选项的列表,在其中选择想要的选项.这样做不但可以节省屏幕空间,也可以让用户在进行选择时更加方便快捷 ...
- 使用 EasyUI 创建左侧导航菜单
使用 JQuery EasyUI 创建左侧导航菜单,菜单的数据由后台服务提供. 效果图 HTML 元素 <div id="menuAccordion"></div ...
- 【转】Ecshop 后台增加一个左侧列表菜单menu菜单的方法
cshop 后台增加一个左侧列表菜单menu菜单需要修改三个文件:/admin/includes/inc_menu.php/admin/includes/inc_priv.php/languages/ ...
- wemall doraemon中Android app商城系统解决左侧抽屉菜单和viewpager不能兼容问题
完美解决左侧抽屉菜单和viewpager不能兼容左右滑动的问题,可进行参考. WeMall-Client/res/layout/wemall_main_ui.xml </RadioGroup&g ...
随机推荐
- python xss相关的编码解码小脚本
1.功能分析: 实际工作中经常会遇到alert()之类的函数被防火墙过滤,而把alert()转化为ascii码放到String.fromCharCode()中就可以绕过,之前会一个一个查ascii表, ...
- vue的学习之路
一.vs code中,适合vue的前端插件 查看网址:http://blog.csdn.net/caijunfen/article/details/78749766 二.如何使用git从gitub上拉 ...
- Windows-WMI 事件 ID 10或0x80041003 死机 解药
最近笔记本重复了好几次奇怪的现象,重启后进入桌面,然后死机,木有蓝屏. 后来在安全模式里查了事件,如下 日志名称: Application 来源: Micros ...
- JVM指令集
指令集,其实就是一系列指令的集合.例如我们需要给一个局部变量赋予1这个值,即这个动作:int a = 1; 在我们看来,这很简单,但对于机器来说需要很多个动作.所以Java虚拟机指令集就是将这些常用的 ...
- Python 列表详细使用
1. 列表 列表是Python中内置有序.可变序列,列表的所有元素放在一对中括号“[]”中,并使用逗号分隔开: 当列表元素增加或删除时,列表对象自动进行扩展或收缩内存,保证元素之间没有缝隙: 在Pyt ...
- 微信小程序实现标签页滑块效果
微信小程序实现标签页滑块效果 小程序完整代码: wxml: <view class="swiper-tab"> <view class="swiper- ...
- Scala - 快速学习08 - 函数式编程:高阶函数
函数式编程的崛起 函数式编程中的“值不可变性”避免了对公共的可变状态进行同步访问控制的复杂问题,能够较好满足分布式并行编程的需求,适应大数据时代的到来. 函数是第一等公民 可以作为实参传递给另外一个函 ...
- 阿里启动新项目:Nacos,比 Eureka 更强!
什么是 Nacos? Nacos 是阿里巴巴推出来的一个新开源项目,这是一个更易于构建云原生应用的动态服务发现.配置管理和服务管理平台. Nacos 致力于帮助您发现.配置和管理微服务.Nacos 提 ...
- [原创]K8PackWebShell ASPX整站打包工具
[原创]K8PackWebShell ASPX整站打包工具[K.8](有无Rar执行权限都可以) 2011-06-11 01:49:21| 分类: 原创工具 Name: K8PackWebShell ...
- oracle 锁表 and 解锁
查询锁定表的相关 SELECT l.session_id sid, s.serial#, l.locked_mode,l.oracle_username, l.os_user_name,s.machi ...