Lodash get 三个基础实现版本

接上篇,在 Vue 中你可以 这样 a.b.c.d 进行 watch,在 lodash 你也可以以同样的形式进行属性的读取,思索其中中源码实现才有了这篇文章
_.get 基本语法

1
2
3
4
5
6
7
// 基本语法
_.get(obj, path, "defaultValue");

_.get(obj, "a.b[0].c", "defaultValue");

// 或者 path 以数组的形式
_.get(obj, ["a", "b", "0", "c"], "defaultValue");

path 支持两种形式的传值,数组和字符串,我们需要转成统一的数组形式,便于取值

JS 最近进入 Stage 4 的两个提案

今天刷推特的时候看到 TC39 的成员说 js 的两个语法糖提案进入 stage 4,最终板上钉钉,修成正果。

  • Optional Chaining
  • Nullish Coalescing
    其中 Optional Chaining 在这之前的 TS 3.7 中就被引入了

Optional Chaining

在此之前使用我们通常获取一个多层级对象一个比较内层的属性,为了避免为空的情况不得不这样写

1
let prop = a.b && a.b.c && a.b.c.d // 取到值或者赋值为 undefined

习惯了 Lodash 之后

1
let prop = _.get(a, "b.c.d", undefined) // 可以自定义默认值

使用 Optional Chaining 之后

1
let prop = a?.b?.c?.d

关于 Vue 的一些冷门技巧

watch

有时候我们会写一些这样的代码, 在 created 一个组件之后获取数据, 然后根据某个值得变动来获取数据, 正常套路是按照下面写的,

1
2
3
4
5
6
7
8
created() {
this.fetchUserList()
},
watch: {
searchText () {
this.fetchUserList ()
}
}

但是 watch 的 api 其实很复杂, 语法糖甜的掉牙了. 于是我们可以简化为

Rxjs Scheduler 下的 eventloop

本文将简单介绍 event loop 在 RxJS 中运用. 偏重于 RxJS Scheduler 而不是 event loop

event loop

event loop 是一种任务调度机制, 用来处理异步任务, 在 JavaScript 单线程语言中, 在同一时间内只能只能处理一件事, 当我们遇到需要处理异步的情况, 不能让异步操作阻塞线程, 我们可以让异步任务先搁置, 先执行同步任务, 等异步时间来临再来执行异步任务, 这就是 event loop.

JavaScript 在执行过程中, 变量与对象会存入对中, 另外还会维护一个任务队列(包括宏任务队列, 微任务队列), 执行函数会被推入栈中, 一旦函数执行完毕就会从函数中推出, 一旦整个执行栈被清空, 就开始处理任务队列, 按照一定逻辑将任务推入执行栈中执行, 执行过程中可能会往任务队列中添加其他任务,微任务具有高优先级, 在单个宏任务的切换中间会检查执行整个微任务队列, 再去执行下一个宏任务

Vue 异步计算属性实现

前段时间在 GitHub 上看到一个 Vue 异步计算属性的库 - vue-async-computed, 将异步操作转化为计算属性, 例如这样用

1
2
3
4
5
6
7
8
9
10
11
new Vue({
data: {
userId: 1
},
asyncComputed: {
username () {
return Vue.http.get('/get-username-by-id/' + this.userId)
.then(response => response.data.username)
}
}
}

好奇其中原理, 看了源码, 了解其中巧妙的实现思路, 绘制了一张核心思路的原型图.

接下来我们实现一个简(阉)易(割)版本的 vue-async-computed 插件,

趁着 beforeCreatedata 中添加 asyncComputedkey, 使之响应式.

TS 一些工具泛型的使用及其实现

本文将简要介绍一些工具泛型使用及其实现, 这些泛型接口定义大多数是语法糖(简写), 甚至你可以在 typescript 包中的 lib.d.ts 中找到它的定义, 最新版的 typescript (2.9) 已经包含了大部分, 没有包含的我会特别指出.

Partial

Partial 作用是将传入的属性变为可选项.
首先我们需要理解两个关键字 keyofin, keyof 可以用来取得一个对象接口的所有 key 值.
比如

使用装饰器自动取消订阅 React 组件中的 RxJS 流

最近自己的一个项目使用了 RxJS 进行状态管理, 需要在组件中订阅流来获取全局状态, 但是在组件卸载的时候需要手动取消订阅流.
这样写起来有点繁琐,所以考虑用装饰器简化下代码

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
import * as React from "react";
import { Subscription } from "rxjs";
import { action$, state$ } from "../store/store";

class Artist extends React.Component {
sub: Subscription;
handleClick() {
setInterval(() => {
action$.next((state: any) => state);
}, 1000);
}
componentDidMount() {
this.sub = state$.subscribe(v => {
console.log("artist", v);
});
}
componentWillUnmount() {
console.log("artist unsubscribe");
this.sub.unsubscribe();
}
render() {
return (
<div>
<button onClick={() => this.handleClick()}>Click Me</button>
</div>
);
}
}

export default Artist;

装饰器学习

前言

一直觉得装饰器的写法有种蜜汁好感和好奇,例如 @component或者@connect(x, y)

装饰器在 React 和 Angular 中很常见,因为这两个框架很强调类,而装饰器的作用范围正是类和类成员,来看装饰器提案的一句话

Decorators make it possible to annotate and modify classes and properties at design time.

指出了装饰器作用对象,注意到最后三个单词 at design time, 再抄袭一句话

装饰器对类的行为的改变,是代码编译时发生的,而不是在运行时。这意味着,装饰器能在编译阶段运行代码。也就是说,装饰器本质就是编译时执行的函数

RxJS Subject 学习

Subject

其实一个 Observable 可以被订阅多次, 但是并不共享一个流的数据,如下例

1
2
3
4
5
6
let stream$ = Rx.of(1, 2, 3);
stream$.subscribe(r => console.log("a", r));

setTimeout(() => {
stream$.subscribe(r => console.log("b", r));
}, 110);

输出结果

1
2
3
4
5
6
a 1
a 2
a 3
b 1
b 2
b 3

RxJS 操作符笔记

RxJS 6

操作符

一些常用的操作符

  • of
  • from
  • first
  • last
  • tap
  • interval
  • timer
  • forkJoin
  • filter
  • map
  • switchMap
  • scan
  • takeWhile
  • takeUtil
  • take
  • concat
  • throttle
  • debounce
  • merge

of

将数字转化为 Observable

1
2
Rx.of("1", "2").subscribe(v => console.log(v));
// 输出 1, 2
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×