首页 > 解决方案 > 当在彼此没有关系的组件 A 上单击按钮时,如何在组件 B 上呈现某些内容?

问题描述

标头组件

<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}

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

标签: svelte

解决方案


实现此目的的一种方法是在andisColumnClicked的公共父级中处理一个变量(它是一个布尔值)。HeaderMain

因此,您将作为道具提供给单击列表项时将触发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组件应该从isColumnClickedprop 中获取值:

Main.svelte:

<script>
    export let columnClicked;
</script>

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

并且共同的父母(可以说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>

请参阅此代码框中的工作示例。


编辑:

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

理想情况下,标题上的“添加列”按钮会在板(主区域)组件上创建一个列组件

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

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

[
  {
    title: "column title",
    todos: [...a list of todos 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>

像这样,你有一个干净的前端应用程序,它只依赖于数据而不是大量的事件。这是代码框的链接


推荐阅读