Live Note

Remain optimistic

整理图片

摄影图片太多了, 需要整理.
之前用的腾讯云oss, 但是需要流量费, 好兄弟推荐了cloudflare, 免费而且速度快.

而且可以 CDN 加速, 非常适合我.

所以把图片都迁移到了 CF, 并新启了一个相册用于放图片

ablum

r2-image-bucket

拖拽元素事件:

  • dragstart:拖拽前触发
  • drag:拖拽前到拖拽结束之间,连续触发
  • dragend:拖拽结束触发
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<ul>
<li>li1</li>
<li>li2</li>
<li>li3</li>
</ul>

<script>
let aLi = document.querySelectorAll("li")
for (let li of aLi) {
let count = 0
li.ondragstart = function () {
this.style.backgroundColor = "red"
}
li.ondrag = function () {
console.log(count++) //连续触发
}
li.ondragend = function () {
this.style.backgroundColor = ""
}
}
</script>
Read more »

扩展运算符

1
2
3
4
5
6
7
8
9
10
11
console.log(...[1, 2, 3]) //1 2 3
console.log(1, ...[2, 3], 4) //1 2 3 4
;[...document.querySelectorAll("div")] //[<div>, <div>, ...];

function add(x, y) {
return x + y
}
add(...[1, 2]) //3

//与表达式一同使用
const arr = [...(x > 0 ? ["a"] : []), "b"]

扩展运算符的应用

  • 替代数组的 apply 方法

    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
    function f(x, y, z) {}
    var args = [0, 1, 2]

    //ES5 写法
    f.apply(null, args)

    //ES6 写法
    f(...args)

    //用 Math.max 求数组中最大的数
    //ES5 写法
    Math.max.apply(null, [2, 33, 3])

    //ES6 写法
    Math.max(...[2, 33, 3])

    //用 push 将一个数组添加到另一个数组尾部
    var arr1 = [0, 1, 2]
    var arr2 = [3, 4, 5]

    //ES5 写法
    Array.prototype.push.apply(arr1, arr2)

    //ES6 写法
    arr1.push(...arr2)
  • 合并数组

    1
    2
    3
    4
    5
    6
    7
    8
    9
    var arr1 = ["a"]
    var arr2 = ["b", "c"]
    var arr3 = ["d"]

    //ES5 写法
    arr1.concat(arr2, arr3)

    //ES6 写法
    ;[...arr1, ...arr2, ...arr3]
  • 与解构赋值结合

    Read more »

querySelector()

querySelector 只能选择一组中的第一个元素:

1
2
3
4
5
6
<div class="test">div1</div>
<div class="test">div2</div>

<script>
document.querySelector(".test").style.color = "red" //只有第一个会变红
</script>

querySelectorAll()

querySelectorAll 获取一组元素:

1
2
3
4
5
6
7
8
9
<div class="test">div1</div>
<div class="test">div2</div>

<script>
let aDiv = document.querySelectorAll(".test")
for (let div of aDiv) {
div.style.color = "red"
}
</script>
Read more »

旧 React 简易实现

react-old.js
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
import { updateDomProperties } from "./dom-utils.js"

// 根实例
let rootInstance = null
const TEXT_ELEMENT = "TEXT_ELEMENT"

// 创建 VDOM 元素
function createElement(type, config, ...args) {
const props = Object.assign({}, config)
const hasChildren = args.length > 0
const rawChildren = hasChildren ? [].concat(...args) : []

props.children = rawChildren
.filter((c) => c !== null && c !== false)
.map((c) => (c instanceof Object ? c : createTextElement(c)))

return { type, props }
}

function createTextElement(text) {
return createElement(TEXT_ELEMENT, { nodeValue: text })
}

function render(element, container) {
const prevInstance = rootInstance
const nextInstance = reconcile(container, prevInstance, element)
rootInstance = nextInstance
}

// 递归更新子元素
function reconcile(parentDom, instance, element) {
if (instance === null) {
// 创建新实例
const newInstance = instantiate(element)
parentDom.appendChild(newInstance.dom)
return newInstance
} else if (element === null) {
// 删除实例
parentDom.removeChild(instance.dom)
return null
} else if (instance.element.type !== element.type) {
// 如果类型不同,则替换实例
const newInstance = instantiate(element)
// 替换实例
parentDom.replaceChild(newInstance.dom, instance.dom)
return newInstance
} else if (typeof element.type === "string") {
// 更新 DOM 实例
updateDomProperties(instance.dom, instance.element.props, element.props)

// 更新 instance
instance.childInstances = reconcilerChildren(instance, element)
instance.element = element

return instance
} else {
// 更新组件实例
instance.publicInstance.props = element.props
const childElement = instance.publicInstance.render()
const oldChildInstance = instance.childInstance
const childInstance = reconcile(parentDom, oldChildInstance, childElement)

instance.dom = childInstance.dom
instance.childInstance = childInstance
instance.element = element

return instance
}
}

function reconcilerChildren(instance, element) {
const dom = instance.dom
const childInstances = instance.childInstances
const nextChildElements = element.props.children || []
const newChildInstances = []

const count = Math.max(childInstances.length, nextChildElements.length)

// 本 demo, 顺序不同也算作更新

for (let i = 0; i < count; i++) {
const childInstance = childInstances[i]
const childElement = nextChildElements[i]

const newChildInstance = reconcile(dom, childInstance, childElement)

newChildInstances.push(newChildInstance)
}

return newChildInstances.filter((instance) => instance !== null)
}

// 把元素实例化成真实的DOM节点
function instantiate(element) {
const { type, props } = element
const isDomElement = typeof type === "string"

if (isDomElement) {
// 创建 DOM 元素
const isTextElement = type === TEXT_ELEMENT
const dom = isTextElement
? document.createTextNode("")
: document.createElement(type)

// 更新 dom
updateDomProperties(dom, [], props)

// 实例化子元素
const childElements = props.children || []
const childInstances = childElements.map(instantiate)
const childDoms = childInstances.map((childInstance) => childInstance.dom)
childDoms.forEach((childDom) => dom.appendChild(childDom))

const instance = { dom, element, childInstances }

return instance
} else {
// 初始化组件
const instance = {}
const publicInstance = createPublicInstance(element, instance)
const childElement = publicInstance.render() // 拿到 vdom
const childInstance = instantiate(childElement) // 实例化
const dom = childInstance.dom

Object.assign(instance, { dom, element, publicInstance, childInstance })

return instance
}
}

function createPublicInstance(element, internalInstance) {
const { type, props } = element

// type 此时是一个 Class
const publicInstance = new type(props)

publicInstance.__internalInstance = internalInstance

return publicInstance
}

function updateInstance(internalInstance) {
const parentDom = internalInstance.dom.parentNode
const element = internalInstance.element

reconcile(parentDom, internalInstance, element)
}

class Component {
constructor(props) {
this.props = props
this.state = this.state || {}
}

setState(partialState) {
this.state = Object.assign({}, this.state, partialState)
updateInstance(this.__internalInstance)
}

// render 出来的也是 VDOM
render() {}
}

export default { render, createElement, Component }
Read more »