当在组件 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}
需要指出的是,这些组件彼此独立,即不是彼此的子组件或父组件。提前感谢您的回答:)
实现此目的的一种方法是在 Header
和 Main
.[=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.
页眉组件
<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}
需要指出的是,这些组件彼此独立,即不是彼此的子组件或父组件。提前感谢您的回答:)
实现此目的的一种方法是在 Header
和 Main
.[=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.