当在组件 A 上单击彼此无关的按钮时,如何在组件 B 上渲染某些内容?

How to render something on Component B when a button is clicked on Component A which has no relation to each other?

页眉组件

<header>
    <li>hello board</li>
    <ul>
        <li>add a column</li>
        <li>manage tags</li>
        <li>settings</li>
    </ul>
</header>

主要成分

{#if "add a column" is clicked}
...
{/if}

需要指出的是,这些组件彼此独立,即不是彼此的子组件或父组件。提前感谢您的回答:)

实现此目的的一种方法是在 HeaderMain.[=36 的公共 parent 中处理一个 isColumnClicked 变量(这是一个布尔值) =]

因此,您将作为 prop 给 Header 一个回调 onAddColumn,当您单击列表项时将触发该回调:

Header.svelte:

<script>
    export let onAddColumn;
</script>

<header>
    <li>hello board</li>
    <ul>
        <li on:click={onAddColumn}>add a column</li>
        <li>manage tags</li>
        <li>settings</li>
    </ul>
</header>

然后 Main 组件应该从 isColumnClicked 中获取值作为 prop:

Main.svelte:

<script>
    export let columnClicked;
</script>

{#if columnClicked}
  <p>Yuhu!</p>
{/if}

而常见的 parent(比方说 App)将协调 isColumnClicked 更新:

App.svelte:

<script>
  import Header from "./Header.svelte";
  import Main from "./Main.svelte";

  let isColumnClicked = false;
</script>

<body>
  <Header 
    onAddColumn={() => {
      isColumnClicked = true
    }} 
  />
  <Main columnClicked={isColumnClicked}/>
</body>

请参阅此 codesandbox 中的工作示例。


编辑:

阅读您的评论后,更加清楚您的意图:

Ideally, the "add a column" button on the header creates a column component on the board (main area) component

对于这种类型的行为,您将不得不采用另一种逻辑,该逻辑更适合使用提到的 store like @grohjy 的组件架构。

因此,您的所有组件都将由包含您的数据的公共 object 编排(所以这里是一个包含所有列的列表)。让我们举例说明它将具有以下结构:

[
  {
    title: "column title",
    todos: [...a list of todos object]
  },
  ...
]

下一步是初始化处理此问题的商店 object。例如,您可以向该商店添加一个 addColumn 函数:

board.js:

import { writable } from "svelte/store";

const emptyColumn = {
  title: "New Column",
  todos: []
};

function createBoardStore() {
  const { subscribe, set, update } = writable([]);

  return {
    subscribe,
    addColumn: () => {
      update((board) => [...board, emptyColumn]);
    },
    reset: () => {
      set([]);
    }
  };
}

export const board = createBoardStore();

然后你的 Main 组件只映射所有现有的 column 使用商店:

Main.svelte:

<script>
  import { board } from "./stores/board.js";

  let boardValue;

  const unsubscribe = board.subscribe(value => {
    boardValue = value;
  });
</script>

{#each boardValue as column}
  <li>{column.title}</li>
{/each}

所以你的 Header 只需要调用 addColumn 函数,因为 Main 组件对商店有反应:

Header.svelte:

<script>
    import { board } from "./stores/board.js";
</script>

<header>
    <li>hello board</li>
    <ul>
        <li on:click={board.addColumn}>add a column</li>
        <li>manage tags</li>
        <li>settings</li>
    </ul>
</header>

像这样你有一个干净的 front-end 应用程序,它只依赖于数据而不是大量的事件。这是 link 到 codesandbox.