当前位置: 首页 > news >正文

【Svelte】动态加载组件并传递参数的正确姿势,及两种方式比较

下面通过比较两种动态加载组件的方式,解释经典的 Svelte 响应式编程方法,让你可以掌握现代前端框架的精髓。

In Svelte 5, the most Svelte-idiomatic and recommended way to dynamically append components is to use Svelte's reactivity system, typically with an array and an {#each} block, rather than direct DOM manipulation like document.querySelector and imperative appendChild for Svelte components.

Here are the two main ways to achieve this, with the first being the strongly preferred Svelte approach:


1. The Svelte-Idiomatic Way (Recommended)

This approach uses Svelte's reactive {#each} block to render components based on an array of data. When you want to add a new CompA, you simply add the data (j) to an array, and Svelte automatically renders a new CompA instance.

src/App.svelte (or your main component)

<script>import CompA from './compa.svelte';// This array will hold the data for each CompA instance// Svelte will reactively render a CompA for each item in this arraylet messages = [];async function addMessage() {// get data from urlconst r = await fetch("https://jsonplaceholder.typicode.com/todos/1", { // Using a public API for examplemethod: "GET", // Changed to GET for the example API// body: "xxx" // Not needed for GET});const j = await r.json();// Add the new data to the messages array// Svelte requires reassignment for reactivity, so we spread the existing array// and add the new item.messages = [...messages, j];console.log('Messages:', messages);}
</script><h1>Svelte 5 Dynamic Components</h1><div id="parent-div" style="border: 1px solid blue; padding: 10px; min-height: 50px;"><h2>Messages from CompA:</h2>{#each messages as msg (msg.id || JSON.stringify(msg))}<CompA data={msg} />{/each}
</div><button onclick={addMessage}>Add CompA with Message</button><style>div {margin-top: 20px;}button {padding: 10px 20px;background-color: #007bff;color: white;border: none;border-radius: 5px;cursor: pointer;}button:hover {background-color: #0056b3;}
</style>

src/compa.svelte

<script>// Declare the prop 'data' that CompA expects to receivelet { data } = $props();// You can also use reactive declarations if needed// let processedData = $state(data.title.toUpperCase());
</script><div style="border: 1px solid green; margin: 5px; padding: 5px;"><p><strong>ID:</strong> {data.id}</p><p><strong>Title:</strong> {data.title}</p><p><strong>Completed:</strong> {data.completed ? 'Yes' : 'No'}</p>
</div>

Explanation:

  1. let messages = [];: We declare a reactive array messages in the parent component.
  2. messages = [...messages, j];: When addMessage is called, we fetch the data j and then add it to the messages array. Crucially, we create a new array using the spread syntax (...) and reassign it. Svelte detects this reassignment and triggers a re-render.
  3. {#each messages as msg (msg.id || JSON.stringify(msg))}: The {#each} block iterates over the messages array. For each item (msg), it renders a <CompA> component.
    • (msg.id || JSON.stringify(msg)) is the key for the {#each} block. It's important for Svelte to efficiently update lists. If your j object has a unique id, use that. Otherwise, JSON.stringify(msg) can be a fallback, though a proper unique ID is always better.
  4. <CompA data={msg} />: For each item, we pass the msg object as a prop named data to CompA.
  5. let { data } = $props();: In CompA.svelte, we declare a prop named data using Svelte 5's $props() macro to receive the data.

2. Advanced / Imperative Way (Less Recommended for this use case)

If you have a very specific reason to imperatively mount a Svelte component into an arbitrary DOM node that is not directly part of the parent component's template (e.g., mounting into a third-party library's container or a document.body overlay), you can use the component constructor directly. However, for adding components to a div within your own component's template, the {#each} approach is much cleaner and safer.

This method requires manual lifecycle management (destroying the component).

src/App.svelte

<script>import CompA from './compa.svelte';import { onDestroy } from 'svelte'; // For cleanuplet componentInstances = []; // To keep track of created component instances for destructionasync function addMessage() {// get data from urlconst r = await fetch("https://jsonplaceholder.typicode.com/todos/2", {method: "GET",});const j = await r.json();// Get the parent elementconst footer = document.querySelector('#parent-div');if (!footer) {console.error('Parent div #parent-div not found!');return;}// Create a new instance of CompA and mount it to the footerconst compAInstance = new CompA({target: footer, // The DOM element to mount the component intoprops: {data: j // Pass j as a prop named 'data'}});// Store the instance so we can destroy it latercomponentInstances = [...componentInstances, compAInstance];console.log('Imperatively added CompA with data:', j);}// Lifecycle hook to destroy all dynamically created components when this parent component is destroyedonDestroy(() => {componentInstances.forEach(instance => {console.log('Destroying imperative instance:', instance);instance.$destroy();});});
</script><h1>Svelte 5 Dynamic Components (Imperative)</h1><div id="parent-div" style="border: 1px solid red; padding: 10px; min-height: 50px;"><h2>Imperatively Added CompA Instances:</h2>
</div><button onclick={addMessage}>Add CompA Imperatively</button><style>div {margin-top: 20px;}button {padding: 10px 20px;background-color: #dc3545;color: white;border: none;border-radius: 5px;cursor: pointer;}button:hover {background-color: #c82333;}
</style>

src/compa.svelte (Same as above)

<script>let { data } = $props();
</script><div style="border: 1px solid orange; margin: 5px; padding: 5px;"><p><strong>ID:</strong> {data.id}</p><p><strong>Title:</strong> {data.title}</p><p><strong>Completed:</strong> {data.completed ? 'Yes' : 'No'}</p>
</div>

Explanation:

  1. import { onDestroy } from 'svelte';: We need onDestroy to clean up the imperatively created components.
  2. let componentInstances = [];: We maintain an array of component instances so we can call $destroy() on them later.
  3. const footer = document.querySelector('#parent-div');: We get the target DOM element.
  4. const compAInstance = new CompA({ target: footer, props: { data: j } });: This is the core. You instantiate the Svelte component directly using its constructor.
    • target: The DOM element where the component will be mounted.
    • props: An object containing the initial props to pass to the component.
  5. onDestroy(() => { ... });: It's crucial to call $destroy() on each created component instance when the parent component unmounts to prevent memory leaks.

Which method to choose?

For almost all scenarios where you want to add components dynamically within your Svelte application, use the first method with {#each}. It's more declarative, leverages Svelte's reactivity system, automatically handles lifecycle management (creation, updates, destruction), and is generally easier to maintain.

The imperative new CompA(...) method should be reserved for niche cases where you need to integrate Svelte components into non-Svelte environments or have very specific DOM manipulation requirements that cannot be met declaratively.

http://www.dtcms.com/a/585302.html

相关文章:

  • 【ZeroRange WebRTC】Amazon Kinesis Video Streams C WebRTC SDK 详解与实践指南
  • openEuler边缘计算实践:构建高效边云协同架构
  • 自建国外购物网站公司网站开发外包公司
  • Linux内存管理揭秘:页表递归清理与TLB优化机制
  • 从“医疗大模型”向“医疗智能体”架构与路径分析(白皮书草案-下)
  • Webpack性能优化终极指南:4步实现闪电打包
  • 零基础学JAVA--Day26(枚举类)
  • Kafka概述
  • CTFHub Web进阶-PHP:Bypass_disable_function通关8之PHP FFI
  • 重庆本地网站有哪些world做网站怎么做连接
  • 【028】Dubbo3从0到1系列之序列化机制
  • phpcms模板资源网站快速优化排名
  • 0 基础学前端:100 天拿 offer 实战课(第 18 天)—— JS 事件进阶:冒泡、委托与自定义事件,搞定复杂交互
  • 【C++】STL小总结
  • go基础语法练习
  • 360任意看地图网站网站开发设计需要什么证书
  • 大数据Spark(七十二):Transformation转换算子repartition和coalesce使用案例
  • Android 16 Kotlin协程 第二部分
  • 网站建设公司兴田德润电话新县城乡规划建设局网站
  • Claude Code使用指南
  • 如何进行MSSQL提权?默认库,xp_cmdshell提权
  • 第三章 布局
  • 「数据获取」《中国口岸年鉴》(2001-2024)(2002未出版)
  • Visual Studio笔记
  • 【开题答辩全过程】以 二手手机交易平台的设计与实现为例,包含答辩的问题和答案
  • “AI+XR”赋能智慧研创中心,预见职业教育“新双高”的未来
  • 保障房建设网站首页河北信息门户网站定制
  • MySQL的IFNULL函数介绍
  • 【数据结构】从零开始认识图论 --- 单源/多源最短路算法
  • 基于PyTorch的动物识别模型训练与应用实战