SolidJS: For vs Index

В своем руководстве по рендерингу списков они говорят:

Для этих случаев предусмотрен компонент. Как правило, при работе с примитивами используйте .

и

<For> заботится о каждой части данных в вашем массиве, и положение этих данных может измениться; <Index> заботится о каждом индексе в вашем массиве, и содержимое каждого индекса может измениться.

Ни одна из этих фраз не имеет для меня смысла. Что значит "при работе с примитивами"? Я всегда использую массив. Может ли кто-нибудь уточнить, когда использовать For против Index?

2 ответа

Что значит "при работе с примитивами"? Я всегда использую массив.

Речь идет об элементах массива — будь то примитивы, как в массиве строк, или объекты.

Короче говоря, если у вас есть массив объектов, используйте . Если у вас есть массив строк и , а массив короткий или вы никогда не вставляете и не удаляете элементы в середине массива, используйте . В противном случае используйте . Если вы не уверены, всегда используйте .

Разница заключается в том, как обновляется DOM при изменении элементов массива.

всегда проверяет, был ли элемент в массиве до изменения, и перемещает узлы DOM, чтобы отразить изменение позиции элемента, не вызывая обратный вызов для рендеринга элемента (он также вызывает сигнал, если он использовался в обратном вызове для отображения элемента положение, поэтому то, что зависит от index()будет обновляться на месте). вызывает обратный вызов для отображения измененного элемента, если элемент ранее не был в массиве.

Итак, когда вы вставляете элемент в середину массива, обратный вызов вызывается только один раз — для рендеринга вставленного элемента, а его результат вставляется в DOM на место в массиве, как и ожидалось.

этого не делает - это намного проще, он просто сравнивает старые и новые элементы по каждому индексу, и если они различаются, он вызывает сигнал, который был передан в качестве параметра для обратного вызова. Сам обратный вызов не будет вызываться, только то, что внутри обратного вызова зависит от item()сигнал будет обновлен на месте. вызывает обратный вызов только тогда, когда новые элементы добавляются в конец массива.

Это также объясняется в FAQ: для eachобратный вызов получил значение элемента и сигнал о позиции элемента. Для , все наоборот - обратный вызов получает сигнал для значения элемента и число для позиции элемента.

Вы можете попробовать этот пример на игровой площадке Solid — вы можете открыть консоль, чтобы увидеть, сколько раз вызывается обратный вызов <For>а также <Index>:

      import { render } from 'solid-js/web';
import { createSignal, For, Index } from 'solid-js';

function ForCats() {
  const [cats, setCats] = createSignal([
    'Keyboard Cat',
    'Maru',
    'Henri The Existential Cat'
  ]);
  
     setTimeout(() => setCats(['Maru', 'Keyboard Cat', 'Keyboard Cat', 'New Cat']), 2000)

  return (
    <ul>
    <For each={cats()}>{name => {

        console.log(`For: rendered ${name} whole cat`);

      return <li>
        <a target="_blank" href="">
          1: {name}
        </a>
      </li>
    }}</For>
    </ul>
  );
}


function IndexCats() {
  const [cats, setCats] = createSignal([
    'Keyboard Cat',
    'Maru',
    'Henri The Existential Cat'
  ]);
  
     setTimeout(() => setCats(['Maru', 'Keyboard Cat', 'Keyboard Cat', 'New Cat']), 2000)

  return (
    <ul>
    <Index each={cats()}>{name => {

        console.log(`Index: rendered ${name()} whole cat`);

      return <li>
        <a target="_blank" href="">
          1: {name()}
        </a>
      </li>
    }}</Index>
    </ul>
  );
}

render(() => <><ForCats /> <IndexCats/ ></>, document.getElementById('app'))

Forиспользует функцию внутри и повторно отображает элемент при обновлении элемента. Indexиспользует и повторно отображает измененные биты, сохраняя при этом уже визуализированный элемент.

Скажем, вы визуализируете список элементов. перерисовывает все liв то время как повторно отображает innerHTML, представляющий значение элемента.

Примитивы или объекты не влияют на то, как элементы отображаются. Если элемент является объектом, mapArrayпо-прежнему перерисовывает весь элемент, indexArrayповторно отображает только обновленное свойство.

      import { createSignal, indexArray, mapArray } from 'solid-js';
import { render } from 'solid-js/web';

const [items, setItems] = createSignal([1, 2, 3, 4]);
let x = 0;
setInterval(() => setItems([1, 2, 3, x++]), 500);

const App = () => {
  return (
    <div>
      <ul>
        {mapArray(items, (item, index) => {
          // If an item updates, <li>...</li> will be re-rendered
          return (
            <li>#{index()}. {item} </li>
          );
        })}
      </ul>
      <ul>
        {indexArray(items, (item, index) => {
          // If item updates, only the value for `{item()}` will be re-rendered
          return (
            <li>#{index}. {item()} </li>
          );
        })}
      </ul>
    </div>
  );
}

render(App, document.querySelector('#app'));
Другие вопросы по тегам