# 2020.5

# 2020.5.2

# 1、div 垂直居中

# 方法一

  • magin:auto;
  • position:absolute;
  • left: 0;  bottom: 0;   right: 0;  top: 0;

# 方法二

  • left:50%;    top:50%;
  • transform: translate(-50%, -50%)
  • position: absolute;

# 方法三

  • left:50%;    top:50%;
  • magin-top: -height/2;
  • magin-left: -width/2;

# 2、antd 初使用

  • Icon 的使用方式——版本3 和版本4不一样了

# 2020.5.3

# Vue  "复"习

# 1、自定义 v-model

  • props
  • mode

注意一一对应如下图!!
image.png

# 2、插槽 slot

  • 默认插槽
  • 作用域插槽
  • 具名插槽

# 3、动态组件

  • 通过 :is

image.png

  • 当在这些组件之间切换的时候,你有时会想保持这些组件的状态,以避免反复重渲染导致的性能问题。
  • 这时可以用 keep-alive 把频繁切换、想缓存的组件缓存下来,在用 keep-alive 包裹的组件之间切换的时候,上一个组件不会被销毁,进入的组件也不会重新渲染。

# 4、异步组件

  • 不在统一的引入组件,而在需要用的时候用 import() 函数导入
  • 这样可以使得一个大组件加载的更快,性能优化的意思。


就是用图片中下面这种加载组件的方式代替上面的那个。起到 异步加载 的效果

image.png

# 4、vue 抽取不同组件相同逻辑

  • mixins (就是一段数据代码)

  • mixins 不是完美的解决方案

  • vue 3.0 Composition API 旨在解决这个问题

# 2020.5.5

# leetcode 384


let arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

function shuffle(arr) {
  let len = arr.length
  for (let i = 0; i < len; i++) {
    let randomIndex = Math.floor(Math.random() * (len - i));  //向下取整
    [arr[len - i - 1], arr[randomIndex]] = [arr[randomIndex], arr[len - i - 1]]
  }
  return arr
}
console.log(shuffle(arr))
1
2
3
4
5
6
7
8
9
10
11
12

# 2020.5.10

# 初识Redis







 



set jing meinv    //添加 key-value数据

get jing  //meinv 通过 key 获取 value

del jing         // 删除一个数据

setex key time value  //设置过期时间

keys *  //查出所有已经设置的 key
1
2
3
4
5
6
7
8
9

redis-server.exe redis.windows.conf 手动启动 Redis redis-cli -p 6378 指定端口启动 auth 密码 验证密码

# live-server --cors 设置允许跨域访问

# 2020.5.12

# next 中的页面跳转

import Link from 'next/link';
import Router from 'next/router';
import { Button } from 'antd';
export default () => {
  function goToB() {
    Router.push("/test/b")
  }
  return (
    <>
      <Link href="/a">
        <Button>Index</Button>
      </Link>
      <Button onClick={goToB}>test B</Button>
    </>
  )
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  • 1、采用Link标签
  • 2、采用 Router.push('路径')

Link标签其实底层也是用 Router.push('路径')来实现页面跳转的

# 2020.5.15

# next 中 _app.js 作用

  • 固定Layout
  • 保持一些公用的状态
  • 给页面传入一些自定义数据(重写一个MyApp)
  • 自定义错误处理
import App from 'next/app';

import 'antd/dist/antd.css';
import Layout from '../compontents/Layout';
class Myapp extends App {

  static async getInitialProps({ Component, ctx }) {
    console.log('app init')
    let pageProps
    if (Component.getInitialProps) {
      pageProps = await Component.getInitialProps(ctx)
    }
    return {
      pageProps
    }
  }

  render() {
    const { Component, pageProps } = this.props
    console.log(Component)
    return (
      <Layout>
        <Component {...pageProps} />
      </Layout>
    )
  }
}

export default Myapp
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

# 2020.5.17

# State Hooks 基础

  • 实现一个计时器
import React, { useEffect, useState, useReducer } from 'react';

//类组件
class MyCount extends React.Component {
  state = {
    count: 0
  }

  componentDidMount() {
    this.interval = setInterval(() => {
      this.setState({
        count: this.state.count + 1
      })
    }, 1000);
  }

  // 在 componentWillUnmount 生命周期函数里面清除定时器之类的
  // 不然会造成内存泄漏
  componentWillUnmount() {
    if (this.interval) {
      clearInterval(this.interval)
    }
  }

  render() {
    return (
      <span>{this.state.count}</span>
    )
  }
}

// useReducer
// 定义一个 'Reducer' 函数,它接受两个参数,第一个为 state,第二个为 action。 然后根据传进来的 action 操作 state
function countReducer(state, action) {
  switch (action.type) {
    case 'add':
      return state + 1
    case 'minus':
      return state - 1
    default:
      return state
  }
}

// 函数组件 hooks
function MyCountFunc() {
  // const [count, setCount] = useState(0)  //useState实现

  // useReducer 接受一个操作state的函数和 state 的初始值
  const [count, dispatchCount] = useReducer(countReducer, 0)    //useReducer实现 

  useEffect(() => {
    const interval = setInterval(() => {
      // setCount(count => count + 1)    //useState
      dispatchCount({ type: 'minus' })
    }, 1000)
    return () => clearInterval(interval)
  }, [])
  return <span>{count}</span>
}


export default MyCountFunc
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

# Effect Hooks 基础

# useEffect

  • 页面初始化useEffect会执行return 前面的代码。
  • 然后页面的任何数据更新了,组件就会重新渲染,就是先把原来的组件取消挂载,然后挂载重新渲染的组件。
  • 如下代码,初始化打印 effect invoked,更新页面先打印effect deteched,然后打印effect invoked
  • useEffect里面第二个参数是个数组 [],这个数组里面放useEffect用到的外面的数据(依赖)。然后useEffect就会根据数组里面的数据来判断要不要重新执行。只有写在里面的数据发生改变的时候,useEffect才会重新执行。如果是个空数组,不管啥数据改变了,useEffect都会执行。
useEffect(() => {
    console.log('Effect invoked')
    return () => console.log('Effect deteched')
  },[])
1
2
3
4

# useLayoutEffect 与 useEffect 的区别

  • useLayoutEffectuseEffect 先执行。
  • useLayoutEffect 是在页面更新时DOM树渲染成HTML之前执行的
  • useEffect 是在页面更新时DOM树渲染成HTML之后执行的
  • 所以很少用 useLayoutEffect,因为如果useLayoutEffect执行时间过长,页面渲染就会等待,造成页面卡顿,降低用户体验。

# 2020.5.18

# Redux reducer

# 1、是一个纯粹的方法,不应该有任何副作用

  • 就是不能在 reducer 中依赖外部变量。

# 2、有任何数据更新应该返回新的对象

  • redux 中使用 reducer 返回 state 的时候必须返回一个新对象!!!
  • 因为在 js 中判断一个对象是否相等比较的是它们在栈中对堆的引用地址。
  • 如果不返回一个新对象,在 ReactDOM 对比节点是否相同的时候就算你修改了某个状态,但是返回的还是原来的对象, React 就会认为此 DOM 没变,就会产生错误。

# 3、可以用 combineReducers 合并不同的 reducer

# 实例代码

import { createStore, combineReducers } from 'redux'

const countInitialState = {
  count: 0,
}

const userInitialState = {
  username: 'jing'
}

const ADD = 'ADD'

function countReducer(state = countInitialState, action) {
  // console.log(state, action)
  switch (action.type) {
    case ADD:
      return { count: state.count + 1 }
    default:
      return state
  }
}

const UPDATE_USERNAME = 'UPDATE_USERNAME'
function userReducer(state = userInitialState, action) {
  switch (action.type) {
    case UPDATE_USERNAME:
      return {
        ...state,
        username: action.username
      }
    default:
      return state
  }
}

// 使用 combineReducers 合并 reducer
const allReducers = combineReducers({
  count: countReducer,
  username: userReducer
})

// createStore中 传入合并后的 reducer
const store = createStore(allReducers, {
  count: countInitialState,
  username: userInitialState
})

// console.log(store.getState())
// store.dispatch({ type: 'ADD' })

store.subscribe(() => {
  console.log(store.getState())
})

// 通过 dispatch 一个 action 来操作数据
store.dispatch({ type: ADD })
store.dispatch({ type: UPDATE_USERNAME, username: 'jingjing20' })

// console.log(store.getState())

export default store
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

# 2020.5.19

# OAuth 认证方式如何保证安全性

  • 一次性 code 获取 —— https://github.com/login/oauth/authorize?client_id=204d73ec49b937657d99
  • client_id + client_secret
  • redirect_uri —— 用户注册 OAuth github App 的时候自己填的 callback 地址。

https://developer.github.com/apps/building-oauth-apps/authorizing-oauth-apps/

# 2020.5.20

# 今天放假

# 咋代码也不能停!

# LeetCode 125 验证回文串

  • 题目描述 给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。

说明:本题中,我们将空字符串定义为有效的回文串。

示例 1:

输入: "A man, a plan, a canal: Panama" 输出: true 示例 2:

输入: "race a car" 输出: false

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/valid-palindrome

# 解法一(API大法)

var isPalindrome = function (s) {
  let newStr = s.replace(/[^0-9a-zA-Z]/g, '').toLowerCase().split('')
  return newStr.join('') == newStr.reverse().join('')
};
1
2
3
4

# 解法二(双指针)

var isPalindrome = function (s) {
  let newStr = s.replace(/[^0-9a-zA-Z]/g, '').toLowerCase()
  let l = 0, r = newStr.length - 1;

  while (l < r) {
    if (newStr[l] != newStr[r]) {
      return false
    }
    l++
    r--
  }
  return true
};
1
2
3
4
5
6
7
8
9
10
11
12
13

# 2020.5.21

# 进程与线程

# 概念

线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中实际运作单位。

# 区别

# 内存使用方面的区别

  • 进程拥有操作系统分配给它的单独的内存,默认情况一个进程的分配的内存无法给另一个进程共享。
  • 一个进程里面的所有线程可以共享进程内存。

# 通信机制方面的区别

  • 进程之间很难互通,可以通过 IPC (进程间通信)。
  • 线程之间共用一块内存,通信方便快捷。

# 量级方面的区别

  • 线程相对于进程创建起来更轻、更快,使用的资源更少。

# nodemon 使用

"start": "nodemon --watch main.js --exec \"electron .\""

  • --watch 监听哪个文件
  • --exec 执行哪个文件
  • 用 \ 转义""

# 2020.5.22

# window.onload 和 DOMContentLoaded 的区别

DOM完整的解析过程:

  • 1、解析HTML结构
  • 2、加载外部脚本和样式表文件
  • 3、解析并执行脚本代码(js)
  • 4、DOM 树构建完成
  • 5、加载图片等外部文件
  • 6、页面加载完毕

# 在第4步的时候DOMContentLoaded事件会被触发。

# 在第6步的时候load事件会被触发。

# 2020.5.23

# Infinity

  • Infinity 是一个 JavaScript 标准内置对象

  • 全局属性 Infinity 是一个数值,表示无穷大。

  • Infinity 是全局对象(global object)的一个属性,即它是一个全局变量。

  • Infinity 的初始值是 Number.POSITIVE_INFINITY。Infinity(正无穷大)大于任何值。该值和数学意义上的无穷大很像,例如任何正值乘以 Infinity 为 Infinity, 任何数值除以 Infinity 为 0(注意,这里说的是正数乘以Infinity 为 Infinity!Infinity * 0 为NaN。

# slice(begin, end)

begin

  • 提取起始处的索引(从 0 开始),从该索引开始提取原数组元素。
  • 如果该参数为负数,则表示从原数组中的倒数第几个元素开始提取。
  • slice(-2) 表示提取原数组中的倒数第二个元素到最后一个元素(包含最后一个元素)。
  • 如果省略 begin,则 slice 从索引 0 开始。
  • 如果 begin 大于原数组的长度,则会返回空数组。

end

  • 提取终止处的索引(从 0 开始),在该索引处结束提取原数组元素。
  • slice 会提取原数组中索引从 begin 到 end 的所有元素(包含 begin,但不包含 end)
  • slice(1,4) 会提取原数组中从第二个元素开始一直到第四个元素的所有元素 (索引为 1, 2, 3的元素)。
  • 如果该参数为负数, 则它表示在原数组中的倒数第几个元素结束抽取。 slice(-2,-1) 表示抽取了原数组中的倒数第二个元素到最后一个元素(不包含最后一个元素,也就是只有倒数第二个元素)。
  • 如果 end 被省略,则 slice 会一直提取到原数组末尾。
  • 如果 end 大于数组的长度,slice 也会一直提取到原数组末尾。