初次使用angular开发某管理系统遇到的一些问题
1、加载完成自动提示功能
项目有个异步加载需要几分钟,想实现一个异步加载完成时中提示用户加载完成。在加载过程中,用户可以进行界面路由之间的跳转,但是angular路由切换后组件就已经销毁了,所以不能通过组件内的变量记录加载过程。所以思路是用localstorage存储一个变量记录完成,但是怎么获取localstorage存的值是值发生改变呢?最后思路是自定义一个localstorage.setItem事件,在组件初始化的时候直接监听该事件,判断值是否发生改变,做相应操作。代码如下:
ngOnInit() {
// 设置监听localStorage.setItem事件改变
const orignalSetItem = localStorage.setItem; // 原始的setItem方法
localStorage.setItem = function(key, newValue) {
const setItemEvent = new Event('setItemEvent');
setItemEvent[key] = newValue;
orignalSetItem.apply(this, arguments); // 调用原始的setItem方法
window.dispatchEvent(setItemEvent); // 派发该事件
};
}
2、flex布局,子盒子设置flex: 1内容溢出
父盒子设置了display:flex; 想让某个子盒子宽度沾满剩余屏幕,设置了flex: 1,但是盒子里的内容超出了容器的宽度,造成内容溢出。上网查了发现很多人也遇到过这个问题。解决方案有两种。给该子盒子设置 width: 0
或者overflow: hidden
.content-wrapper {
display: flex;
.content {
flex: 1;
width: 0; // 解决超过内容超出容器bug 或者 overflow: hidden
}
}
3、文本框自动搜索功能,添加防抖
想要对文本框实现输入内容自动搜索功能,添加一个防抖函数,以前在vue是通过watch方法进行实现的,但是angular没有watch方法。查了一下网上说angular可以通过rxjs的debounce操作符实现。具体实现如下:
- vue中核心实现
created () {
// 监听query参数发生改变, 通过防抖派发出去
this.$watch('query', debounce((newQuery) => {
this.$emit('query', newQuery)
}, 200))
}
- angular实现
定义一个自定义指令
// @author: zhuanglinxin @date: 2020-07-08 12:05:49
import { Directive, HostListener, Input, EventEmitter, Output, OnDestroy, OnInit } from '@angular/core';
import { debounceTime } from 'rxjs/operators';
import { Subject, Subscription } from 'rxjs';
@Directive({
selector: '[appDebound]'
})
// 防抖
export class DeboundDirective implements OnInit, OnDestroy {
@Input('appDebound') debounceTime = 500; // 防抖时间 默认值: 500ms
@Output() debounceInput = new EventEmitter(); // 定义派发事件源
private inputs = new Subject<any>(); // 将值或事件多路推送给多个 Observer
private subscription: Subscription; // Observable 的执行,用于取消 Observable 的执行
constructor() {}
@HostListener('input', ['$event'])
clickEvent(event) {
event.preventDefault();
event.stopPropagation();
const value = event.srcElement['value'];
// 将文本框输入的值派发出去
this.inputs.next(value);
}
ngOnInit(): void {
// 订阅事件 并添加防抖操作符
this.subscription = this.inputs.pipe(debounceTime(this.debounceTime)).subscribe(e => this.debounceInput.emit(e));
}
ngOnDestroy(): void {
this.subscription.unsubscribe();
}
}
使用:
<input type="text" [appDebound]="500" (debounceInput)="search()" [(ngModel)]="name" />
4、实现全局路由动画
angular没有vue的 <transition>
标签实现全局路由动画。
自定义一个动画函数。
import {animate, state, style, transition, trigger, group, AnimationTriggerMetadata, query} from '@angular/animations';
export const slideToTop = trigger('routeAnim', [
transition('* => *', [
query(':leave', style({ transform: 'translateY(0)', position: 'absolute', width: '100%'}), { optional: true }),
query(':enter', style({ transform: 'translateY(-100%)', position: 'absolute', width: '100%'}), { optional: true }),
group([
query(':leave', animate('.5s ease-in-out', style({transform: 'translateY(100%)', width: '100%', position: 'absolute'})), { optional: true }),
query(':enter', animate('.5s ease-in-out', style({transform: 'translateY(0)', width: '100%', position: 'absolute'})), { optional: true })
])
])
]);
在放置路由的组件里使用:
import { Component, OnInit, ViewChild, Renderer2 } from '@angular/core';
import { slideToTop } from 'src/app/shared/animation/router.anim';
@Component({
selector: 'app-person',
templateUrl: './person.component.html',
styleUrls: ['./person.component.scss'],
animations: [slideToTop] // 引入动画
})
export class PersonComponent implements OnInit {
routerState = true;
routerStateCode = 'active';
constructor(private router: Router) {
this.router.events.subscribe(event => {
if (event instanceof NavigationEnd) {
// 每次路由跳转改变状态
this.routerState = !this.routerState;
this.routerStateCode = this.routerState ? 'active' : 'inactive';
}
});
}
}
<div class="routerBox" [@routeAnim]="routerStateCode">
<router-outlet></router-outlet>
</div>
5、添加http拦截器,给每个请求添加token
待更新中…