欢迎各位兄弟 发布技术文章
这里的技术是共享的
1-1 Angular打造企业平台导学
需要的基础知识
1-2 环境搭建
使用淘宝镜像 (cnpm 的 c 是 sync 的意思) (i 是intall 安装的意思)
# npm i -g cnpm
安装脚手架 angular/cli @表示范围的意思
快速构建应用,而不用繁琐的进行配置
# cnpm i -g @angular/cli
$ ng --version
_ _ ____ _ ___
/ \ _ __ __ _ _ _| | __ _ _ __ / ___| | |_ _|
/ △ \ | '_ \ / _` | | | | |/ _` | '__| | | | | | |
/ ___ \| | | | (_| | |_| | | (_| | | | |___| |___ | |
/_/ \_\_| |_|\__, |\__,_|_|\__,_|_| \____|_____|___|
|___/
Angular CLI: 8.3.2
Node: 10.16.0
OS: win32 x64
Angular:
...
Package Version
------------------------------------------------------
@angular-devkit/architect 0.803.2
@angular-devkit/core 8.3.2
@angular-devkit/schematics 8.3.2
@schematics/angular 8.3.2
@schematics/update 0.803.2
rxjs 6.4.0
Administrator@Carl MINGW64 ~
指定版本号的安装
$ cnpm i -g @angular/cli@1.1.0
$ ng new 新建一个子项目
$ ng build 构建一个项目
$ ng test 进行测试
https://code.visualstudio.com/ 下载
安装 vs code
扩展
http://chrome-extension-downloader.com 同样是 chrome 的扩展商店吧
我还是使用的chrome的商店
几个常用命令
Mock Rest API
构建服务端的API的数据
# 安装 json-server
npm install -g json-server
cmd 命令行执行启动服务
json-server ./mock/data.json
https://www.getpostman.com 下载 postman
postman 是api测试工具
rest client 也是是api测试工具,通过纯文本来描述这种请求 rest.http
如果出现错误
npm uninstall -g @angular/cli
npm cache clean
npm install -g @angular/cli
2-1 项目工程结构介绍
(--skip-install ( 可以简写为 -si )会跳过npm依赖的安装,速度会很快)
ng new taskmgr --skip-install --style=scss
打开 vs code
在 vs code 的命令终端
# cnpm install 出错
还是使用
# npm install 吧
# ng g m core ( g就是 generate 产生的意思, 就是module的意思) 这里安装(创建)核心模块
# ng g m shared ( g就是 generate 产生的意思, 就是module的意思) 这里安装(创建)共享模块
2-2 UI整体布局
# ng g c core/header --spec=false (c 表示组件components --spec=false表示不想使用测试)
# ng g c core/footer --spec=false (c 表示组件components --spec=false表示不想使用测试)
# ng g c core/sidebar --spec=false (c 表示组件components --spec=false表示不想使用测试)
//启动 ng 服务
# ng serve
2-3 Material介绍
https://material.io/components/
material示例的著名的优秀站点
http://materialdesignblog.com/material-design-showcase/
安装 @angular/material
# npm i --save @angular/material@2.0.0-beta.7
我使用的是 下面的安装方法
#npm i --save @angular/material
https://material.io/color 为什么我这边是404 而人家的可以打开?
https://material.io/resources/color/#!/?view.left=0&view.right=0 这个可以打开
2-4 MdIcon 组件
图标字体 在里面可以直接找图标
https://material.io/resources/icons/?style=baseline
阿里巴巴矢量图标库
2-5 Input 组件
创建一个login的模块
# ng g m login
在login下创建一个叫login的组件
# ng g c login/login --spec=false (c 表示组件components --spec=false表示不想使用测试)
是不是要安装 @angular/animations 因为 material 的很多控件有动画
# npm install --save @angular/animations
2-6 Card 和 Button 组件
2-7 在侧滑菜单中使用 MdList
这里 安装javascript?
# npm install --save date-fns
这里是安装把javascript转为typescript?
# npm i --save-dev @types/date-fns
2-8 Angular Material 主题
@import '~@angular/material/prebuilt-themes/deeppurple-amber.css';
可以自定义主题 theme.scss是自定义的文件
@import 'theme.scss'
https://www.materialpalette.com
2-9 GridList 打造注册页面头像列表
# ng g c login/register --spec-false
2-10 对话框的使用
# ng g m project
$ ng g c projetc/project-list
2-11 Autocomplete 的使用
2-12 任务列表之菜单
# ng g m task
# ng g c task/task-home --spec=false
# ng g c task/task-list --spec=false
# ng g c task/task-item --spec=false
# ng g c task/task-header --spec=false
2-13 任务列表之任务组件
2-14 任务列表之新任务对话框
# ng g c task/new-task --spec=false
2-15 任务列表之移动内容对话框
# ng g c task/copy-task --spec=false
2-16 完成主框架(上)
# ng g c shared/confirm-dialog -it -is --spec=false ( -it 表示 --inline templete 内联式的模板, -is 表示 --inline style 内联式的style)
2-17 完成主框架(下)
# ng g c task/new-task-list --spec=false
# npm install hammerjs --save ( hammerjs 是为了处理移动端的)
为什么使用下面的就会报错,( 把--save放在前面就会报错 )
# npm install --save hammerjs
npm ERR! code EINVALIDTAGNAME
npm ERR! Invalid tag name "": Tags may not have any characters that encodeURIComponent encodes.
npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\Administrator\AppData\Roaming\npm-cache\_logs\2019-09-20T06_47_44_724Z-debug.log
3-1 初识 Angular Animation
animation 动画
https://www.w3.org/TR/web-animations-1/
# npm i --save @angular/animations ( i 就是 install 安装的意思 )
3-2 缓动函数和关键帧
缓动函数两个网站
https://cubic-bezier.com/ ( https://cubic-bezier.com/#.07,.56,.86,.64 )
3-3 项目卡片和任务动画
3-4 路由动画及高阶动画函数
4-1 依赖性注入
4-2 ChangeDetection
4-3 打造支持拖拽的属性型指令
# ng g m directive
# ng g d directive/drag --spec=false (这里 d 表示 directive 指令的意思 ,,,,)
# ng g d directive/drop --spec=false
# ng g s directive/drag-drop ( 这里 s 表示 service 服务 )
4-4 结构型指令、模块和样式
entryComponents : 是预先编译初始化(比如对话框,不是在模板里面的,是预先编译留给别人调用的)
exports: 模块里面的组件希望给大家共用的,要exports出来,否则别人没法使用,默认情况下declarations 里面的组件只能是自己模块使用
forRoot() : 第三方库及自带的库,比如 route (不仅有forRoot() 还有forChild() )
# ng g m services
4-5 模板驱动型表单处理
# ng g c task/quick-task --spec=false
4-6 响应式表单处理和自定义表单控件(上)
响应式表单 其实也叫模型驱动型表单
4-7 响应式表单处理和自定义表单控件(下)
# ng g c shared/image-list-select --spec=false
5-1 RxJS帮你走进响应式编程的世界
rxjs 官网
网页编辑器 rxjs
http://jsbin.com/qawivar/edit?html,js,console,output qawivar 好像是视频作者的
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div><input type="nubmer" id="height"></div>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
const height = document.getElementById('height');
const height$ = Rx.Observable.fromEvent(height,'keyup');
height$.subscribe(val => console.log(val.target.value));
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div><input type="text" id="length"></div>
<div><input type="text" id="width"></div>
<div id="area"></div>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
const length = document.getElementById('length');
const width = document.getElementById('width');
const area = document.getElementById('area');
const length$ = Rx.Observable.fromEvent(length,'keyup').pluck('target','value');
const width$ = Rx.Observable.fromEvent(width,'keyup').pluck('target','value');
const area$ = Rx.Observable.combineLatest(length$,width$,(l,w)=>{return l*w; });
area$.subscribe(val=> area.innerHTML = val);
combineLatest (取最新的值) 改成 zip (就是两个新值是成对出现,只出现一个新值的话,结果不变)
5-2 常见操作符(一)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div><input type="text" id="length"></div>
<div><input type="text" id="width"></div>
<div id="area"></div>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
const length = document.getElementById('length');
const width = document.getElementById('width');
const area = document.getElementById('area');
const length$ = Rx.Observable.fromEvent(length,'keyup').map(ev=>ev.target.value);
const width$ = Rx.Observable.fromEvent(width,'keyup').map(ev=>ev.target.value);
const area$ = Rx.Observable.combineLatest(length$,width$,(l,w)=>{return l*w; });
area$.subscribe(val=> area.innerHTML = val);
mapTo(1) 常量 1
mapTo(2) 常量 2
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div><input type="text" id="length"></div>
<div><input type="text" id="width"></div>
<div id="area"></div>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
const length = document.getElementById('length');
const width = document.getElementById('width');
const area = document.getElementById('area');
const length$ = Rx.Observable.fromEvent(length,'keyup').mapTo(1);
// const length$ = Rx.Observable.fromEvent(length,'keyup').map(_=>1);
const width$ = Rx.Observable.fromEvent(width,'keyup').mapTo(2);
//const width$ = Rx.Observable.fromEvent(width,'keyup').map(_=>2);
const area$ = Rx.Observable.combineLatest(length$,width$,(l,w)=>{return l*w; });
area$.subscribe(val=> area.innerHTML = val);
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div><input type="text" id="length"></div>
<div><input type="text" id="width"></div>
<div id="area"></div>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
const length = document.getElementById('length');
const width = document.getElementById('width');
const area = document.getElementById('area');
const length$ = Rx.Observable.of({id:1,value:20});
const width$ = Rx.Observable.fromEvent(width,'keyup').mapTo(2);
const area$ = Rx.Observable.combineLatest(length$,width$,(l,w)=>{return l.value*w; });
area$.subscribe(val=> area.innerHTML = val);
# json-server ./mock/data.json
http://localhost:3000/quotes/1
5-3 常见操作符(二)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
const interval$ = Rx.Observable.interval(100);
interval$.subscribe(val=> console.log(val))
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
const interval$ = Rx.Observable.interval(100).take(3);
interval$.subscribe(
val=> console.log(val),
err=> console.log(err),
()=>console.log('I am complete')
)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
const interval$ =
Rx.Observable.interval(100).take(3);
const timer$ =
Rx.Observable.timer(100);
timer$.subscribe( v => console.log(v));
// interval$.subscribe(
// function(val) {
// console.log(val)
// },
// function (err) {
// console.log(err)
// },
// function () {
// console.log('I am complete')
// }
// )
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
const interval$ =
Rx.Observable.interval(100).take(3);
const timer$ =
Rx.Observable.timer(100,100);
timer$.subscribe( v => console.log(v));
// interval$.subscribe(
// function(val) {
// console.log(val)
// },
// function (err) {
// console.log(err)
// },
// function () {
// console.log('I am complete')
// }
// )
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
const interval$ =
Rx.Observable.interval(100)
.map(val => val*2)
.do(v => console.log('val is '+ v))
.take(3);
interval$.subscribe(
(val) =>console.log(val),
function (err) {
console.log(err)
},
function () {
console.log('I am complete')
}
)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
let logLabel = '当前值是';
const interval$ =
Rx.Observable.interval(100)
.map(val => val*2)
.do(v => {
console.log( logLabel + v);
logLabel = '当前'
})
.take(3);
interval$.subscribe(
(val) =>console.log(val),
function (err) {
console.log(err)
},
function () {
console.log('I am complete')
}
)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
let logLabel = '当前值是';
const interval$ =
Rx.Observable.interval(100)
.filter(val => val % 2 === 0)
.do(v => {
console.log( logLabel + v);
logLabel = '当前'
})
.take(3);
interval$.subscribe(
(val) =>console.log(val),
function (err) {
console.log(err)
},
function () {
console.log('I am complete')
}
)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
let logLabel = '当前值是';
const interval$ =
Rx.Observable.interval(100)
.filter(val => val % 2 === 0)
.first();
// .first() 就相当于 take(1)
interval$.subscribe(
(val) =>console.log(val),
function (err) {
console.log(err)
},
function () {
console.log('I am complete')
}
)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
let logLabel = '当前值是';
const interval$ =
Rx.Observable.interval(100)
.filter(val => val % 2 === 0)
.last();
//last() 时 就是 never ,因为它是一个无穷序列,就是人为制造了一个empty
interval$.subscribe(
(val) =>console.log(val),
function (err) {
console.log(err)
},
function () {
console.log('I am complete')
}
)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
let logLabel = '当前值是';
const interval$ =
Rx.Observable.interval(100)
.filter(val => val % 2 === 0)
.skip(2);
interval$.subscribe(
(val) =>console.log(val),
function (err) {
console.log(err)
},
function () {
console.log('I am complete')
}
)
scan((x,y)=>{return x+y } ,,,,,,,,,,,x 表示累加器的值,把x+y累加器的值赋给x;;y是每次发射的值
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
let logLabel = '当前值是';
const interval$ =
Rx.Observable.interval(100)
.filter(val => val % 2 === 0)
.scan((x,y)=>{ return x+y; })
.take(4);
interval$.subscribe(
(val) =>console.log(val),
function (err) {
console.log(err)
},
function () {
console.log('I am complete')
}
)
reduce 是把序列当中所有的东西,做最后一个累加值,只出来最后一个值,
(因为这里它是一个无限的序列,所以算不出来,又制造了一个 never)
而scan是每次做叠加时,都会发射出来一个item
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
let logLabel = '当前值是';
const interval$ =
Rx.Observable.interval(100)
.filter(val => val % 2 === 0)
.reduce((x,y)=>{ return x+y; })
.take(4);
interval$.subscribe(
(val) =>console.log(val),
function (err) {
console.log(err)
},
function () {
console.log('I am complete')
}
)
与 scan运算是一样的,只算一个最终值,只发射最终值
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
let logLabel = '当前值是';
const interval$ =
Rx.Observable.interval(100)
.filter(val => val % 2 === 0)
.take(4)
.reduce((x,y)=>{ return x+y; })
;
interval$.subscribe(
(val) =>console.log(val),
function (err) {
console.log(err)
},
function () {
console.log('I am complete')
}
)
reduce 第一个参数是匿名函数,第二个参数是 x的初始值,x的初始值默认为 0 吧
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
let logLabel = '当前值是';
const interval$ =
Rx.Observable.interval(100)
.filter(val => val % 2 === 0)
.take(4)
.reduce((x,y)=>{ return [...x,y];},[]);
interval$.subscribe(
(val) =>console.log(val),
function (err) {
console.log(err)
},
function () {
console.log('I am complete')
}
)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
let logLabel = '当前值是';
const interval$ =
Rx.Observable.interval(100)
.map(val =>{
throw '出错了'
})
.take(4)
.reduce((x,y)=>{ return [...x,y];},[]);
interval$.subscribe(
(val) =>console.log(val),
function (err) {
console.log("Error"+err);
},
function () {
console.log('I am complete')
}
)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
let logLabel = '当前值是';
const interval$ =
Rx.Observable.never();
interval$.subscribe(
(val) =>console.log(val),
function (err) {
console.log("Error"+err);
},
function () {
console.log('I am complete')
}
)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
let logLabel = '当前值是';
const interval$ =
Rx.Observable.throw('出差了');
interval$.subscribe(
(val) =>console.log(val),
function (err) {
console.log("Error"+err);
},
function () {
console.log('I am complete')
}
)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
let logLabel = '当前值是';
const interval$ =
Rx.Observable.empty();
interval$.subscribe(
(val) =>console.log(val),
function (err) {
console.log("Error"+err);
},
function () {
console.log('I am complete')
}
)
5-4 常见操作符(三)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div><input type="nubmer" id="length"></div>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
const length = document.getElementById('length');
const length$ = Rx.Observable.fromEvent(length,'keyup').pluck('target','value')
.debounceTime(300);
length$.subscribe(val=> console.log(val));
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div><input type="nubmer" id="length"></div>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
const length = document.getElementById('length');
const length$ = Rx.Observable.fromEvent(length,'keyup')
.pluck('target','value')
.debounce(()=>Rx.Observable.interval(300));
length$.subscribe(val=> console.log(val));
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div><input type="nubmer" id="length"></div>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
const length = document.getElementById('length');
const length$ = Rx.Observable.fromEvent(length,'keyup')
.pluck('target','value')
.distinct();//不跟流以前所有的重复
length$.subscribe(val=> console.log(val));
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div><input type="nubmer" id="length"></div>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
const length = document.getElementById('length');
const length$ = Rx.Observable.fromEvent(length,'keyup')
.pluck('target','value')
.distinctUntilChanged();//不跟上一个重复
length$.subscribe(val=> console.log(val));
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div><input type="nubmer" id="length"></div>
<div><input type="nubmer" id="width"></div>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
const length = document.getElementById('length');
const width = document.getElementById('width');
const length$ = Rx.Observable.fromEvent(length,'keyup')
.pluck('target','value');
const width$ = Rx.Observable.fromEvent(width,'keyup')
.pluck('target','value');
const merged$ = Rx.Observable.merge(length$,width$);//按照时间顺序输出两个流
merged$.subscribe(val=> console.log(val));
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div><input type="nubmer" id="length"></div>
<div><input type="nubmer" id="width"></div>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
const length = document.getElementById('length');
const width = document.getElementById('width');
const length$ = Rx.Observable.fromEvent(length,'keyup')
.pluck('target','value');
const width$ = Rx.Observable.fromEvent(width,'keyup')
.pluck('target','value');
const merged$ = Rx.Observable.concat(length$,width$)// concat 是先输出第一个所有流,再输出第二个所有流
merged$.subscribe(val=> console.log(val));
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div><input type="nubmer" id="length"></div>
<div><input type="nubmer" id="width"></div>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
const length = document.getElementById('length');
const width = document.getElementById('width');
const length$ = Rx.Observable.fromEvent(length,'keyup')
.pluck('target','value');
const width$ = Rx.Observable.fromEvent(width,'keyup')
.pluck('target','value');
const first$ = Rx.Observable.from([1,2,3,4]);
const merged$ = Rx.Observable.concat(first$,width$);// concat 是先输出第一个所有流,再输出第二个所有流
merged$.subscribe(val=> console.log(val));
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div><input type="nubmer" id="length"></div>
<div><input type="nubmer" id="width"></div>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
const length = document.getElementById('length');
const width = document.getElementById('width');
const length$ = Rx.Observable.fromEvent(length,'keyup')
.pluck('target','value');
const width$ = Rx.Observable.fromEvent(width,'keyup')
.pluck('target','value');
const first$ = Rx.Observable.from([1,2,3,4])
.startWith(0); //就是在前面添加一个值;通常用来赋初始值,并且让一开始流是没有值的?
const merged$ = Rx.Observable.concat(first$,width$);
merged$.subscribe(val=> console.log(val));
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div><input type="nubmer" id="length"></div>
<div><input type="nubmer" id="width"></div>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
const length = document.getElementById('length');
const width = document.getElementById('width');
const length$ = Rx.Observable.fromEvent(length,'keyup')
.pluck('target','value');
const width$ = Rx.Observable.fromEvent(width,'keyup')
.pluck('target','value');
const merged$ = Rx.Observable
.combineLatest(length$,width$,(l,w)=>l*w);
merged$.subscribe(val=> console.log(val));
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div><input type="nubmer" id="length"></div>
<div><input type="nubmer" id="width"></div>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
const length = document.getElementById('length');
const width = document.getElementById('width');
const length$ = Rx.Observable.fromEvent(length,'keyup')
.pluck('target','value');
const width$ = Rx.Observable.fromEvent(width,'keyup')
.pluck('target','value');
const merged$ = Rx.Observable
.zip(length$,width$,(l,w)=>l*w); //一一相对的,第一流的第一值与第二个流的第一个值 相乘,第一流的第二值与第二个流的第二个值 相乘,以此类推, 最慢的流决定最终的速度
merged$.subscribe(val=> console.log(val));
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div><input type="nubmer" id="length"></div>
<div><input type="nubmer" id="width"></div>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
const length = document.getElementById('length');
const width = document.getElementById('width');
const length$ = Rx.Observable.fromEvent(length,'keyup')
.pluck('target','value');
const width$ = Rx.Observable.fromEvent(width,'keyup')
.pluck('target','value');
const merged$ = length$
.withLatestFrom(width$); //以第一个流length$为主流,监听主流的变化,组成一个数组
merged$.subscribe(val=> console.log(val));
5-5 实战复杂表单控件(上)
# ng g c shared/age-input --spec=false
5-6 实战复杂表单控件(中)
5-7 实战复杂表单控件(下)
6-1 高阶操作符
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div><input type="text" id="length"></div>
<div><input type="text" id="width"></div>
<div id="area"></div>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
const length = document.getElementById('length');
const width = document.getElementById('width');
const length$ = Rx.Observable
.fromEvent(length,'keyup')
.pluck('target','value')
.map(_=>Rx.Observable.interval(100));
length$.subscribe(val=>{
console.log(val);
})
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div><input type="text" id="length"></div>
<div><input type="text" id="width"></div>
<div id="area"></div>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
const length = document.getElementById('length');
const width = document.getElementById('width');
const length$ = Rx.Observable
.fromEvent(length,'keyup')
.pluck('target','value')
.map(_=>Rx.Observable.interval(100));
length$.subscribe(val=>{
val.subscribe( v => console.log(v));
})
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div><input type="text" id="length"></div>
<div><input type="text" id="width"></div>
<div id="area"></div>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
const length = document.getElementById('length');
const width = document.getElementById('width');
const length$ = Rx.Observable
.fromEvent(length,'keyup')
.pluck('target','value')
.flatMap(_=>Rx.Observable.interval(100)); //两个流交替进行
length$.subscribe(val=> console.log(val));
flatMap 就是 mergeMap 的别名
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div><input type="text" id="length"></div>
<div><input type="text" id="width"></div>
<div id="area"></div>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
const length = document.getElementById('length');
const width = document.getElementById('width');
const length$ = Rx.Observable
.fromEvent(length,'keyup')
.pluck('target','value')
.switchMap(_=>Rx.Observable.interval(1000)); // switchMap 是当第二个流时,第一个流断掉了
length$.subscribe(val=> console.log(val));
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div><input type="text" id="length"></div>
<div><input type="text" id="width"></div>
<div id="area"></div>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
const length = document.getElementById('length');
const width = document.getElementById('width');
const length$ = Rx.Observable
.fromEvent(length,'keyup')
.pluck('target','value')
.mergeMap(_=>Rx.Observable.interval(1000)); // mergeMap 与 flatMap 一样,交替进行的流输出来
length$.subscribe(val=> console.log(val));
https://rxjs-dev.firebaseapp.com/api/operators/mergeMap
http://reactivex.io/rxjs/class/es6/Subject.js~Subject.html 好像不是
https://rxjs-dev.firebaseapp.com/api/operators/switchMap
# json-server ./mock/data.json --watch (--watch 观察的意思,就是 data.json改动的话,会发映到服务器里面)
6-2 实战服务逻辑(上)
6-3 实战服务逻辑(中)
# npm i --save lodash (javascript 里面提供的类库,专门处理数据,对像的一些提供了很多扩展的方法)
# npm i --save-dev @types/lodash (还要装它这个类型)
# json-server ./mock/data.json
# json-server ./mock/data.json --watch
6-4 实战服务逻辑(下)
6-5 实战自动建议表单控件
# ng g c shared/chips-list --spec=false
6-6 Observable 的冷和热以及 Subject
冷: 看视频,你先看,我也看视频,我是从头开始看的,,,,
热: 看央视直播,你先看,我也看央视直播,咱们看到的内容是一模一样的
subject 既是观察者,又是被观察对象
.同时实现了 Obervable 和 Observe
ReplaySubject 保留最新的n个值
BehaviorSubject 是ReplaySubject的一种特殊形式 保留最新的一个值
https://jsbin.com/?html,js,output
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
const count$ =
Rx.Observable.interval(1000);
const sub1 = count$.subscribe(
val=>console.log(val));
setTimeout(function(){
const sub2 = count$.subscribe(
val=>console.log(val));
},2000);
以前上冷Observable(从头开始)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
const count$ =
Rx.Observable.interval(1000).share();
const sub1 = count$.subscribe(
val=>console.log(val));
setTimeout(function(){
const sub2 = count$.subscribe(
val=>console.log(val));
},2000);
热的 Observable
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
const counter$ =
Rx.Observable.interval(1000).take(5);
const subject = new Rx.Subject();
const observer1 = {
next: (val)=>console.log("l:"+val),
error: (err)=>console.error("Error>> l:"+err),
complete:() =>console.log('1 is complete')
}
const observer2 = {
next: (val)=>console.log("2:"+val),
error: (err)=>console.error("Error>> 2:"+err),
complete:() =>console.log('2 is complete')
}
subject.subscribe(observer1);
setTimeout(function(){
subject.subscribe(observer2);
},2000);
counter$.subscribe(subject);
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
const counter$ =
Rx.Observable.interval(1000).take(5);
const subject = new Rx.Subject();
const observer1 = {
next: (val)=>console.log("l:"+val),
error: (err)=>console.error("Error>> l:"+err),
complete:() =>console.log('1 is complete')
}
const observer2 = {
next: (val)=>console.log("2:"+val),
error: (err)=>console.error("Error>> 2:"+err),
complete:() =>console.log('2 is complete')
}
subject.subscribe(observer1);
subject.next(10);
subject.next(11);
setTimeout(function(){
subject.subscribe(observer2);
},2000);
counter$.subscribe(subject);
subject 是一个热流hot流,类似于是一个电视直播
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
const counter$ =
Rx.Observable.interval(1000).take(5);
const subject = new Rx.ReplaySubject(2); //最后两个重播
subject.next(10);
subject.next(11);
const observer1 = {
next: (val)=>console.log("l:"+val),
error: (err)=>console.error("Error>> l:"+err),
complete:() =>console.log('1 is complete')
}
const observer2 = {
next: (val)=>console.log("2:"+val),
error: (err)=>console.error("Error>> 2:"+err),
complete:() =>console.log('2 is complete')
}
subject.subscribe(observer1);
setTimeout(function(){
subject.subscribe(observer2);
},2000);
counter$.subscribe(subject);
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>
</body>
</html>
const counter$ =
Rx.Observable.interval(1000).take(5);
const subject = new Rx.BehaviorSubject(); // BehaviorSubject 只记住最新的最后一个值
subject.next(10);
subject.next(11);
const observer1 = {
next: (val)=>console.log("l:"+val),
error: (err)=>console.error("Error>> l:"+err),
complete:() =>console.log('1 is complete')
}
const observer2 = {
next: (val)=>console.log("2:"+val),
error: (err)=>console.error("Error>> 2:"+err),
complete:() =>console.log('2 is complete')
}
subject.subscribe(observer1);
setTimeout(function(){
subject.subscribe(observer2);
},2000);
counter$.subscribe(subject);
6-7 实战身份验证控件和地址选择控件(上)
# ng g c shared/identity-input --spec=false
# ng g c shared/area-list --spec=false
6-8 实战身份验证控件和地址选择控件(中)
6-9 实战身份验证控件和地址选择控件(下)
7-1 Redux 的概念和实战(一)
Action 信号,事件, 中从Store中发出吗?
Reducer 计数器,进行处理;它是一个纯函数
Store 结果存在 Store中,然后程序就从Store中取数据
Store 里面的State值是不可改变的,它每次都返回一个新的State
chrome 的开发者工具 Reduc DevTools
redux 的依赖 ngrx,是google的angular团队的几个员工写的框架,用来在angular当中实现redux
它是anguarl/core框架的一个补充,不是必须的,官方鼓励大家用ngrx
下面是慕客网用的版本
下面是我用的方法
# npm i --save @ngrx/core @ngrx/store @ngrx/router-store @ngrx/effects @ngrx/store-devtools
# npm install --save ngrx-store-freeze
7-2 Redux 的概念和实战(二)
# json-server ./mock/data.json
# ng serve
# npm i --save reselect
reselect 提供了 从缓存读取数据,提高性能;合并多个输入型函数(除了最后一个) createSelector
7-3 什么是 Effects
reducer 是对内部的影响和改变(会改变store),跟ui相关的
effects 是对外部的影响和改变(跟dom,跟http请求相关的等)
# npm install -g concurrently ( concurrently 就是并行 同时的意思)
# npm start
7-4 实战认证信息流
# npm install --save lodash
# npm install --save-dev @types/lodash
7-5 实战项目信息流(上)
7-6 实战项目信息流(中)
# npm install --save lodash
# npm install --save-dev @types/lodash
7-7 实战项目信息流(下)
7-8 实战任务列表信息流
7-9 实战任务 Reducer
7-10 实战任务 Effects
7-11 实战任务使用 Reducer 和 Effects
8-1 Angular 测试框架介绍
# ng g class reducers/auth.reducer --spec=true # 为什么我执行这个命令会报错
# 而人家执行这个命令没事
# ng test
8-2 单元测试 Service 和 Effects 以及集成测试
# ng g s services/auth --spec (我这边不行)
# ng test
# ng g class effects/auth.effects --spec (我这边不行)
# ng e2e
9-1 第三方组件的集成和懒加载
# npm install --save angular-calendar
# ng g m my-calendar
# ng g c my-calendar/calendar-home -is -it --spec=false
9-2 项目总结
vs code 调试
安装 chrome的调试插件后 ,重启下 vs code
设置断点
然后启动 json-server 和 ng serve
看断点处的变量
webstorm调试
chrome 调试