http://blog.csdn.net/daihuimaozideren/article/details/78566757
不过没把cnpm设为global:
没写这句:
ng set --global packageManager=cnpm
ng new AngularTest
进入项目后(cd AngularTest)
ng serve 默认4200
写的很棒的入门小作品:
https://www.angular.cn/guide/quickstart#src%E6%96%87%E4%BB%B6%E5%A4%B9
和下面这个是一样的
http://yunkus.com/angular-tutorial-part5/
命名风格指南https://www.angular.cn/guide/styleguide#naming
npm i --save 包名: 安装软件依赖(工程目录下的package.json 里的dependencies)
nmp i --save-dev 包名:安装开发环境的依赖(工程目录下的package.json 里的devDependencies)
ng build -prod 生产环境编译 会压缩代码AOT之类的
npm install -g json-server 模拟后端接口
文件组织约定:
命名约定:
- 模块和组件的类文件都使用index.ts的命名约定
ng new taskmgr -si --style=scss
flex
<div class="site">
<header></header>
<main></main>
<footer></footer>
</div>
.site{
display: flex;
flex-direction: column;
}
main{
flex:1;
}
Flex 布局,可以简便、完整、响应式地实现各种页面布局。
Flexible Box 的缩写,意为”弹性布局”
Material风格UI组件库:
适合场景:缺少统一UI框架,且大家觉得这个不错,企业化,不要太多特效
优点:兼容性好,可扩展性强,可测试性好,对主题的支持好
缺点:目前组建不算丰富,只有Material风格
先安装Metarial:
进入项目,npm i –save @angular/material@latest (直接装最新版吧@5.2.2,但是发现有问题,http://www.bubuko.com/infodetail-2503040.html 还是换回低版本的吧,,npm i –save @angular/material@2.0.0-beta.7,还是不行,报错:ERROR in node_modules/@angular/material/autocomplete/typings/autocomplete-trigger.d.ts(8,32): error TS2307: Cannot find module ‘@angular/cdk/bidi’一堆,是不是缺少angular/cdk,安装个试试:npm i –save @angular/cdk,结果还是不行,
material2.0.0对应的是angualr/core4.4,我本地装的是angular5,要装material5.2.2,然后cdk版本对应的是@angualr/cdk@5.2.2,还要装ajv@^6.0.0)
然后还是挂,最后去material官网上找到了:https://material.angular.io/guide/getting-started
中文版:https://www.jianshu.com/p/4e05836e4f4c
感人了
SideNav:侧边栏导航
用侧边栏:要先把用到的MatSidenavModule放入app.module.ts:
import { MatSidenavModule } from '@angular/material';
imports:[
...,MatSidenavModule,...]
<mat-sidenav #sidenav mode="push">
mode有over,push,side
imports:导入其他模块,就是要使用其他模块的功能,必须要导入。
declarations:声明,声明本模块包含的内容。可能有些同学会遇到,定义了一个指令,在component中使用却总是没有生效的问题,首先我们要检查的就是是否进行了声明。
exports:外部可见的内容。相当于.net中声明为public的那些类。
providers:服务提供者,主要用来定义服务。估计ng2框架会自动将注册的服务体检到依赖注入实例中,目前测试也是如此。
bootstrap:启动模块。只在根模块使用。在除了根模块以外的其他模块不能使用。
md-icon:
使用图标字体,内建Metarial icon支持
支持svg:通过注入MdIconRegistry和DomSanitizer完成
this.iconRegistry.addSvgIcon(
'project',this.sanitizer.bypassSecurityTrustResourceUrl('assets/img/sidebar/project.svg')
);
用matIcon:
1.在core.module.ts里import MatIconModule 并 imports
2.在根目录的index.html里增加360的material镜像:
<link href="//lib.baomitu.com/material-design-icons/3.0.1/iconfont/material-icons.min.css" rel="stylesheet">
3.在header.component.html里:
<mat-toolbar color="primary">
<button (click)="openSidebar()">
<mat-icon>menu</mat-icon>
</button>
<span>XXX</span>
</mat-toolbar>
下一步是把button改造一下:
<button mat-icon-button (click)="openSidebar()">
<mat-icon>menu</mat-icon>
</button>
也要在core.module.ts里引入MatButtonModule才行
引入外部svg:
1.把要引入的svg放到assets/文件夹下
2.在core.module里引入:
import { HttpModule } from "@angular/http";
import { HttpClientModule } from "@angular/common/http";
imports:[
HttpModule,HttpClientModule,]
3.在header.module里:
import { MatIconRegistry } from '@angular/material';
import { DomSanitizer } from "@angular/platform-browser";
constructor(iconRegistry: MatIconRegistry,sanitizer: DomSanitizer) {
iconRegistry.addSvgIcon('gifts',sanitizer.bypassSecurityTrustResourceUrl('assets/gifts.svg'));
}
4.在header.component.html里
<mat-icon svgIcon="gifts"></mat-icon>
问题:
太零碎了,而且不知道svg文件使用的时候有没有被导入
在app/下创建utils
创建svg.util.ts:
import { MatIconRegistry } from '@angular/material';
import { DomSanitizer } from "@angular/platform-browser";
export const loadSvgResource = (ir: MatIconRegistry,ds: DomSanitizer)=>{
ir.addSvgIcon('gifts',ds.bypassSecurityTrustResourceUrl('assets/gifts.svg'));
}
core.module.ts:
import { MatIconRegistry } from '@angular/material';
import { DomSanitizer } from "@angular/platform-browser";
import { loadSvgResource } from "../utils/svg.util";
export class CoreModule {
constructor(@Optional() @SkipSelf() parent: CoreModule,ir: MatIconRegistry,ds: DomSanitizer){
if(parent){
throw new Error("模块已经存在,不能再次加载");
}
//调用工具类
loadSvgResource(ir,ds);
}
}
header.module.ts:
import { Component,OnInit,Output,EventEmitter } from '@angular/core';
@Component({
selector: 'app-header',templateUrl: './header.component.html',styleUrls: ['./header.component.scss']
})
export class HeaderComponent implements OnInit {
@Output() toggle = new EventEmitter<void>();
constructor() {
}
ngOnInit() {
}
openSidebar(){
this.toggle.emit();
}
}
把core.module.ts里的模块抽出来,放到shared里:
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import {
MatToolbarModule,MatIconModule,MatButtonModule,MatCardModule,MatInputModule } from "@angular/material";
@NgModule({
imports: [
CommonModule,MatToolbarModule,MatInputModule,],exports: [
CommonModule,declarations: []
})
export class SharedModule { }
core:
import { SharedModule } from "../shared/shared.module";
imports: [
CommonModule,HttpModule,SharedModule,
路由:
在login/下新建login-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule,Routes } from '@angular/router';
import { LoginComponent } from "./login/login.component";
const routes: Routes = [
{ path: 'login',component: LoginComponent }
];
@NgModule({
imports: [ RouterModule.forChild(routes)],exports: [RouterModule]
})
export class LoginRoutingModule {}
app文件夹下新建app-routing.module.ts:
import { NgModule } from '@angular/core';
import { RouterModule,Routes } from '@angular/router';
import { AppComponent } from "./app.component";
const routes: Routes = [
{ path: '',redirectTo:'/login',pathMatch:'full' },];
@NgModule({
imports: [ RouterModule.forRoot(routes)],exports: [RouterModule]
})
export class AppRoutingModule {}
app.module.ts更新:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { MatSidenavModule } from '@angular/material';
import { CoreModule } from "./core/core.module";
import { AppRoutingModule } from "./app-routing.module";
import { AppComponent } from './app.component';
import { LoginModule } from './login/login.module';
@NgModule({
declarations: [
AppComponent
],imports: [
BrowserModule,CoreModule,AppRoutingModule,LoginModule
],providers: [],bootstrap: [AppComponent]
})
export class AppModule { }
core.module.ts更新:
import { NgModule,SkipSelf,Optional } from '@angular/core';
import { HttpModule } from "@angular/http";
import { HttpClientModule } from "@angular/common/http";
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MatIconRegistry } from '@angular/material';
import { DomSanitizer } from "@angular/platform-browser";
import { SharedModule } from "../shared/shared.module";
import { loadSvgResource } from "../utils/svg.util";
import { HeaderComponent } from './header/header.component';
import { FooterComponent } from './footer/footer.component';
import { SidebarComponent } from './sidebar/sidebar.component';
@NgModule({
imports: [
HttpModule,BrowserAnimationsModule,declarations: [
HeaderComponent,FooterComponent,SidebarComponent,exports: [
HeaderComponent,SidebarComponent
]
})
export class CoreModule {
constructor(@Optional() @SkipSelf() parent: CoreModule,ds);
}
}
注意:要在app.module里import login.module,不然会报错:
Uncaught (in promise): Error: Cannot match any routes.
input:
mdInput在<md-input-container>内部,有前缀后缀,
<md-error>只有验证不通过时出现,对两种类型表单都如此
<md-hint>:当error显示时,hint会隐藏
<mat-card>
<mat-card-header>
<mat-card-title>登录:</mat-card-title>
</mat-card-header>
<mat-card-content>
<mat-input-container color="accent" floatPlaceholder="always/nerver/float" hintLabel="必填项" align="end> <span matPrefix>wang</span> <input matInput type="text" placeholder="您的email">
<span matSuffix>@gmail.com</span>
<mat-hint>必填项</mat-hint>#这个和hintLabel只要写一个
<mat-error></mat-error>
</mat-input-container>
</mat-card-content>
<mat-card-actions>
<p>还没有账户?<a href="">注册</a></p>
<p>忘记密码?<a href="">找回</a></p>
</mat-card-actions>
</mat-card>
card:
适合图文形式突出某一主题
Button:
标准按钮:md-button,md-raised-button,md-icon-button
浮动按钮:md-fab,md-mini-fab
<form>
<mat-card>
<mat-card-header>
<mat-card-title>登录:</mat-card-title>
</mat-card-header>
<mat-card-content>
<mat-input-container
color="primary"
floatPlaceholder="float" class="full-width">
<input matInput type="text" placeholder="您的email">
</mat-input-container>
<mat-input-container
color="primary"
floatPlaceholder="float" class="full-width">
<input matInput type="password"
placeholder="您的密码">
</mat-input-container>
<button mat-raised-button type="button">登录</button>
</mat-card-content>
<mat-card-actions class="text-right">
<p>还没有账户?<a href="">注册</a></p>
<p>忘记密码?<a href="">找回</a></p>
</mat-card-actions>
</mat-card>
<mat-card>
<mat-card-header>
<mat-card-title>每日佳句</mat-card-title>
</mat-card-header>
<mat-card-subtitle>
满足感在于不断的努力,而不是现有成就,全新努力定会胜利满满。
</mat-card-subtitle>
<img mat-card-image src="/assets/quote_fallback.jpg" alt="">
<mat-card-content>
Satisfaction lies in the effort,not in the attainment. Full effort is full victim.
</mat-card-content>
</mat-card>
</form>
login.component.scss:
mat-card{
height: 25em;
flex: 0 0 20em;
}
form{
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
}
.text-right{
margin: 10px;
text-align: end;
}
styles.scss:
加
.full-width{
width: 100%;
}
sidebar:
sidebar.component.html:
<mat-nav-list><!-- 加dense是压缩列表 -->
<h3 mat-subheader>项目</h3>
<mat-list-item>
<mat-icon mat-list-icon svgIcon="projects"></mat-icon>
<span mat-line>项目首页</span>
<span mat-line mat-subheader>查看您的所有项目</span>
</mat-list-item>
<h3 mat-subheader>日历</h3>
<mat-list-item>
<mat-icon mat-list-icon svgIcon="month"></mat-icon>
<span mat-line>月视图</span>
<span mat-line mat-subheader>按月查看您的任务</span>
</mat-list-item>
<mat-list-item>
<mat-icon mat-list-icon svgIcon="week"></mat-icon>
<span mat-line>周视图</span>
<span mat-line mat-subheader>按周查看您的任务</span>
</mat-list-item>
<mat-list-item>
<mat-icon mat-list-icon svgIcon="day"></mat-icon>
<span mat-line>日视图</span>
<span mat-line mat-subheader>按天查看您的任务</span>
</mat-list-item>
</mat-nav-list>
sidebar.component.scss:
mat-icon{
align-self: flex-start;
}
app.component.scss:
mat-sidenav{
width: 300px;
}
增加当前日期:
npm install --save date-fns
npm install --save-dev types/date-fns
sidebar.component.ts:
import { Component,OnInit } from '@angular/core';
import { getDate } from "date-fns";
@Component({
selector: 'app-sidebar',templateUrl: './sidebar.component.html',styleUrls: ['./sidebar.component.scss']
})
export class SidebarComponent implements OnInit {
today = 'day';
constructor() { }
ngOnInit() {
this.today = `day${getDate(new Date())}`;
}
}
svg.util.ts改成:
export const loadSvgResource = (ir: MatIconRegistry,ds: DomSanitizer)=>{
const imgDir = 'assets/img';
const sidebarDir = `${imgDir}/sidebar`;
const dayDir = `${imgDir}/days`;
ir.addSvgIcon('day',ds.bypassSecurityTrustResourceUrl(`${sidebarDir}/day.svg`));
ir.addSvgIcon('month',ds.bypassSecurityTrustResourceUrl(`${sidebarDir}/month.svg`));
ir.addSvgIcon('project',ds.bypassSecurityTrustResourceUrl(`${sidebarDir}/project.svg`));
ir.addSvgIcon('projects',ds.bypassSecurityTrustResourceUrl(`${sidebarDir}/projects.svg`));
ir.addSvgIcon('week',ds.bypassSecurityTrustResourceUrl(`${sidebarDir}/week.svg`));
const days = [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];
days.forEach(d => ir.addSvgIcon(`day${d}`,ds.bypassSecurityTrustResourceUrl(`${dayDir}/day${d}.svg`)));
}
sidebar.component.ts:把svgIcon那里改一下
<mat-list-item>
<mat-icon mat-list-icon [svgIcon]="today"></mat-icon>
<span mat-line>日视图</span>
<span mat-line mat-subheader>按天查看您的任务</span>
</mat-list-item>