开始编写 Svelte 单文件组件所需的一切知识
由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!
本文是我关于 Svelte 的三篇系列文章的第二部分。在我看来,无需框架即可构建 JavaScript(UI)框架的理念,是前端开发未来发展最有前景的方向。我很期待继续撰写关于 Svelte 的文章。第一部分讨论了如何使用Svelte 和 Sapper 创建静态网站。第三部分展示了如何将 Tailwind CSS 与 Svelte 和 Sapper 结合使用。
版本:
Svelte:3.16.7
介绍
Svelte 是一个现代化的框架,用于创建具有赛博朋克风格的 Web 应用。它无需在客户端加载整个库,所有工作都在编译阶段完成。关于 Svelte 还有很多内容可以介绍,但今天我们只讨论如何使用 Svelte 创建应用。
本文重点介绍如何编写 Svelte 单文件组件。文章将阐述如何:
.svelte 单文件组件 (SFC)
Svelte 的 SFC 看起来与 Vue 非常相似,或者换句话说:就像 HTML、JavaScript 和 CSS 一样。不过,它与 Vue 的 SFC 略有不同:
一个 .svelte SFC 以<script>代码块开头。它包含了 SFC 的逻辑。它可以导入子组件,并导出数据属性和特性。
后面跟着一个<style>代码块,其中包含该组件的 CSS 代码。与其他基于组件的框架相比,该框架会自动scoped为该组件应用样式,无需为其添加关键字。
默认情况下,样式作用域仅限于组件。要设置全局样式,请添加关键字:
<style global></style>。
令人惊讶的是,这部分 HTML 代码并没有被包裹在<template>代码块中。也不需要将所有 HTML 标签都包裹在一个外层标签内。重要的是:这里没有<template>代码块。可以直接将 HTML 代码添加到文件中。
一个 .svelte SFC 的示例如下所示:
<!-- component.svelte -->
<script>
// nothing to do here. This block can be removed.
</script>
<style>
h1 {
font-size: 42px;
}
p {
font-size: 14px;
}
</style>
<h1>Hello World!</h1>
<p>I am a Demo.</p>
由于没有将 HTML 包裹在标签中,因此它与其他基于组件的框架有几点不同:
- 网格样式可以通过增加自由度而变得更简单。
- 除了传递属性之外,无法像
class=""给子组件那样添加其他属性。
数据属性
Svelte 的模板语言与 Angular/Vue 类似。与这些框架一样,它也与Handlebars有相似之处。要在模板中使用变量,请将其用花括号括起来:{VARIABLE}。
<script>
const title = "World";
</script>
<style>
h1 {
font-size: 42px;
}
p {
font-size: 14px;
}
</style>
<h1>Hello {title}!</h1>
<p>I am a Demo.</p>
虽然我认为在标记中使用变量添加 HTML 是个坏主意,但可以通过编写以下代码来实现
<h1>Hello {@html title}</h1>。
变量还可以用于将动态值绑定到 HTML 属性。例如,带有 href 变量的锚链接如下所示:
<a href={href} target="_blank" rel="noopener">
Open Link
</a>
在使用 HTML 属性变量时,一个常见的错误是给变量加上引号。应该是 `\`
href={href}而不是 `\href="{href}"`。
一个很棒的功能是使用简写属性。当变量名与属性名相同时,只需在花括号中添加属性名即可:
<a {href} target="_blank" rel="noopener">
Open Link
</a>
简写属性可以减少冗余代码。例如,可以使用
{href}`for`href={href}。
甚至可以展开一个对象来添加多个属性:
<script>
const link = {
href: "some src",
target: "_blank",
rel: "noopener"
}
</script>
<a {...link}>
<!-- will be compiled to: <a href="some src" target="_blank" rel="noopener">-->
Open Link
</a>
条件渲染
与其他框架相比, Vue 的条件渲染if并非else通过指令实现。在 Vue 中,条件渲染需要这样写: `<div class="vue.js <p v-if="true">" />`。而在 Svelte 中,条件渲染if可以通过添加纯代码块并用花括号括起来来实现。
{#if Math.random() > 0.5}
<p>I like Svelte.</p>
{:else}
<p>I don't like Svelte.</p>
{/if}
对于条件渲染,
if-else代码块可以用花括号括起来。Else代码块是可选的。`#<body>` 表示代码块的开始,`:<body>` 表示代码块的延续,` <body>` 表示/代码块的结束。
事件处理程序
在 UI 框架出现之前,开发者使用原生 JavaScript 为网站添加逻辑和行为。onclick事件处理程序允许在用户点击 HTML 元素时立即添加回调函数。在 Svelte 中,事件处理程序通过元素指令on:添加到 DOM 元素。可以传递一个函数作为引用,也可以编写一个内联函数。
用于
on:在 DOM 元素上添加事件处理程序。
以下是一些示例,帮助您了解事件处理程序:
<script>
let counter = 1;
function logout() {
// ... log user out
}
function toggleTooltip() {
// ... show or hide tooltip
}
</script>
<button on:click={logout}>
Logout
</button>
<div on:mouseover={toggleTooltip}>
Info
</div>
<button on:click="{() => a += 1}">
<!-- you can pass the event as property: -->
<!-- <button on:click|preventDefault="{(e) => /* do something with the event e */}"> -->
a is {a}.
</button>
接下来我们来谈谈如何组合组件。
组成部件
子组件可以直接导入到<script>代码块中,无需再进行注册。
<script>
import GridItem from '../components/GridItem.svelte';
</script>
该组件可以像其他 HTML 标签一样添加到模板中。
<GridItem></GridItem>
<!-- or <GridItem /> -->
子组件采用驼峰命名法编写,并在
<script>代码块中导入。
组件名称区分大小写。建议使用 PascalCase 命名。这样做的好处是,可以将Header、Footer等已被占用的标签名称用作 Svelte 组件的名称。这与其他框架不同,在其他框架中,像TheHeader或TheFooter这样的名称是一种变通方案,但也明确指出这些组件在页面模板中只能使用一次。
传递属性
可以使用花括号将属性传递{}给子组件。子组件可以通过导出属性来访问它们。声明数据属性的语法是 `<data-attributes>` [let/const] variable = 'abc';,而访问已传递属性的语法是 `<data-attributes> export let variable;`。
<!-- Parent.svelte -->
<script>
import Child from '../components/Child.svelte';
</script>
<Child title="World!"></Child>
<!-- Child.svelte -->
<script>
export let title;
</script>
<h1>Hello {title}</h1>
可以添加一个可选的默认值:
<!-- Child.svelte -->
<script>
export let title = "my dear friend.";
</script>
<h1>Hello {title}</h1>
使用
<Child></Child>或<Child />用于嵌套组件,而无需使用插槽。
使用插槽
现在,是时候创建一个简单的 Grid 了,它带有 GridItems 插槽,可以使用 `<grid>` 标签添加<slot></slot>。请注意,此 Grid 的实现非常简单,每行仅允许两列。@vaheqelyan实现了一个更复杂的Svelte-Grid版本。
<!-- Grid.svelte -->
<style>
.section {
display: flex;
flex: flex-wrap;
}
</style>
<section>
<slot></slot>
</section>
要在一个组件中使用多个插槽,请添加属性name=以创建命名插槽。命名插槽和未命名插槽可以组合使用。
<!-- GridItem.svelte -->
<style>
.div {
width: 50%;
}
</style>
<div>
<slot name="title"></slot>
<hr>
<slot name="content"></slot>
<slot></slot>
<!-- or <slot /> -->
</div>
这是一种创建复杂组件组合的强大方法。下面我们将看到一个完整的网格布局示例:
<!-- index.svelte -->
<script>
import Grid from '../components/Grid.svelte';
import GridItem from '../components/GridItem.svelte';
let title = 'World!";
</script>
<h1>Hello {title}</h1>
<Grid>
<GridItem>
<h2 slot="title">I will be rendered within the named slot title.</h2>
<p slot="content">I will be rendered within the named slot.</h2>
<p>I will be rendered within the unnamed slot.</p>
</GridItem>
<GridItem>
<h2 slot="title">I only have a headline, nothing else.</h2>
</GridItem>
</Grid>
在 Svelte 中添加组件、数据、属性等,只需在
<script>代码块中导入或声明即可,无需进一步注册。
下一步
🤩 掌握了这些知识,就可以开始实现你的第一个 Svelte 单文件组件了🤩
小型静态页面通常不需要太多功能。为了巩固相关知识,我建议花 1 小时时间学习一下官方教程。
还有更多东西需要学习。Svelte 提供了生命周期钩子、绑定、存储、过渡等诸多功能,可以用来创建更复杂的应用程序。继续学习吧!👨🎓👩🎓
文章来源:https://dev.to/vannsl/all-you-need-to-know-to-start-writing-svelte-single-file-components-cbd