文章目录
- vue与react的区别。
- react的生命周期有哪些及它们的作用。
- setState是同步的还是异步的。
- 如何更新数据后,立刻获取最新的dom或者更新后的数据。
- 使用回调函数:
- 在生命周期方法中处理:
- 函数式组件和class组件的区别。
- class组件
- 函数式组件
- 区别
- 常用的hooks有哪些。
- 自定义hooks。
- 使用自定义 Hooks 时的注意点:
- 创建自定义 Hooks 时的注意点:
- 为什么同一个hooks调用很多次,其不同的结果都能被保存并返回来。
- 手写一个useState的实现原理。
- useEffect如何消除副作用。
- react如何优化每次父组件数据更新,子组件也会更新。
- 1. 使用 `React.memo`:
- 2. 使用 `shouldComponentUpdate`:
- 3. 将不变的函数移到外部:
- 4. 使用 useCallback 和 useMemo:
- 5. 使用 React Developer Tools 分析性能:
- memo和useMemo的区别。
- react虚拟dom。
- 1. 创建虚拟 DOM:
- 2. 对比虚拟 DOM:
- 3. 计算差异:
- 4. 更新真实 DOM:
- 5. 提高性能:
- 虚拟 DOM 的优势:
vue与react的区别。
Vue.js和React.js都是流行的JavaScript库,用于构建用户界面,但它们有一些关键的区别。以下是一些Vue.js和React.js之间的主要区别:
-
设计和理念:
- Vue.js: 设计简单、灵活,更容易上手。Vue强调渐进式框架,可以逐步地应用到项目中。
- React.js: 设计更加灵活且功能强大,但可能对初学者有一定的学习曲线。React注重构建可复用的组件。
-
模板语法和 JSX:
- Vue.js: 使用基于HTML的模板语法,将模板直接写在HTML中。
- React.js: 使用JSX(JavaScript XML),这是一种在JavaScript中嵌套XML标签的语法。JSX允许在JavaScript代码中直接编写类似XML的结构。
-
组件通信:
- Vue.js: 支持父子组件通信、兄弟组件通信、以及通过事件总线或Vuex(状态管理库)进行跨组件通信。
- React.js: 父子组件通信通过props,而跨组件通信通常需要通过提升状态(lifting state up)或使用全局状态管理库,如Redux。
-
状态管理:
- Vue.js: 包含了Vuex,一个专门用于状态管理的库。Vuex提供了一种集中式管理状态的方式。
- React.js: 可以使用Context API来进行状态管理,但更常见的是使用独立的状态管理库,如Redux。
-
生命周期:
- Vue.js: 拥有明确的生命周期钩子,例如
beforeCreate
、created
、mounted
等。 - React.js: 也有生命周期方法,包括
componentDidMount
、componentWillUnmount
等。
- Vue.js: 拥有明确的生命周期钩子,例如
-
指令和特性:
- Vue.js: 提供了丰富的指令,如
v-if
、v-for
、v-bind
等,用于操作DOM。 - React.js: 使用属性(props)和状态(state)来管理组件的渲染和行为。
- Vue.js: 提供了丰富的指令,如
-
学习曲线:
- Vue.js: 相对较低的学习曲线,尤其适合初学者。
- React.js: 初始学习曲线可能较陡峭,但一旦掌握了基本概念,会变得更容易。
-
社区和生态系统:
- Vue.js: 在中国社区有较大影响力,生态系统不如React庞大,但在一些场景中更受欢迎。
- React.js: 拥有庞大的社区和生态系统,广泛应用于大型项目和企业级应用。
react的生命周期有哪些及它们的作用。
https://blog.csdn.net/glorydx/article/details/103358868 react生命周期介绍
setState是同步的还是异步的。
在 React 中,setState
方法通常是异步的。这是因为 React 会对多个 setState
调用进行批处理,以提高性能。React 将这些 setState
调用合并成一个单一的更新,然后异步地应用到组件状态。
这种异步的行为有一些重要的方面:
-
在事件处理函数中的异步行为:
handleClick() { this.setState({ count: this.state.count + 1 }); console.log(this.state.count); // 不一定会立即更新 }
上述代码中,
console.log
不一定会在setState
之后立即显示更新后的状态。React 在合适的时候异步地执行状态更新。 -
setState
接受函数参数的情况:this.setState((prevState) => { return { count: prevState.count + 1 }; });
当
setState
接受一个函数作为参数时,React 会在合适的时候调用这个函数,提供最新的状态,以确保正确的更新。 -
componentDidUpdate
中的异步行为:componentDidUpdate() { console.log(this.state.count); // 不一定会立即更新 }
在
componentDidUpdate
生命周期方法中,this.state
不一定会立即反映最新的状态,因为状态更新是异步的。
虽然 setState
是异步的,但React提供了一些能够在状态更新后执行的回调函数,可以通过将回调函数作为 setState
的第二个参数来实现:
this.setState({ count: this.state.count + 1 }, () => {
console.log(this.state.count); // 在回调函数中可以访问到最新的状态
});
总体而言,理解 setState
的异步行为对于正确地处理 React 组件的状态和生命周期是很重要的。
更多关于setstate
介绍
react 玩转state和setState
如何更新数据后,立刻获取最新的dom或者更新后的数据。
在 React 中,setState
是异步的,因此在调用 setState
后,不能立即获得更新后的状态或 DOM。如果你需要在 setState
完成并且组件已经重新渲染后执行一些操作,你可以使用回调函数或者在生命周期方法中处理。
使用回调函数:
this.setState({ count: this.state.count + 1 }, () => {
// 在回调函数中可以访问到最新的状态
console.log("Updated count:", this.state.count);
// 这里可以执行其他需要在状态更新后立即执行的操作
});
在生命周期方法中处理:
如果你需要在组件更新后执行操作,可以在 componentDidUpdate
生命周期方法中处理:
componentDidUpdate(prevProps, prevState) {
// 检查状态是否发生变化
if (this.state.count !== prevState.count) {
console.log("Updated count:", this.state.count);
// 这里可以执行其他需要在状态更新后立即执行的操作
}
}
在 componentDidUpdate
中,你可以比较当前状态和之前的状态,然后执行相应的操作。需要注意的是,在使用这种方法时,确保你不会陷入无限循环的状态,即在 componentDidUpdate
中再次调用 setState
导致组件再次更新。
选择使用回调函数还是生命周期方法取决于你的具体需求和场景。如果你需要访问最新的状态,回调函数是一个更直接的方式。如果你需要在组件更新后执行其他操作,componentDidUpdate
可能更适合。
函数式组件和class组件的区别。
class组件
class ClassComponentWithState extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0,
};
}
componentDidMount() {
document.title = `Count: ${this.state.count}`;
}
componentDidUpdate(prevProps, prevState) {
if (this.state.count !== prevState.count) {
document.title = `Count: ${this.state.count}`;
}
}
render() {
return (
<div>
<p>{this.props.message}</p>
<p>Count: {this.state.count}</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Increment
</button>
</div>
);
}
}
函数式组件
import React, { useState, useEffect } from 'react';
const FunctionalComponentWithState = (props) => {
const [count, setCount] = useState(0);
useEffect(() => {
// 这里可以处理副作用,类似于 componentDidMount 和 componentDidUpdate
document.title = `Count: ${count}`;
}, [count]);
return (
<div>
<p>{props.message}</p>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
};
区别
class组件特点:
- 有组件实例
- 有生命周期
- 有 state 和 setState
函数组件特点:
- 没有组件实例
- 没有生命周期
- 没有 state 和 setState,只能接收 props
- 函数组件是一个纯函数,执行完即销毁,无法存储 state
常用的hooks有哪些。
usestate
,useEffect
,usememo
,useCallback
,useReducer
,useContext
自定义hooks。
自定义 Hooks 是一种用于在 React 函数式组件之间共享状态逻辑的机制。创建自定义 Hooks 可以帮助您将可复用的逻辑提取出来,以便在多个组件中共享。以下是使用和创建自定义 Hooks 时的一些建议和注意点:
使用自定义 Hooks 时的注意点:
-
命名规范:
- 自定义 Hook 的命名应以 “use” 开头,这是 React 社区的一种约定,帮助开发者识别其为 Hook。
function useCustomHook() { // ... }
-
多次使用:
- 自定义 Hook 可以在一个或多个组件中使用,使得逻辑的重用更加灵活。
function ComponentA() { const data = useCustomHook(); // ... } function ComponentB() { const data = useCustomHook(); // ... }
-
不包含组件生命周期:
- 自定义 Hook 中不应包含与组件生命周期相关的逻辑,例如
componentDidMount
或componentDidUpdate
。这样的逻辑应该由使用 Hook 的组件自行处理。
- 自定义 Hook 中不应包含与组件生命周期相关的逻辑,例如
-
不依赖组件内部状态:
- 自定义 Hook 应该是无状态的,不依赖组件内部的状态。如果 Hook 需要保存状态,应该通过 Hook 的返回值提供给组件。
创建自定义 Hooks 时的注意点:
-
返回值:
- 自定义 Hook 应该返回一个可用于组件的值,通常是状态和更新状态的函数。确保返回值对于使用 Hook 的组件是直观和易用的。
function useCustomHook() { const [value, setValue] = useState(initialValue); // 其他逻辑... return { value, setValue }; }
-
参数:
- 如果需要,可以通过参数将定制的配置传递给自定义 Hook。这样可以使 Hook 更灵活,适应不同的用例。
function useCustomHook(config) { const [value, setValue] = useState(config.initialValue); // 其他逻辑... return { value, setValue }; }
-
提取共享逻辑:
- 将多个组件之间共享的逻辑提取到自定义 Hook 中,以确保逻辑的一致性和可维护性。
function useSharedLogic() { // 共享逻辑... } function ComponentA() { useSharedLogic(); // ... } function ComponentB() { useSharedLogic(); // ... }
-
避免与组件耦合:
- 自定义 Hook 应该是独立于组件的,不依赖于组件的实现细节。这有助于确保 Hook 的通用性和可重用性。
// 不好的例子,过于与组件耦合 function useBadCustomHook() { const [value, setValue] = useState(0); useEffect(() => { console.log("Component did mount"); }, []); return { value, setValue }; } // 好的例子,不与组件耦合 function useGoodCustomHook() { const [value, setValue] = useState(0); return { value, setValue }; }
使用和创建自定义 Hooks 时,遵循这些注意点可以帮助您创建出易于理解、复用和维护的逻辑。
为什么同一个hooks调用很多次,其不同的结果都能被保存并返回来。
跟vue的data一样,hooks本身也是函数,函数返回的数据是在函数内部生成的,每一次调用hook,都在函数内部生成一个新的数据并抛出,组件内部用变量接收后,相当于形成闭包,函数执行完,并不会摧毁函数的执行期上下文,所以变量也不会被释放。
手写一个useState的实现原理。
function useState(init) {
let state;
// useState无法保存函数
if(typeof init === 'function') {
state = init()
} else {
state = init
}
const setState = (change) => {
// 判断一下是否传递过来的是函数
if(typeof change === 'function') {
// 如果是函数,调用,并将之前的state传过去,接收到的返回值作为新的state并赋值
state = change(state)
} else {
// 如果不是函数,直接赋值
state = change;
}
}
return [state, setState]
}
更多useState使用介绍请看
react使用usestate踩坑
useEffect如何消除副作用。
useeffect可以返回一个回调函数,函数体将在组件卸载前执行,用以消除副作用。
import React, { useEffect } from 'react';
function DOMManipulationComponent() {
useEffect(() => {
// 手动操作 DOM
const element = document.getElementById('exampleElement');
element.style.color = 'red';
// 在组件卸载时进行清理操作
return () => {
element.style.color = ''; // 恢复原始样式
};
}, []); // 空数组表示仅在组件挂载和卸载时执行
return <div id="exampleElement">DOM Manipulation Example</div>;
}
react如何优化每次父组件数据更新,子组件也会更新。
在 React 中,当父组件的数据更新时,子组件通常也会更新。React 通过 Virtual DOM 和一些智能的渲染机制来优化这个过程,确保只有实际发生变化的部分才会更新。然而,有时候我们可能需要进一步优化,以避免不必要的子组件更新。
以下是一些优化子组件更新的方法:
1. 使用 React.memo
:
React.memo
是一个高阶组件,用于对函数式组件进行浅层的 props 比较,以避免不必要的重新渲染。它可以用于包裹子组件,只有在传递给子组件的 props 发生变化时才会重新渲染。
import React, { memo } from 'react';
const MemoizedComponent = memo(({ data }) => {
// 只有 data 发生变化时才会重新渲染
return <div>{data}</div>;
});
2. 使用 shouldComponentUpdate
:
对于类组件,可以手动实现 shouldComponentUpdate
方法来控制组件是否应该更新。
class PureComponentClassComponent extends React.PureComponent {
shouldComponentUpdate(nextProps) {
// 只有当 nextProps.data 发生变化时才会重新渲染
return nextProps.data !== this.props.data;
}
render() {
return <div>{this.props.data}</div>;
}
}
3. 将不变的函数移到外部:
确保传递给子组件的函数是不变的,以避免每次父组件更新时都重新生成函数。
function ParentComponent() {
const handleClick = () => {
// 处理点击事件
};
return <ChildComponent onClick={handleClick} />;
}
4. 使用 useCallback 和 useMemo:
使用 useCallback
和 useMemo
来缓存函数和计算结果,以避免不必要的重新计算和函数生成。
import React, { useCallback, useMemo } from 'react';
function ParentComponent({ data }) {
const handleClick = useCallback(() => {
// 处理点击事件
}, []);
const processedData = useMemo(() => {
// 计算结果
return data.map(item => item * 2);
}, [data]);
return <ChildComponent data={processedData} onClick={handleClick} />;
}
5. 使用 React Developer Tools 分析性能:
使用 React Developer Tools 来检查组件的渲染和更新,找出造成不必要更新的原因。这可以帮助您更好地理解组件渲染的情况。
通过结合上述方法,您可以更精确地控制子组件的更新,从而提高应用程序的性能。请注意,这些优化方法的适用性取决于具体的使用场景,需要根据实际情况来选择和结合使用。
memo和useMemo的区别。
useMemo 是一个自定义 Hook,它用于在渲染过程中执行昂贵的计算,并缓存计算结果,以便在后续的渲染中重复使用。
React.memo 是一个高阶组件,用于对函数式组件进行浅层的 props 比较,如果组件的 props 没有发生变化,将会阻止不必要的重新渲染。
react虚拟dom。
虚拟 DOM(Virtual DOM)是 React 中一种用于提高性能的技术。它是一个内存中的表示,类似于真实 DOM 树的结构。React 使用虚拟 DOM 来进行高效的 DOM 操作,减少直接操作真实 DOM 的次数,从而提高应用性能。
以下是虚拟 DOM 的基本原理和工作流程:
1. 创建虚拟 DOM:
当 React 组件的状态(state)或属性(props)发生变化时,React 会重新渲染组件。在重新渲染之前,React 会创建一个新的虚拟 DOM 树,以表示更新后的组件结构。
2. 对比虚拟 DOM:
React 使用一种叫做“协调算法”的机制,来比较新的虚拟 DOM 树和之前的虚拟 DOM 树。这个算法能够找出两个树之间的差异(所谓的“差异树”)。
3. 计算差异:
通过计算差异,React 知道在更新真实 DOM 时应该做什么。这包括哪些节点需要被添加、删除、更新,以及如何更新它们。
4. 更新真实 DOM:
一旦计算出了差异,React 就会将这些变化应用到真实 DOM 上。为了尽可能减少对真实 DOM 的直接操作,React 采用了一种批处理的方式,将所有变更一次性应用到真实 DOM。
5. 提高性能:
由于虚拟 DOM 的存在,React 能够减少直接操作真实 DOM 的次数。通过批处理和智能的差异计算,React 能够更有效地更新用户界面,提高应用的性能。
虚拟 DOM 的优势:
-
性能提升: 通过在内存中进行比较和计算,减少直接操作真实 DOM 的次数,提高了性能。
-
跨平台兼容性: 虚拟 DOM 可以在不同平台上运行,使得 React 可以同时支持 Web、原生移动应用和其他平台。
-
方便的抽象层: 虚拟 DOM 提供了一个抽象层,使得开发者可以更方便地操作组件和状态,而不用过多关心底层的 DOM 操作。
虽然虚拟 DOM 为 React 带来了性能的提升,但并不是所有情况下都需要手动操作虚拟 DOM。React 提供了高度抽象的 API,大部分情况下开发者只需要关心组件的声明和状态更新,React 会自动处理虚拟 DOM 的创建和更新。