JS数据结构之树的遍历(Tree Traversal)

预备工作

先写几个函数,能够生成树状结构的数据

生成随机数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 随机数据,支持string、number、boolean和object类型
const randomData = {
get string() {
return Math.random().toString(36).slice(2, 6)
},
get number() {
return (Math.random() * 10000) | 0
},
get boolean() {
return !((Math.random() * 2) | 0)
},
get object() {
return {
id: this.number,
name: this.string,
}
},
}

randomData[类型] 调用即可。

Read More

同一WiF无法ping通

同一个 WiFi 下,手机和电脑无法互相 ping 通:

  1. 是不是在同一子网下
  2. 检查防火墙,杀毒软件
  3. 路由器是否开启了AP隔离

小米路由器的 WiFi 默认使用 WPA 加密,把加密方法改为 WPA2 就好了,但是也不稳定,需要在 wpa2 和 普通方式之间来回切换,然后重启路由器才行。这么看来,小米路由器挺垃圾的。

Vue响应式原理之「对象属性劫持」

在 Vue 中,data 对象是响应式的,即对 data 中属性的修改会触发视图更新,今天就来分析一下这是如何做到的。

首先定义一个普通的 JS 对象,例如:{ name: 'keliq' },我们希望当 name 发生变化时,能收到通知。

在 Vue 当中,有三个非常重要的概念:Observer、Dep 和 Watcher,它们的功能是:

  • Observer:把普通对象变成响应式对象,实现原理就是递归地对属性进行劫持,在 get 的时候把依赖收集到 dep.subs 里面,从而在 set 的时候能够逐个通知
  • Dep:用于存放 Observer 收集到的依赖
  • Watcher:创建观察者,即订阅响应式通知,当目标发生变化时执行回调

Read More

Flutter字符串处理

Dart 的 String 类使用 UTF-16 编码格式,遇到一些特殊语言和表情符号时会处理异常,例如:

1
2
3
4
main() {
var input = ['Resume', 'Résumé', '个人简历', '💼📃', 'Currículo'];
input.forEach((it) => print(it.substring(0, 3)));
}

输出:

1
2
3
4
5
Res
Ré
个人简
💼���
Cur

通过引入字符串处理包 https://pub.flutter-io.cn/packages/characters ,然后用 it.characters.take(3) 替换 it.substring(0, 3)

Flutter中滚动组件嵌套滚动组件

【转】原文地址。在 Flutter 中,如果想在 scrollview 里面嵌套另一个 listview 的话,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Scaffold(
appBar: AppBar(
title: Text("ListView"),
),
body: Container(
child: SingleChildScrollView(
child: Column(
children: <Widget>[
HeaderWidget("Header 1"),
HeaderWidget("Header 2"),
HeaderWidget("Header 3"),
HeaderWidget("Header 4"),
ListView(
children: <Widget>[
BodyWidget(Colors.blue),
BodyWidget(Colors.red),
BodyWidget(Colors.green),
],
),
],
),
),
),
);

Read More

Dart List操作

总结 dart 中关于 list 的一些特殊操作:

在 map 中使用索引

在 js 中可以在 map 中取到 i 的值:

1
2
list.map((it, i)=>{
})

但是在 dart 中这种写法会报错,函数中只能得到 it 而得不到 i,那应该怎么办呢?可以使用 Map Entries:

1
2
3
4
5
list.asMap().entries.map((entry) {
int i = entry.key;
String it = entry.value;
return something;
}

Read More

Dart根据类名生成类的实例

在一个 Flutter 项目中,想动态创建类的实例,就是根据类名字符串,在进行某些操作的时候自动创建类的实例。但 Dart 语言不支持通过类名字符串生成实例,但是可以用下面的方式实现相同的效果:

1
2
3
4
5
6
7
var factories = <String, Object Function()>{
'Foo', () => new Foo(),
'Bar', () => new Bar()
};

String name = 'Foo';
Object instance = factories[name]();

flutter container中的image

如何把图片放到容器内部,长宽保持跟容器相同呢?有两种方法:

  1. 用 container 的 decoration image

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Container(
    decoration: BoxDecoration(
    image: DecorationImage(
    image: AssetImage(imagePath),
    fit: BoxFit.cover,
    ),
    ),
    child: hild,
    padding: padding,
    );
  2. FittedBox 包裹 Image

    1
    2
    3
    4
    FittedBox(
    child: Image.asset('foo.png'),
    fit: BoxFit.fill,
    )

75行代码实现Promise/A+规范

Promise 是一种非常重要的异步编程模式,可以巧妙地避免产生的回调地狱问题,有如下几个特点:

  • Promise 是基于回调的
  • 利用发布订阅模式来进行通知回调
  • 递归链式调用

Promise/A+ 规范中对 Promise 做了如下的定义:

一个有 then 方法的对象或者函数,只要是符合 A+ 规范,就是 Promise

A+ 规范里面有很规则,主要讲述了 Promise 的内部变量和 then 函数的执行流程,并没有定义 catch/finally 等方法,其实这些方法都是基于 Promise 和 then 函数的,具体用法可参考 MDN 文档。

接下来就来实现一个 Promise,首先定义构造函数,里面保存四个私有变量:

  1. Promise 的状态(status),该状态只能被改一次
  2. 成功的值 value
  3. 拒绝的原因 reason
  4. 异步时预先保存的成功或失败的回调 cb

Read More

typescript装饰器

之前总结过浏览器中的事件循环,在 Node.js 中也有自己的事件循环,但与浏览器不一样,在 Node.js 中有 5 个宏任务队列,分别是:

  1. 计时器队列,里面存放 setTimeout 和 setInterval 函数添加的回调
  2. 系统相关回调队列,例如端口监听、进程资源占用
  3. IO 事件队列,里面存放 I/O 事件回调,这是 Node.js 异步非阻塞的关键
  4. 立即执行队列,里面存放 setImmediate 函数添加的回调
  5. 关闭操作队列,里面存放 close 事件处理回调

Read More