持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第11天,点击查看活动详情
内嵌响应式
Solid可以独立处理嵌套更新的原因之一就是它提供了细粒度响应式。你可以提供一个列表,更新数据时只会更新dom的一个位置,并不会对列表本身进行差异对比。
如:
import { render } from "solid-js/web";
import { For, createSignal } from "solid-js";
const App = () => {
const [todos, setTodos] = createSignal([])
let input;
let todoId = 0;
const addTodo = (text) => {
const [completed, setCompleted] = createSignal(false);
setTodos([...todos(), { id: ++todoId, text, completed, setCompleted }]);
}
const toggleTodo = (id) => {
const index = todos().findIndex((t) => t.id === id);
const todo = todos()[index];
if (todo) todo.setCompleted(!todo.completed())
}
return (
<>
<div>
<input ref={input} />
<button
onClick={(e) => {
if (!input.value.trim()) return;
addTodo(input.value);
input.value = "";
}}
>
Add Todo
</button>
</div>
<For each={todos()}>
{(todo) => {
const { id, text } = todo;
console.log(`Creating ${text}`)
return <div>
<input
type="checkbox"
checked={todo.completed()}
onchange={[toggleTodo, id]}
/>
<span
style={{ "text-decoration": todo.completed() ? "line-through" : "none"}}
>{text}</span>
</div>
}}
</For>
</>
);
};
render(App, document.getElementById("app"));
在实例中,我们在Signal中存放待办事项列表。为了将待办事项标记为完成,我们需要用克隆对象替换旧的待办事项,同时调用set Completed来更新名称,无需任何额外的差异比对。因为我们已经将复杂性转移到数据而不是试图。并且我们确切知道数据是如何变化的。
创建Store
Store是Solid处理嵌套响应式给出回答。Store是代理对象,其属性可以被跟踪,并且可以包含其它对象,这些对象会自动包装在代理中。
createStore函数接收一个初始值并返回一个类似于Signal的元祖。第一个元素是只读的store代理,第二个元素是setter函数。
如:
const [store, setStore] = createStore({ todos: [] })
const addTodo = (text) => {
setStore("todos", todos => [...todos, { id: ++todoId, text, completed: false }]);
}
const toggleTodo = (id) => {
setStore("todos", todo => todo.id === id, "completed", completed => !completed);
}
修改
solid提供了一个producestore修饰符,它可以让你在setStore调用中改变Store对象的可代理版本。
const [store, setStore] = createStore({ todos: [] })
const addTodo = (text) => {
setStore(
'todos',
produce((todos) => {
todos.push({ id: ++todoId, text, completed: false });
}),
);
};
const toggleTodo = (id) => {
setStore(
'todos',
todo => todo.id === id,
produce((todo) => (todo.completed = !todo.completed)),
);
};