Live Note

Remain optimistic

validity 对象

通过 validity 对象,通过下面的 valid 可以查看验证是否通过,如果八种验证都通过返回 true,有一种失败则返回 false

  • oText.addEventListener(‘invalid’, fn, false);
  • ev.preventDefault()
  • valueMissing: 输入值为空时
  • typeMismatch: 控件值与预期类型不匹配
  • patterMismatch: 输入值不满足 pattern 正则
  • tooLong: 超过 maxLength 最大限制
  • rangeUnderflow: 验证的 range 最小值
  • rangeOverflow: 验证的 range 最大值
  • setMismatch: 验证 range 的当前值是否符合 min、max、step 的规则
  • customError: 不符合自定义验证–setCustomValidity()设置自定义验证
Read more »

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
import System.Environment
import System.Directory
import System.IO
import Data.List

main = do
(command:args) <- getArgs -- get the command
let (Just action) = lookup command dispatch -- find the command
action args -- do something

add :: [String] -> IO ()
add [fileName, todoItem] = appendFile fileName (todoItem ++ "\n") -- add the todoItem

view :: [String] -> IO ()
view [fileName] = do -- match the filename
contents <- readFile fileName -- read the file
let todoTasks = lines contents -- get the contents
numberedTasks = zipWith (\n line -> show n ++ ": " ++ line) [0..] todoTasks
putStrLn $ unlines numberedTasks -- show the items

remove :: [String] -> IO ()
remove [fileName, numberString] = do -- get the filename and the line number
handle <- openFile fileName ReadMode
(tempName, tempHandle) <- openTempFile "." "temp" -- create a temp file
contents <- hGetContents handle -- get contents from the handle
let number = read numberString -- read the String to Number
todoTasks = lines contents
newTodoTasks = delete (todoTasks !! number) todoTasks -- remove the line of the number
hPutStr tempHandle $ unlines newTodoTasks -- putStr into the tempfile
hClose handle -- close handles
hClose tempHandle
removeFile fileName
renameFile tempName fileName

dispatch :: [(String, [String] -> IO ())]
dispatch = [
("add", add),
("view", view),
("remove", remove)
]

-- runhaskell arags-test.hs view newData.txt
-- runhaskell args-test.hs add newData.txt "Say Hello"
-- runhaskell args-test.hs remove newData.txt 4

在使用 Android dev 开发 flutter 应用时,控制台会输出 GPU debug 日志:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[+1001 ms] D/EGL_emulation( 9434): app_time_stats: avg=1001.31ms min=1001.31ms max=1001.31ms count=1
[+1989 ms] D/EGL_emulation( 9434): app_time_stats: avg=994.95ms min=992.16ms max=997.75ms count=2
[+1996 ms] D/EGL_emulation( 9434): app_time_stats: avg=998.40ms min=994.74ms max=1002.06ms count=2
[+2005 ms] D/EGL_emulation( 9434): app_time_stats: avg=1002.85ms min=990.68ms max=1015.03ms count=2
[+1983 ms] D/EGL_emulation( 9434): app_time_stats: avg=991.95ms min=987.00ms max=996.89ms count=2
[+1016 ms] D/EGL_emulation( 9434): app_time_stats: avg=1015.37ms min=1015.37ms max=1015.37ms count=1
[+1002 ms] D/EGL_emulation( 9434): app_time_stats: avg=1002.23ms min=1002.23ms max=1002.23ms count=1
[+1002 ms] D/EGL_emulation( 9434): app_time_stats: avg=1003.33ms min=1003.33ms max=1003.33ms count=1
[+1008 ms] D/EGL_emulation( 9434): app_time_stats: avg=1005.76ms min=1005.76ms max=1005.76ms count=1
[+1997 ms] D/EGL_emulation( 9434): app_time_stats: avg=999.30ms min=994.23ms max=1004.37ms count=2
[+1998 ms] D/EGL_emulation( 9434): app_time_stats: avg=998.66ms min=998.60ms max=998.71ms count=2
[+2000 ms] D/EGL_emulation( 9434): app_time_stats: avg=1000.03ms min=998.15ms max=1001.91ms count=2
[+1998 ms] D/EGL_emulation( 9434): app_time_stats: avg=999.53ms min=999.27ms max=999.79ms count=2
[+1990 ms] D/EGL_emulation( 9434): app_time_stats: avg=995.32ms min=993.38ms max=997.25ms count=2
[+1001 ms] D/EGL_emulation( 9434): app_time_stats: avg=1001.47ms min=1001.47ms max=1001.47ms count=1
[+1001 ms] D/EGL_emulation( 9434): app_time_stats: avg=1001.27ms min=1001.27ms max=1001.27ms count=1
[+1004 ms] D/EGL_emulation( 9434): app_time_stats: avg=1004.90ms min=1004.90ms max=1004.90ms count=1
[+1005 ms] D/EGL_emulation( 9434): app_time_stats: avg=1005.88ms min=1005.88ms max=1005.88ms count=1
[+1979 ms] D/EGL_emulation( 9434): app_time_stats: avg=989.67ms min=979.52ms max=999.82ms count=2

这些日志并不影响应用的运行,但是会占用控制台的空间,可以通过以下方式忽略掉:

1
flutter run --dart-define=ENV=dev --verbose | grep -v "EGL_emulation"

使用 HOC 进行代码复用

假设存在下面两个组件:

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
import React from "react"

class ButtonCounter extends React.Component {
constructor(props) {
super(props)

this.state = {
count: 0,
}
}

increase = () => {
let { step } = this.props

this.setState((pre) => {
return {
count: pre.count + step,
}
})
}

render() {
let { count } = this.state

return <button onClick={this.increase}>click {count} times</button>
}
}

export default ButtonCounter
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
import React from "react"

class ButtonCounter extends React.Component {
constructor(props) {
super(props)

this.state = {
count: 0,
}
}

increase = () => {
let { step } = this.props

this.setState((pre) => {
return {
count: pre.count + step,
}
})
}

render() {
let { count } = this.state

return <div onMouseLeave={this.increase}>click {count} times</div>
}
}

export default ButtonCounter

使用 HOC 进行改造

HOC 通过传入的组件,返回一个新的组件。

1
2
3
4
5
6
7
8
9
10
11
12
13
import React from "react"

const withCounter = (OriginalComponent) => {
class newComponent extends React.Component {
render() {
return <OriginalComponent />
}
}

return newComponent
}

export default withCounter
Read more »

Iterator 概念

Iterator 是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构,只要部署 Iterator 接口,就可以完成遍历操作。
Iterator 的主要作用:为数据结构提供统一的、简便的访问接口;使得数据结构的成员能够按照某种次序排列;供 for…of 消费。
遍历过程如下:

  1. 创建一个指针对象,指向当前数据结构的起始位置。
  2. 第一次调用指针对象的 next 方法,将指针指向数据结构的第一个成员。
  3. 第二次调用 next 方法,指向第二个成员。
  4. 不断调用 next 方法,直到指针指向数据结构的结束位置。

每次调用 next 方法都会返回数据结构当前成员的信息,返回一个包含 value 的 done 两个属性的对象。value 属性是当前成员的值,done 属性是一个布尔值,表示遍历是否结束。
模拟 next 方法返回值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var it = makeIterator(['a', 'b'])
it.next() // { value : 'a', done : false }
it.next() // { value : 'b', done : false }
it.next() // { value : undefined, done : true }
function makeIterator(array) {
var nextIndex = 0
return {
next: function () {
return nextIndex < array.length
? { value: array[nextIndex++], done: false }
: { value: undefined, done: true }
},
}
}

遍历器与所遍历的数据结构实际上是分开的,完全可以写出没有对应数据结构的遍历器对象,或者用遍历器对象模拟出数据结构。无限运行的遍历器对象的例子:

1
2
3
4
5
6
7
8
9
10
11
12
var it = idMaker()
it.next().value // 0
it.next().value // 1
//...
function idMaker() {
var index = 0
return {
next: function () {
return { value: index++, done: false }
},
}
}
Read more »