关于前端:本周遇到的问题

44次阅读

共计 2645 个字符,预计需要花费 7 分钟才能阅读完成。

首先是又遇到了一些 RXjs 操作符,在这里简略的说一下。
首先是 combineLatest。
将其间接翻译过去就是联合最新的(observeble),那么联合一下上面这张图片就很容易了解了。

combineLatest 联合作为参数传递的所有 Observables 的值。这是通过按程序订阅每个 Observable 并在任何 Observable 收回时从每个 Observable 收集最新值的数组来实现的。因而,如果您将 nObservable 传递给运算符,则返回的 Observable 将始终收回一个值数组,n 其程序与传递的 Observable 的程序绝对应(第一个 Observable 的值在第一位,依此类推)。

让咱们再联合代码试一下

const firstTimer = Rx.Observable.timer(0, 1000); // emit 0, 1, 2... after every second, starting from now
const secondTimer = Rx.Observable.timer(500, 1000); // emit 0, 1, 2... after every second, starting 0,5s from now
const combinedTimers = Rx.Observable.combineLatest(firstTimer, secondTimer);
combinedTimers.subscribe(value => console.log(value));
// Logs
// [0, 0] after 0.5s
// [1, 0] after 1s
// [1, 1] after 1.5s
// [2, 1] after 2s

从此处咱们也能更粗浅地意识到,只有两个 observble 都触发时才会开始触发 combineLatest。

我的项目中 用到了状态治理相干内容,上面来简略地说一下什么是状态模式,之前也有听老师讲过状态模式,然而因为没有找到理论代码所以对状态模式总是不了解。

以后我的项目的状态模式能够体现为如下模式

相当于状态模式就是代替了之前咱们所用的服务层并且状态模式的非凡之处集体认为就体现在 store 的应用,store 实现了将数据作为缓存间接存储在前台。
可能这么说不是很间接,上面再加上代码来阐明一下。
咱们目前能够简略地认为一个 store 只用来存储 / 操作一种状态,而后通过继承 store 类并将其设置为注射器来实现:
比方咱们想对 building 实体进行治理

@Injectable()
export class BuildingStore extends Store<Building>{
export const BuildingActions = {getUnit: 'getUnit'}

static units(state: Unit) {return state.units;}

// 增加 action 注解与 actions 进行对接,使其能够由 dispatch 调用
// 咱们能够发现此办法中尽管返回了 observable 然而 data 并没有返回,这是因为此办法将数据作为状态的更新存进了缓存(store)@Action(taskActions.getUnit)
getUnit(state: Building, payload: number | string) {return this.http.get(xxxurl).pipe(.tap((data) => {
        // 获取以后状态
        const state = this.snapshot;
        // 获取新状态
        state.units = data.units;
        // 更新状态
        this.next(state);
        
    })
}


}

而后咱们能够在 C 层中这样调用

@Injectable()
export class BuildingComponent extends {
    . . .
    // 获取 building 对应的 unit 到缓存中
    this.buildingStore
        .dispatch(BuildingActions.getUnit, 1)
        .subscribe(() => {console.log('已获取 units')        
    });

    // 在此组件中获取 units(去 store 中获取)this.buildingStore.select(BuildingStore.units)
        .subscribe(data => {console.log("获取到的单元:");
            console.log(units);
        })
    
}

此外值得一提的是如果咱们照下面代码操作的话 this.buildingStore.select 会触发两次,第一次是旧数据,第二次是新数据。
猜想其过程为:

那么如果咱们要从 store 中获取多种数据咱们为了防止获取到旧的数据咱们就能够和文章后面说到的 combineLatest 联合应用,从而保持数据的更新并且便于应用。

而后再来说一下本周遇到的一个奇怪的 bug:
先说一下问题:
当咱们更改工夫时会弹出一个弹窗,将弹窗敞开后批改工夫没有问题,然而点击右侧 X 号清空工夫尽管向后盾收回了申请然而前台显示没有实时更新——依然是显示 11 月 24,刷新页面后显示为空。

遇到这个问题期初是认为我的项目本身就存在的 bug,然而将弹窗操作去除后发现一切正常,起初想是不是因为开启弹窗后因为弹窗组件没有失常销毁导致的。

于是在其销毁时进行打点并且在原组件中也进行打点判断各个中央的执行程序有没有受到影响,然而打点后察看发现执行程序和各个办法没有任何影响。并且销毁工夫也合乎预期。

起初询问老师后得悉如果在子组件中扭转了子组件的值也会产生这样的问题。

比方咱们将 XXX 对象传给了弹窗组件,咱们在弹窗组件中对其进行了更改就会产生问题,因为就想之前说到的那样,对象之间的传递都是传的地址,而 angular 并不举荐像这样扭转父组件中的对象。

起初我又尝试既然间接传递对象有问题,那么将要传递的对象深拷贝后将拷贝后的对象传给弹窗组件应该就没问题了。

尝试之后发现还是不行,就算深拷贝后还是会有这样的问题。

起初老师考察后发现问题还是出在了状态模式中的 store 上。

比方咱们还拿 building 举例,咱们在父组件中依据 buildingId 获取了 units,而后在子组件中再依据这个 buildingId 获取 units,这两个中央都是获取缓存并进行操作就可能会呈现问题,从而导致下面的问题。

要想更深刻理解问题应该就须要进一步理解它缓存的机制——缓存是怎么存的?父组件,子组件缓存共享吗?什么时候清空缓存?缓存在什么状况下会呈现问题?
这些问题都须要在之后的我的项目中进一步理解。

正文完
 0