一、React Hook(部分)
1.useEffect
useEffect 用于处理组件中的 effect,通常用于请求数据,事件处理,订阅等相关操作。
1.当 useEffect 没有第二个参数时,useEffect 会不停的调用
2.当 useEffect 第二个参数为空数组时,仅在组件挂载和卸载时调用
3.当 useEffect 第二个参数为变量时,例如[count],useEffect 会在 count 变化时调用
4.useEffect 清除,useEffect 通过 return 进行一些清除
2.useState
const [state,setState] = useState(initialState);
返回一个 state,以及更新 state 的函数。
在初始渲染期间,返回的状态 (state) 与传入的第一个参数 (initialState) 值相同。
setState 函数用于更新 state。它接收一个新的 state 值并将组件的一次重新渲染加入队列。
操作:setState(newState);
3.useReducer
const [state,dispatch] = useReducer(reducer, initialState);
useReducer 是 useState 的替代方案。它接收一个形如 (state, action) => newState 的 reducer,并返回当前的 state 以及与其配套的 dispatch 方法。
useReducer 接收两个参数:
第一个参数:reducer 函数。
第二个参数:初始化的 state。返回值为最新的 state 和 dispatch 函数(用来触发 reducer 函数,计算对应的 state)
// useState 计数器
function Counter({initialCount}) {
const [count, setCount] = useState(initialCount);
return (
<>
Count: {count}
<button onClick={() => setCount(initialCount)}>Reset
<button onClick={() => setCount(prevCount => prevCount - 1)}>-
<button onClick={() => setCount(prevCount => prevCount + 1)}>+
</>
);
}
// reducer 计数器
const initialState = {count: 0};
const reducer = (state, action) => {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
default:
throw new Error();
}
};
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
Count: {state.count}
<button onClick={() => dispatch({type: 'decrement'})}>-
<button onClick={() => dispatch({type: 'increment'})}>+
</>
);
}
// 返回一个 newState (newObject)
function countReducer(state, action) {
switch(action.type) {
case 'add':
return { ...state, count: state.count + 1; }
case 'sub':
return { ...state, count: state.count - 1; }
default:
return count;
}
}
//三个点(...)真名叫扩展运算符,是在ES6中新增加的内容,它可以在函数调用/数组构造时,将数组表达式或者string在语法层面展开;还可以在构造字面量对象时将对象表达式按照key-value的方式展开。
在某些场景下,useReducer 会比 useStatee适用,例如 state 逻辑较复杂且包含多个子值,或者下一个 state 依赖于之前的 state 等。并且,使用 useReducer 还能给那些会触发深更新的组件做性能优化。
const [{ state1, state2 }, setState] = useReducer(
(state: any, payload: any) => {
return {
...state,
...payload,
};
},
{ state1: false, state2: undefined }
);
操作:setState({state1: newState});
二、数据处理
1.深拷贝
深拷贝开辟一个新的栈,两个对象属完成相同,但是对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性。
function cloneDeep(obj) {
// 1.判断是否为null 或undefined
if (typeof obj == null) return obj;
// 2.判断是否为日期Date
if (obj instanceof Date) return new Date(obj);
// 3.判断是否为正则 typeof /\d+/ === 'object'
if (obj instanceof RegExp) return new RegExp(obj);
// 4.如果不是数组或对象,返回该值
if (typeof obj !== "object") return obj;
// 接下来,要么是对象,要么是数组 可以用 new obj.constructor得到它类型的空值
let cloneObj = new obj.constructor();
for (const key in obj) {
// 递归深拷贝
cloneObj[key] = cloneDeep(obj[key]);
}
return cloneObj;
}
2.数组去重
纯数字数组去重
function uniqueArray(arr) {
return [...new Set(arr)];
}
对象数组根据对应属性进行去重
function uniqueFunc(arr, uniId) {
const map = new Map();
return arr.filter((item) => !map.has(item[uniId]) && map.set(item[uniId], 1));
}
三、CSS 选择器权重
规则:(x,y,z)
x:id 选择器的数量
y:类、伪类、属性的数量
z:元素、伪元素的数量
.container #list::before {} //(1,1,1)
.container #list a::before {} //(1,1,2)
.container .form input[type="text"] {} //(0,3,1)
.container ul a:hover {} //(0,2,2)
四、Q and A
Question
//? 位置应该怎么写才能输出为true;
var a = ?;
console.log(a1 && a2 && a==3);
Answer
var a = {
n: 1,
valueOf: function () {
return this.n++;
},
};
Analysis
的判断规则:
1.特殊类型,如 undefined == null,NaN ! NaN
2.类型相同,直接比较值
3.类型不同:均为原始类型时,转换为数字进行比较。一端为原始类型一端为对象时,对象转为原始类型后比较。对象转原始类型的过程为,先调用 valueOf(),若无法转换成原始类型,再调用 toString()