Store的设计
- 集中式存储:采用单一数据源的模式,将所有需要共享的状态集中存储在一个Store对象中。例如使用Redux或MobX这类状态管理库,在Redux中,整个应用的状态都保存在一个store中。这样可以方便各个组件获取和修改状态,同时保证状态的一致性。
- 状态结构规划:根据不同类型的事件和业务逻辑,合理规划Store中状态的结构。例如,将与鼠标移动相关的状态(如鼠标坐标)和表单提交相关的状态(如表单数据)分开存放,使状态结构清晰,易于维护。
事件监听与处理机制
- 事件绑定:
- 鼠标移动事件:在相关组件(如具有交互区域的DOM元素对应的组件)中,通过事件绑定函数(如在React中使用
addEventListener
或useEffect
结合addEventListener
)监听mousemove
事件。当事件触发时,调用相应的Action(在Redux中)或Mutation(在Vuex中)来更新Store中的状态。例如,在React + Redux应用中:
import React, { useEffect } from'react';
import { useDispatch } from'react-redux';
import { updateMousePosition } from '../actions';
const InteractiveComponent = () => {
const dispatch = useDispatch();
useEffect(() => {
const handleMouseMove = (e) => {
dispatch(updateMousePosition({ x: e.clientX, y: e.clientY }));
};
window.addEventListener('mousemove', handleMouseMove);
return () => {
window.removeEventListener('mousemove', handleMouseMove);
};
}, [dispatch]);
return <div>Interactive Area</div>;
};
export default InteractiveComponent;
- 表单提交事件:在表单组件中,监听
submit
事件。同样通过调用相应的Action或Mutation来更新Store中与表单相关的状态。如在React中:
import React from'react';
import { useDispatch } from'react-redux';
import { submitFormData } from '../actions';
const FormComponent = () => {
const dispatch = useDispatch();
const handleSubmit = (e) => {
e.preventDefault();
const formData = new FormData(e.target);
dispatch(submitFormData(Object.fromEntries(formData.entries())));
};
return (
<form onSubmit={handleSubmit}>
{/* form fields */}
<input type="submit" value="Submit" />
</form>
);
};
export default FormComponent;
- 事件处理:
- Redux方式:在Redux中,Actions是普通的JavaScript对象,描述了发生的事件。Reducers根据Actions来更新Store的状态。例如,对于鼠标移动事件的Action和Reducer:
// actions.js
export const updateMousePosition = (position) => ({
type: 'UPDATE_MOUSE_POSITION',
payload: position
});
// reducers.js
const initialState = {
mousePosition: { x: 0, y: 0 }
};
const rootReducer = (state = initialState, action) => {
switch (action.type) {
case 'UPDATE_MOUSE_POSITION':
return {
...state,
mousePosition: action.payload
};
default:
return state;
}
};
export default rootReducer;
- MobX方式:在MobX中,可观察状态(observable state)会自动响应变化。当事件触发时,调用修改状态的函数,MobX会自动跟踪依赖并更新相关组件。例如:
import { makeObservable, observable, action } from'mobx';
class Store {
mousePosition = { x: 0, y: 0 };
formData = {};
constructor() {
makeObservable(this, {
mousePosition: observable,
formData: observable,
updateMousePosition: action,
submitFormData: action
});
}
updateMousePosition = (position) => {
this.mousePosition = position;
};
submitFormData = (data) => {
this.formData = data;
};
}
const store = new Store();
export default store;
避免不必要的重渲染
- 使用Memoization技术:
- React.memo:在React中,对于那些只依赖于props的纯展示组件,可以使用
React.memo
进行包裹。它会浅比较组件的props,如果props没有变化,组件不会重新渲染。例如:
const DisplayComponent = React.memo(({ mousePosition }) => {
return <div>Mouse position: {mousePosition.x}, {mousePosition.y}</div>;
});
- useMemo和useCallback:
useMemo
用于缓存计算结果,只有当依赖项发生变化时才重新计算。useCallback
用于缓存函数,防止函数在每次渲染时重新创建,从而避免不必要的重渲染。例如:
import React, { useCallback, useMemo } from'react';
import { useSelector } from'react-redux';
const ComplexComponent = () => {
const mousePosition = useSelector(state => state.mousePosition);
const expensiveCalculation = useMemo(() => {
// 复杂计算逻辑
return mousePosition.x * mousePosition.y;
}, [mousePosition]);
const handleClick = useCallback(() => {
// 点击处理逻辑
}, []);
return (
<div>
<p>Expensive calculation result: {expensiveCalculation}</p>
<button onClick={handleClick}>Click me</button>
</div>
);
};
export default ComplexComponent;
- 粒度控制:
- 状态拆分:将Store中的状态进行合理拆分,使每个组件只订阅它真正需要的状态。例如,一个只显示鼠标位置的组件只订阅鼠标位置相关的状态,而不订阅表单提交相关的状态。这样,当表单提交状态变化时,显示鼠标位置的组件不会重渲染。
- 局部状态管理:对于一些只在组件内部使用,不涉及多组件共享的状态,使用组件自身的局部状态(如React中的
useState
)进行管理。这样可以避免因共享状态的变化而导致不必要的重渲染。例如,一个组件内部的展开/折叠状态,就适合使用局部状态管理。