面试题答案
一键面试减少不必要重新渲染的策略及代码实现
- 使用
createMemo
- 策略:
createMemo
可以缓存一个值,只有当它依赖的响应式数据发生变化时才会重新计算。对于复杂应用中一些计算成本较高的派生数据,使用createMemo
可以避免在无关状态变化时重复计算,从而减少重新渲染。 - 代码实现:
在上述代码中,import { createSignal, createMemo } from'solid-js'; const [count, setCount] = createSignal(0); const [otherValue, setOtherValue] = createSignal(''); const expensiveCalculation = createMemo(() => { // 模拟复杂计算 let result = 0; for (let i = 0; i < 1000000; i++) { result += i; } return result * count(); }); const App = () => { return ( <div> <p>Count: {count()}</p> <p>Other Value: {otherValue()}</p> <p>Expensive Calculation: {expensiveCalculation()}</p> <button onClick={() => setCount(count() + 1)}>Increment Count</button> <button onClick={() => setOtherValue('new value')}>Change Other Value</button> </div> ); };
expensiveCalculation
依赖count
,当otherValue
变化时,expensiveCalculation
不会重新计算,因为它不依赖otherValue
,减少了不必要的重新渲染。 - 策略:
- 使用
Memo
组件- 策略:
Memo
组件可以包裹子组件,只有当它的props
发生变化时才会重新渲染子组件。对于嵌套组件,在一些组件接收的props
不常变化的情况下,使用Memo
可以避免不必要的重新渲染。 - 代码实现:
在这个例子中,import { createSignal } from'solid-js'; import { Memo } from'solid-js/web'; const [count, setCount] = createSignal(0); const ChildComponent = Memo((props) => { return <p>{props.value}</p>; }); const App = () => { return ( <div> <ChildComponent value="Some static value" /> <button onClick={() => setCount(count() + 1)}>Increment Count</button> </div> ); };
ChildComponent
包裹在Memo
中,即使count
变化(与ChildComponent
的props
无关),ChildComponent
也不会重新渲染,因为它的props
没有改变。 - 策略:
- 拆分状态
- 策略:将大的状态对象拆分成多个小的状态,使得每个状态的变化只影响依赖它的部分组件。这样可以避免一个大状态的微小变化导致大量无关组件重新渲染。
- 代码实现:
这里将用户信息拆分成import { createSignal } from'solid-js'; const [userName, setUserName] = createSignal(''); const [userAge, setUserAge] = createSignal(0); const UserNameComponent = () => { return ( <div> <input type="text" value={userName()} onChange={(e) => setUserName(e.target.value)} /> <p>Name: {userName()}</p> </div> ); }; const UserAgeComponent = () => { return ( <div> <input type="number" value={userAge()} onChange={(e) => setUserAge(Number(e.target.value))} /> <p>Age: {userAge()}</p> </div> ); }; const App = () => { return ( <div> <UserNameComponent /> <UserAgeComponent /> </div> ); };
userName
和userAge
两个状态,修改userName
不会导致UserAgeComponent
重新渲染,反之亦然。 - 使用
createEffect
正确处理副作用- 策略:
createEffect
用于处理副作用操作,如订阅、定时器等。正确使用createEffect
可以确保副作用只在相关状态变化时执行,避免因副作用不当处理导致的不必要重新渲染。 - 代码实现:
在上述代码中,import { createSignal, createEffect } from'solid-js'; const [count, setCount] = createSignal(0); createEffect(() => { // 模拟副作用,比如更新文档标题 document.title = `Count is ${count()}`; }); const App = () => { return ( <div> <p>Count: {count()}</p> <button onClick={() => setCount(count() + 1)}>Increment Count</button> </div> ); };
createEffect
会在count
变化时更新文档标题,并且不会因为其他无关状态变化而重复执行这个副作用操作,从而避免了不必要的重新渲染。 - 策略: