Home >Web Front-end >CSS Tutorial >Getting Started With SvelteKit

Getting Started With SvelteKit

Lisa Kudrow
Lisa KudrowOriginal
2025-03-09 10:42:14442browse

Getting Started With SvelteKit

SvelteKit is a representative of the new generation of application frameworks. It will of course build applications for you, including file-based routing, deployment, and server-side rendering that Next has always provided. But SvelteKit also supports nested layouts, server-side mutations of synchronized page data, and some other features we'll introduce soon.

This article aims to give a high-level overview of SvelteKit, hoping to inspire the interest of anyone who has never used SvelteKit. It will be an easy journey. If you like what you see, the full documentation is here.

In some ways, writing this article is challenging. SvelteKit is an application framework. It exists to help you build...apps. This makes the demonstration difficult. Building an entire application in a blog post is not feasible. So we will use our imagination a little bit. We will build the skeleton of the application, using some empty UI placeholders and hard-coded static data. The goal is not to build an actual application, but to show you the running mechanism of SvelteKit so that you can build your own application. To do this, we will build a tried and tested to-do application as an example. But don't worry, this will focus more on how SvelteKit works than creating another to-do app.

All the code in this article can be found on GitHub. This project has also been deployed on Vercel for real-time demonstrations.

Create a project

It's very easy to start a new SvelteKit project. Run

npm create svelte@latest your-app-name in the terminal and answer the question tips. Be sure to select "Skeleton Project", but for TypeScript, ESLint, etc., you can make any choice if you want.<https:> <p>After the project is created, run <code>npm i<https:> and <code>npm run dev<https:>, and the development server should start running. Launch <code>localhost:5173<https:> in your browser and you will get the placeholder page for the skeleton application. <https:> <h3>Basic Routing<https:> <p>Please note the <code>routes<https:> folder under <code>src<https:>. It contains the code for all our routes. There is already a <code> page.svelte<https:> file that contains the contents of the root <code>https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712<https:> route. No matter where you are in the file hierarchy, the actual page of that path is always named <code> page.svelte<https:>. With this in mind, let's <code>https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712list<https:>, <code>https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712details<https:> , <code>https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712adminhttps://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712user-settings<https:> and <code>https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712adminhttps://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712paid-status<https:> Create a page and add some text placeholders for each page. <https:> <p>Your file layout should look like this: <https:> <p>You should be able to navigate by changing the URL path in the browser's address bar. <https:> <h3>Layout<https:> <p>We want to add navigation links to our app, but we certainly don't want their tags to be copied to each page we create. So let's create a <code>layout.svelte<https:> file in the root of the <code>routes<https:> folder, which SvelteKit will treat as a global template for all pages.Let's add some content to it: <https:> <pre class="brush:php;toolbar:false">&lt;nav&gt; &lt;ul&gt; &lt;li&gt; &lt;a href=&quot;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712&quot;&gt;Home&lt;https:&gt; &lt;https:&gt; &lt;li&gt; &lt;a href=&quot;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712list&quot;&gt;To-Do list&lt;https:&gt; &lt;https:&gt; &lt;li&gt; &lt;a href=&quot;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712adminhttps://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712paid-status&quot;&gt;Account status&lt;https:&gt; &lt;https:&gt; &lt;li&gt; &lt;a href=&quot;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712adminhttps://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712user-settings&quot;&gt;User settings&lt;https:&gt; &lt;https:&gt; &lt;https:&gt; &lt;https:&gt; &lt;slot&gt;&lt;https:&gt; &lt;style&gt; nav { background-color: beige; } nav ul { display: flex; } li { list-style: none; margin: 15px; } a { text-decoration: none; color: black; } &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712style&gt;&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712pre&gt; &lt;p&gt;Some basic navigation and some basic styles. What is particularly important is the &lt;code&gt;&lt;slot&gt;&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712slot&gt;&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; tag. This &lt;em&gt; is not the slot you use with web components and Shadow DOM, but a feature of Svelte that indicates where our content is placed. When the page is rendered, the page content will slide into the location where the slot is located. &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712em&gt; &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt;Now we have some navigation! We won't win any design competitions, but we didn't try to do that either. &lt;p&gt; &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt;Nested layout&lt;h3&gt; &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712h3&gt;What if we want all management pages to inherit the normal layout we just built and also share some common points of all management pages (but only management pages)? No problem, we add another &lt;p&gt; layout.svelte&lt;code&gt; to the root &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; admin&lt;code&gt; directory and it will be inherited by everything below it.Let's do this and add this: &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;pre class=&quot;brush:php;toolbar:false&quot;&gt;&lt;div&gt;This is an admin page&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712div&gt; &lt;slot&gt;&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712slot&gt; &lt;style&gt; div { padding: 15px; margin: 10px 0; background-color: red; color: white; } &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712style&gt;&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712pre&gt; &lt;p&gt;We add a red banner indicating that this is an admin page, and then, as before, a &lt;code&gt;&lt;slot&gt;&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712slot&gt; indicates where we want the content of the page to go. &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt;Our previous root layout will render. There is a &lt;p&gt;&lt;code&gt;&lt;slot&gt;&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712slot&gt; tag in the root layout. The content of the nested layout enters the root layout &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt;&lt;code&gt;&lt;slot&gt;&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712slot&gt;. Finally, the nested layout defines its own &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt;&lt;code&gt;&lt;slot&gt; where the page content will be rendered. &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712slot&gt; &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt;If you navigate to the admin page, you should see a new red banner: &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;p&gt;Define data&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;h3&gt;Okay, let's render some actual data - or at least see how we render some actual data. There are many ways to create and connect to a database. This post is about SvelteKit, not managing DynamoDB, so we will instead &quot;load&quot; some static data. However, we will use the same mechanism you use for real data to read and update it. For real web applications, replace the function that returns static data with the function that connects and querys any database you use. &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712h3&gt; &lt;p&gt;Let's create a very simple module in &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt;libhttps://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712datahttps://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712todoData.ts&lt;p&gt; which returns some static data along with manual delays to simulate the actual query. You will see this &lt;code&gt;lib&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; folder imported elsewhere via &lt;code&gt;$lib&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt;. This is what SvelteKit provides for that specific folder, and you can even add your own alias.&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;pre class=&quot;brush:php;toolbar:false&quot;&gt;let todos = [ { id: 1, title: &quot;Write SvelteKit intro blog post&quot;, assigned: &quot;Adam&quot;, tags: [1] }, { id: 2, title: &quot;Write SvelteKit advanced data loading blog post&quot;, assigned: &quot;Adam&quot;, tags: [1] }, { id: 3, title: &quot;Prepare RenderATL talk&quot;, assigned: &quot;Adam&quot;, tags: [2] }, { id: 4, title: &quot;Fix all SvelteKit bugs&quot;, assigned: &quot;Rich&quot;, tags: [3] }, { id: 5, title: &quot;Edit Adam's blog posts&quot;, assigned: &quot;Geoff&quot;, tags: [4] }, ]; let tags = [ { id: 1, name: &quot;SvelteKit Content&quot;, color: &quot;ded&quot; }, { id: 2, name: &quot;Conferences&quot;, color: &quot;purple&quot; }, { id: 3, name: &quot;SvelteKit Development&quot;, color: &quot;pink&quot; }, { id: 4, name: &quot;CSS-Tricks Admin&quot;, color: &quot;blue&quot; }, ]; export const wait = async (amount) =&gt; new Promise((res) =&gt; setTimeout(res, amount ?? 100)); export async function getTodos() { await wait(); return todos; } export async function getTags() { await wait(); return tags.reduce((lookup, tag) =&gt; { lookup[tag.id] = tag; return lookup; }, {}); } export async function getTodo(id) { return todos.find((t) =&gt; t.id == id); }&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712pre&gt; &lt;p&gt;一个函数返回我们待办事项的扁平数组、我们的标签的查找以及获取单个待办事项的函数(我们将在“详细信息”页面中使用最后一个函数)。&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;h3&gt;加载数据&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712h3&gt; &lt;p&gt;我们如何将这些数据放入我们的 Svelte 页面?方法有很多,但现在,让我们在 &lt;code&gt;list&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; 文件夹中创建一个 &lt;code&gt; page.server.js&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; 文件,并将此内容放在其中:&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;pre class=&quot;brush:php;toolbar:false&quot;&gt;import { getTodos, getTags } from &quot;$libhttps://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712datahttps://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712todoData&quot;; export function load() { const todos = getTodos(); const tags = getTags(); return { todos, tags, }; }&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712pre&gt; &lt;p&gt;我们定义了一个 &lt;code&gt;load()&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; 函数,它会提取页面所需的数据。请注意,我们&lt;em&gt;没有&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712em&gt;等待对我们的 &lt;code&gt;getTodos&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; 和 &lt;code&gt;getTags&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; 异步函数的调用。这样做会创建一个数据加载瀑布,因为我们在加载标签之前等待待办事项进入。相反,我们从 &lt;code&gt;load&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; 返回原始 promise,SvelteKit 会执行必要的等待工作。&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;p&gt; So, how do we access this data from the page component? SvelteKit provides our component with a &lt;code&gt;data&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; attribute with data. We will access our to-dos and tags from it using reactive assignments. &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;p&gt;Our list page component now looks like this. &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;pre class=&quot;brush:php;toolbar:false&quot;&gt;&lt;script&gt; export let data; $: ({ todos, tags } = data); &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712script&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;Task&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712th&gt; &lt;th&gt;Tags&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712th&gt; &lt;th&gt;Assigned&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712th&gt; &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712tr&gt; &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712thead&gt; &lt;tbody&gt; {#each todos as t} &lt;tr&gt; &lt;td&gt;{t.title}&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712td&gt; &lt;td&gt;{t.tags.map((id) =&gt; tags[id].name).join(', ')}&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712td&gt; &lt;td&gt;{t.assigned}&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712td&gt; &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712tr&gt; {https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712each} &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712tbody&gt; &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712table&gt; &lt;style&gt; th { text-align: left; } &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712style&gt;&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712pre&gt; &lt;p&gt;This should render our to-do list! &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;h3&gt;Layout Group&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712h3&gt; &lt;p&gt; Before we move on to the Details page and mutated data, let's take a quick look at a very clever feature of SvelteKit: &lt;strong&gt;Layout Group&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712strong&gt;. We've seen nested layouts for all management pages, but what if we want to share layouts between arbitrary pages on the same level in the file system? In particular, what if we just want to share the layout between our list page and the details page? We already have a global layout at that level. Instead, we can create a new directory, but the name should be placed in brackets, as follows: &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;p&gt;We now have a layout group covering the list and details pages. I named it &lt;code&gt;(todo-management)&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt;, but you can name it whatever you like.It should be clear that this name &lt;em&gt; will not affect the URL of the page in the layout group. The URL will remain the same; the layout group allows you to add shared layouts to the page without them all forming part of the entire directory in &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712em&gt;routes&lt;code&gt;. &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt;We&lt;p&gt; can&lt;em&gt; add a &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712em&gt; layout.svelte&lt;code&gt; file and some silly &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt;&lt;code&gt; banner that says &quot;Hey, we're managing to do things.&quot;But let's do something more interesting. The layout can define the &lt;code&gt;load()&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; function to provide data for all routes under it. Let's use this feature to load our tags – because we will use our tags in the details page – and the list page we already have. In fact, it is almost certainly not worth it to force the layout group just to provide a single data; it is best to copy that data in the &lt;code&gt;load()&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; function on each page. But for this post, it will provide an excuse we need to see new features of SvelteKit! &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;p&gt;First, let's go to the &lt;code&gt; page.server.js&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; file of the list page and delete the tags from it. &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;pre class=&quot;brush:php;toolbar:false&quot;&gt;import { getTodos } from &quot;$libhttps://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712datahttps://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712todoData&quot;; export function load() { const todos = getTodos(); return { todos, }; }&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712pre&gt; &lt;p&gt;Our list page should now produce an error because there is no &lt;code&gt;tags&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; object. Let's solve this problem by adding a &lt;code&gt; layout.server.js&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; file to the layout group, and then define a &lt;code&gt;load()&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; function that loads the tags. &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;pre class=&quot;brush:php;toolbar:false&quot;&gt;import { getTags } from &quot;$libhttps://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712datahttps://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712todoData&quot;; export function load() { const tags = getTags(); return { tags, }; }&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712pre&gt; &lt;p&gt;In this way, our list page was rendered again! &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;h4&gt;We are loading data from multiple locations&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712h4&gt; &lt;p&gt;Let's focus on what's going on here: &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;ul&gt; &lt;li&gt;We define a &lt;code&gt;load()&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; function for the layout group, and we place it in &lt;code&gt; layout.server.js&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; . &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712li&gt; &lt;li&gt;This provides data for all &lt;strong&gt; pages serving the layout - in this case, this means our list and details pages.&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712li&gt; &lt;li&gt;Our list page also defines a &lt;code&gt;load()&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; function located in its &lt;code&gt; page.server.js&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; file. &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712li&gt; &lt;li&gt;SvelteKit performs heavy lifting, merging the results of these data sources together and providing both in &lt;code&gt;data&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt;. &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712li&gt; &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712ul&gt; &lt;h3&gt;Details Page&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712h3&gt; &lt;p&gt;We will use the details page to edit the to-do list. First, let's add a column to the list page that links to the details page of the query string containing the to-do ID. &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;pre class=&quot;brush:php;toolbar:false&quot;&gt;&lt;td&gt;&lt;a href=&quot;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712details?id={t.id}&quot;&gt;Edit&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712a&gt;&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712td&gt;&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712pre&gt; &lt;p&gt;Let's build the details page now. First, we will add a loader to get the to-do item we are editing. Create a &lt;code&gt; page.server.js&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; in &lt;code&gt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712details&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; with the following content: &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;pre class=&quot;brush:php;toolbar:false&quot;&gt;import { getTodo } from &quot;$libhttps://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712datahttps://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712todoData&quot;; export function load({ url }) { const id = url.searchParams.get(&quot;id&quot;); const todo = getTodo(id); return { todo, }; }&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712pre&gt; &lt;p&gt;Our loader comes with the &lt;code&gt;url&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; attribute from which we can extract query string values. This makes it easy to find the to-do list we are editing. Let's render the to-do, and edit it's function. &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;p&gt;SvelteKit has excellent built-in mutability as long as you use the form. Remember the form? Here is our details page. For simplicity, I've omitted styles.&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;pre class=&quot;brush:php;toolbar:false&quot;&gt;&lt;script&gt; import { enhance } from &quot;$apphttps://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712forms&quot;; export let data; $: ({ todo, tags } = data); $: currentTags = todo.tags.map((id) =&gt; tags[id]); &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712script&gt; &lt;div&gt; {#each currentTags as tag} {tag.name} {https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712each} &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712div&gt; &lt;form method=&quot;POST&quot; action=&quot;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712editTodo&quot; use:enhance&gt; &lt;input type=&quot;hidden&quot; name=&quot;id&quot; value={todo.id} https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712&gt; &lt;input type=&quot;text&quot; name=&quot;title&quot; bind:value={todo.title} https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712&gt; &lt;button type=&quot;submit&quot;&gt;Save&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712button&gt; &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712form&gt;&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712pre&gt; &lt;p&gt;We get the label from the loader of the layout group as before and the to-do items from the loader of the page. We get the actual tag object from the to-do list of tag IDs and then render everything. We create a form with a hidden ID input and a real title input. We display the label and then provide a button to submit the form. &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;p&gt;If you notice &lt;code&gt;use:enhance&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt;, this is just telling SvelteKit to use progressive enhancement and Ajax to submit our form. You may always use it. &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;h4&gt;How do we save our edits? &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712h4&gt; &lt;p&gt;Note the &lt;code&gt;action=&quot;?https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712editTodo&quot;&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; attribute on the form itself? This tells us where we want to submit the edited data. For our case, we want to submit to a &lt;code&gt;editTodo&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt;&quot;action&quot;.&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;p&gt;Let's create it by adding the following to the &lt;code&gt; page.server.js&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; file we already provide for &quot;Details&quot; (the file currently has a &lt;code&gt;load()&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; function to get our to-do items): &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;pre class=&quot;brush:php;toolbar:false&quot;&gt;import { redirect } from &quot;@sveltejshttps://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712kit&quot;; import { updateTodo, wait } from &quot;$libhttps://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712datahttps://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712todoData&quot;; https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712 ... export const actions = { async editTodo({ request }) { const formData = await request.formData(); const id = formData.get(&quot;id&quot;); const newTitle = formData.get(&quot;title&quot;); await wait(250); await updateTodo(id, newTitle); throw redirect(303, &quot;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712list&quot;); }, };&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712pre&gt; The &lt;p&gt;Form action provides us with a &lt;code&gt;request&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; object that provides access to our &lt;code&gt;formData&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; which has a &lt;code&gt;get&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; method for our various form fields. We added a hidden ID value input so that we can get it here to find the to-do we are editing. We simulate the delay, call the new &lt;code&gt;updateTodo()&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; method, and redirect the user back to the &lt;code&gt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712list&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; page. The &lt;code&gt;updateTodo()&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; method simply updates our static data; in real life, you will run some kind of update in any data store you use. &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;pre class=&quot;brush:php;toolbar:false&quot;&gt;export async function updateTodo(id, newTitle) { const todo = todos.find((t) =&gt; t.id == id); Object.assign(todo, { title: newTitle }); }&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712pre&gt; &lt;p&gt;Let's try it. We first go to the list page: &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;p&gt;Now, let's click the Edit button for one of the to-do items to bring up the edit page in &lt;code&gt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712details&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt;.&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;p&gt;We will add a new title: &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;p&gt;Now, click Save.This should bring us back to the &lt;code&gt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712list&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; page and apply the new to-do title. &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;p&gt;How did the new title appear? This is automatic. Once we redirect to the &lt;code&gt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712list&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; page, SvelteKit will automatically rerun all our loaders as usual. This is a key advancement that new generation application frameworks like SvelteKit, Remix, and Next 13 offer. Instead of giving you a convenient way to render pages, then good luck getting any endpoints you may need to update your data, they integrate data mutation with data loading, allowing the two to work together. &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;p&gt;Some things you might want to know...&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;p&gt;&lt;strong&gt;This mutation update doesn't seem too impressive. &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712strong&gt;The loader will run again while you navigate. What happens if we do not add a redirect in the form action, but instead stay on the current page? SvelteKit will perform updates in form operations as before, but will still rerun all loaders for the current page, including those in the page layout. &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;p&gt;&lt;strong&gt;Can we have a more targeted way to invalidate our data? &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712strong&gt;For example, our tags are not edited, so in real life we ​​don't want to re-query them. Yes, all I'm showing you is the default form behavior in SvelteKit. You can turn off the default behavior by providing a callback to &lt;code&gt;use:enhance&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt;. SvelteKit then provides a manual failure function. &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;p&gt;&lt;strong&gt;Loading data every time you navigate can be expensive and unnecessary. &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712strong&gt;Can I cache this data like a tool like react-query? Yes, it's just different. SvelteKit allows you to set (and then respect) cache control headers that the Web has provided. I will introduce the cache failure mechanism in a subsequent article. &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;p&gt;We use static data throughout the article and modify values ​​in memory. If you need to restore everything and start over, stop and restart the &lt;code&gt;npm run dev&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712code&gt; Node process. &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;h3&gt;Summary&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712h3&gt; &lt;p&gt;We just touched the surface of SvelteKit, but hopefully you’ve seen something that’s enough to get you excited.I don't remember the last time I found web development so interesting. With out-of-the-box features like bundling, routing, SSR, and deployment, I can spend more time coding than configuring. &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;p&gt;The following are some more resources you can use as the next steps to learn SvelteKit: &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712p&gt; &lt;ul&gt; &lt;li&gt;Announced SvelteKit 1.0 (Svelte Blog)&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712li&gt; &lt;li&gt;SvelteKit Beginner Course (Vercel)&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712li&gt; &lt;li&gt;SvelteKit Documentation&lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712li&gt; &lt;https://www.php.cn/link/29a9f8c8460e5e2be4edde557fd83712ul&gt;&lt;/style&gt;&lt;/https:&gt;&lt;/slot&gt;&lt;/https:&gt;&lt;/https:&gt;&lt;/https:&gt;&lt;/https:&gt;&lt;/a&gt; &lt;/li&gt;&lt;/https:&gt;&lt;/https:&gt;&lt;/a&gt; &lt;/li&gt;&lt;/https:&gt;&lt;/https:&gt;&lt;/a&gt; &lt;/li&gt;&lt;/https:&gt;&lt;/https:&gt;&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;&lt;/nav&gt;</pre></https:></https:>

The above is the detailed content of Getting Started With SvelteKit. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn