SolidJs之Store

283 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 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)),
    );
  };