Svelte模板语法入门:HTML与JS的完美结合
Svelte 模板语法基础:绑定
- 文本绑定
在 Svelte 中,将 JavaScript 变量的值显示在 HTML 中是非常常见的操作。这可以通过文本绑定来实现。
假设我们有一个 Svelte 组件,在
<script>
标签内定义一个变量:
<script>
let name = 'John';
</script>
<p>Hello, {name}!</p>
在上述代码中,{name}
就是文本绑定的示例。花括号将 JavaScript 表达式嵌入到 HTML 模板中,Svelte 会在渲染时将 name
变量的值替换到这里。
文本绑定不仅支持简单变量,还可以使用更复杂的 JavaScript 表达式。例如:
<script>
let num1 = 5;
let num2 = 3;
</script>
<p>The sum of {num1} and {num2} is {num1 + num2}.</p>
这里,{num1 + num2}
是一个算术表达式,Svelte 会计算其结果并显示在 HTML 中。
- 属性绑定
属性绑定用于将 JavaScript 变量的值绑定到 HTML 元素的属性上。例如,我们想根据一个变量来设置
<img>
元素的src
属性:
<script>
let imageSrc = 'https://example.com/image.jpg';
</script>
<img {src}>
这里,{src}
是一种简写形式,等同于 <img src={imageSrc}>
。这种简写方式使得代码更加简洁,当属性名和变量名相同时可以直接使用。
对于布尔属性,如 <input>
元素的 checked
属性,Svelte 的处理方式也很直观。假设我们有一个表示复选框是否选中的变量:
<script>
let isChecked = true;
</script>
<input type="checkbox" {checked}>
如果 isChecked
为 true
,则 checked
属性会被添加到 <input>
元素上,复选框将被选中;反之则不会添加该属性,复选框未选中。
- 双向绑定 双向绑定允许在 HTML 元素和 JavaScript 变量之间建立双向的数据流动。这在处理用户输入时非常有用,比如文本输入框。 以下是一个双向绑定文本输入框的示例:
<script>
let userInput = '';
</script>
<input type="text" bind:value={userInput}>
<p>You entered: {userInput}</p>
在这个例子中,当用户在输入框中输入内容时,userInput
变量的值会实时更新。同时,如果通过 JavaScript 代码改变 userInput
的值,输入框中的内容也会相应改变。
双向绑定还可以应用于其他表单元素,如 <select>
元素。假设我们有一个选项列表和一个用于存储选中值的变量:
<script>
let selectedOption = 'option2';
let options = ['option1', 'option2', 'option3'];
</script>
<select bind:value={selectedOption}>
{#each options as option}
<option value={option}>{option}</option>
{/each}
</select>
<p>You selected: {selectedOption}</p>
这里,用户在 <select>
元素中选择不同的选项时,selectedOption
变量的值会改变,同时如果通过 JavaScript 改变 selectedOption
的值,<select>
元素也会自动选中相应的选项。
条件渲染
- if 块
在 Svelte 中,
if
块用于根据条件决定是否渲染某部分 HTML 内容。语法如下:
<script>
let isLoggedIn = true;
</script>
{#if isLoggedIn}
<p>Welcome, user!</p>
{:else}
<p>Please log in.</p>
{/if}
在上述代码中,{#if isLoggedIn}
开始一个条件块。如果 isLoggedIn
为 true
,则会渲染 <p>Welcome, user!</p>
;否则,会渲染 {:else}
后面的 <p>Please log in.</p>
。
if
块还可以有多个分支,使用 {:else if}
语法。例如:
<script>
let score = 85;
</script>
{#if score >= 90}
<p>You got an A!</p>
{:else if score >= 80}
<p>You got a B!</p>
{:else if score >= 70}
<p>You got a C!</p>
{:else}
<p>You need to improve.</p>
{/if}
这里根据 score
的值,不同的 <p>
元素会被渲染。
- null 和 undefined 的处理
Svelte 对
null
和undefined
值在if
块中有特殊的处理。例如:
<script>
let data;
</script>
{#if data}
<p>The data is: {data}</p>
{:else}
<p>No data available.</p>
{/if}
如果 data
是 null
或 undefined
,则会渲染 {:else}
部分的内容。这在处理可能未加载数据的情况时很有用,比如从 API 获取数据。
列表渲染
- each 块
each
块用于遍历数组并为每个数组元素渲染相同结构的 HTML 内容。假设我们有一个包含用户名字的数组:
<script>
let users = ['Alice', 'Bob', 'Charlie'];
</script>
{#each users as user}
<p>{user}</p>
{/each}
在这个例子中,{#each users as user}
表示遍历 users
数组,user
是每次迭代的数组元素。对于 users
数组中的每个名字,都会渲染一个 <p>
元素显示该名字。
- 索引的使用
在
each
块中,我们还可以获取当前迭代的索引。语法如下:
<script>
let numbers = [1, 2, 3, 4, 5];
</script>
{#each numbers as number, index}
<p>Index {index}: {number}</p>
{/each}
这里,index
就是当前迭代的索引,从 0 开始。我们可以在 HTML 模板中使用它来显示元素的索引信息。
- key 的重要性
当使用
each
块渲染列表时,为每个元素提供一个唯一的key
是非常重要的。这有助于 Svelte 更高效地更新列表。例如,我们有一个包含用户对象的数组,每个用户对象有一个唯一的id
:
<script>
let users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' }
];
</script>
{#each users as user (user.id)}
<p>{user.name}</p>
{/each}
这里,(user.id)
就是为每个 user
元素指定的 key
。当数组中的元素顺序改变或元素被添加、删除时,Svelte 可以通过 key
更准确地更新 DOM,而不是重新渲染整个列表。
事件处理
- 基本事件绑定 在 Svelte 中,绑定事件处理函数到 HTML 元素非常简单。例如,为一个按钮绑定点击事件:
<script>
function handleClick() {
console.log('Button clicked!');
}
</script>
<button on:click={handleClick}>Click me</button>
这里,on:click
表示绑定 click
事件,{handleClick}
是事件处理函数。当按钮被点击时,handleClick
函数会被调用,控制台会输出 Button clicked!
。
- 事件对象的访问
许多事件会提供一个事件对象,包含与事件相关的信息。在 Svelte 中,可以通过事件处理函数的参数来访问这个事件对象。例如,处理输入框的
input
事件:
<script>
function handleInput(event) {
console.log('Input value:', event.target.value);
}
</script>
<input type="text" on:input={handleInput}>
在 handleInput
函数中,event
参数就是输入事件的事件对象。我们可以通过 event.target.value
获取输入框的当前值。
- 修饰符的使用
Svelte 提供了一些事件修饰符,用于对事件处理进行更精细的控制。例如,
preventDefault
修饰符可以阻止事件的默认行为。对于表单的submit
事件,默认行为是提交表单并刷新页面,我们可以使用preventDefault
修饰符来阻止这种行为:
<script>
function handleSubmit(event) {
console.log('Form submitted, but not actually submitted to server.');
}
</script>
<form on:submit|preventDefault={handleSubmit}>
<input type="submit" value="Submit">
</form>
这里,|preventDefault
就是修饰符,它会在 handleSubmit
函数被调用前阻止表单的默认提交行为。
组件间通信
- 父组件向子组件传值
在 Svelte 中,父组件向子组件传递数据是通过属性(props)实现的。首先,创建一个子组件
Child.svelte
:
<script>
export let message;
</script>
<p>{message}</p>
这里,export let message
声明了一个名为 message
的属性,子组件可以接收来自父组件的值。
然后,在父组件 Parent.svelte
中使用子组件并传递数据:
<script>
import Child from './Child.svelte';
let parentMessage = 'Hello from parent!';
</script>
<Child message={parentMessage} />
在父组件中,通过 <Child message={parentMessage} />
将 parentMessage
的值传递给子组件的 message
属性,子组件会显示这个值。
- 子组件向父组件传值
子组件向父组件传值通常通过自定义事件实现。在子组件
Child.svelte
中:
<script>
import { createEventDispatcher } from'svelte';
const dispatch = createEventDispatcher();
function sendDataToParent() {
dispatch('custom-event', { data: 'Some data from child' });
}
</script>
<button on:click={sendDataToParent}>Send data to parent</button>
这里,createEventDispatcher
用于创建一个事件分发器 dispatch
。sendDataToParent
函数通过 dispatch('custom - event', { data: 'Some data from child' })
触发一个自定义事件 custom - event
,并传递数据。
在父组件 Parent.svelte
中监听这个自定义事件:
<script>
import Child from './Child.svelte';
function handleCustomEvent(event) {
console.log('Received data from child:', event.detail.data);
}
</script>
<Child on:custom-event={handleCustomEvent} />
父组件通过 on:custom - event={handleCustomEvent}
监听子组件触发的 custom - event
事件,handleCustomEvent
函数中的 event.detail.data
可以获取子组件传递的数据。
- 跨组件通信(非父子关系)
对于非父子关系的组件之间的通信,可以使用一个共享的状态管理机制。一种简单的方法是通过创建一个独立的 JavaScript 文件来管理共享状态。例如,创建
store.js
:
import { writable } from'svelte/store';
export const sharedData = writable('Initial value');
然后在两个非父子组件 ComponentA.svelte
和 ComponentB.svelte
中使用这个共享状态:
在 ComponentA.svelte
中:
<script>
import { sharedData } from './store.js';
function updateSharedData() {
sharedData.set('New value from ComponentA');
}
</script>
<button on:click={updateSharedData}>Update shared data</button>
在 ComponentB.svelte
中:
<script>
import { sharedData } from './store.js';
let data;
sharedData.subscribe((value) => {
data = value;
});
</script>
<p>The shared data is: {data}</p>
在 ComponentA.svelte
中,通过 sharedData.set
方法更新共享数据。在 ComponentB.svelte
中,通过 sharedData.subscribe
方法订阅共享数据的变化,并更新本地变量 data
以反映最新的值。
响应式声明
- 基本响应式变量 在 Svelte 中,声明响应式变量非常简单。当一个变量的值发生变化时,与之相关的 DOM 会自动更新。例如:
<script>
let count = 0;
function increment() {
count++;
}
</script>
<p>The count is: {count}</p>
<button on:click={increment}>Increment</button>
这里,count
是一个普通的 JavaScript 变量。当点击按钮调用 increment
函数使 count
的值增加时,<p>The count is: {count}</p>
部分的 DOM 会自动更新,显示最新的 count
值。
- 响应式声明块
Svelte 还提供了响应式声明块(
$:
),用于在变量变化时执行一些副作用操作。例如:
<script>
let num1 = 5;
let num2 = 3;
let sum;
$: sum = num1 + num2;
</script>
<p>The sum of {num1} and {num2} is {sum}</p>
<button on:click={() => num1++}>Increment num1</button>
<button on:click={() => num2++}>Increment num2</button>
在这个例子中,$: sum = num1 + num2;
是一个响应式声明块。当 num1
或 num2
的值发生变化时,sum
会重新计算,并且 <p>The sum of {num1} and {num2} is {sum}</p>
会自动更新。
- 派生状态 派生状态是基于其他响应式变量计算出来的响应式值。例如,我们有一个包含任务的数组,并且想计算已完成任务的数量:
<script>
let tasks = [
{ id: 1, text: 'Task 1', completed: true },
{ id: 2, text: 'Task 2', completed: false },
{ id: 3, text: 'Task 3', completed: true }
];
let completedTaskCount;
$: completedTaskCount = tasks.filter(task => task.completed).length;
</script>
<p>Number of completed tasks: {completedTaskCount}</p>
这里,completedTaskCount
是一个派生状态,它基于 tasks
数组计算得出。当 tasks
数组中的任务完成状态发生变化时,completedTaskCount
会自动更新,相关的 DOM 也会更新显示最新的已完成任务数量。
模板中的样式
- 局部样式
在 Svelte 组件中,
<style>
标签定义的样式是局部作用域的,只应用于该组件。例如:
<script>
let isActive = false;
</script>
<style>
.active {
background - color: lightblue;
}
</style>
<button class: active={isActive}>Click me</button>
在这个例子中,.active
类的样式只应用于当前组件中的按钮。class: active={isActive}
表示当 isActive
为 true
时,按钮会添加 .active
类,从而应用相应的样式。
- 全局样式
如果需要定义全局样式,可以在 Svelte 应用的入口文件(通常是
main.js
)中导入一个全局样式文件。例如,创建global.css
:
body {
font - family: Arial, sans - serif;
margin: 0;
padding: 0;
}
然后在 main.js
中导入:
import './global.css';
import App from './App.svelte';
const app = new App({
target: document.body
});
export default app;
这样,global.css
中的样式就会应用到整个应用中。
- 动态样式绑定 Svelte 支持动态绑定样式属性。例如,根据一个变量动态改变元素的颜色:
<script>
let color ='red';
function changeColor() {
color = 'blue';
}
</script>
<button style: color={color} on:click={changeColor}>Change color</button>
这里,style: color={color}
将按钮的 color
样式属性绑定到 color
变量。当点击按钮调用 changeColor
函数改变 color
的值时,按钮的文本颜色会动态更新。
过渡与动画
- 过渡效果
Svelte 提供了多种内置的过渡效果,如淡入淡出(
fade
)、滑动(slide
)等。要应用过渡效果,首先需要导入相应的过渡函数。例如,为一个元素添加淡入过渡效果:
<script>
import { fade } from'svelte/transition';
let showElement = false;
function toggleElement() {
showElement =!showElement;
}
</script>
<button on:click={toggleElement}>Toggle element</button>
{#if showElement}
<div transition: fade>
This is a fading element.
</div>
{/if}
在这个例子中,import { fade } from'svelte/transition';
导入了 fade
过渡函数。<div transition: fade>
表示当 showElement
变量变化时,<div>
元素会有淡入淡出的过渡效果。
- 动画效果
动画效果可以通过
animate
指令实现。例如,为一个元素添加位置移动的动画:
<script>
import { animate } from'svelte/animate';
let x = 0;
function startAnimation() {
animate('x', 100, {
duration: 1000,
easing: 'ease - out'
});
}
</script>
<button on:click={startAnimation}>Start animation</button>
<div style="position: relative; left: {x}px;">Animated element</div>
这里,animate('x', 100, { duration: 1000, easing: 'ease - out' })
表示将 x
的值从当前值动画过渡到 100,持续时间为 1000 毫秒,缓动函数为 ease - out
。<div style="position: relative; left: {x}px;">
根据 x
的值动态改变元素的位置,从而实现动画效果。
- 自定义过渡与动画 除了内置的过渡和动画,Svelte 还允许创建自定义的过渡和动画。例如,创建一个自定义的旋转过渡效果:
<script>
function customRotate(node, params) {
const start = window.getComputedStyle(node).transform;
const end = `rotate(${params.degrees}deg)`;
return {
duration: params.duration || 1000,
css: t => `transform: ${t === 0? start : (t === 1? end : `rotate(${t * params.degrees}deg)`)}`
};
}
let showElement = false;
function toggleElement() {
showElement =!showElement;
}
</script>
<button on:click={toggleElement}>Toggle element</button>
{#if showElement}
<div transition: customRotate={{ degrees: 360, duration: 2000 }}>
This is a rotating element.
</div>
{/if}
在这个例子中,customRotate
函数定义了一个自定义的旋转过渡效果。transition: customRotate={{ degrees: 360, duration: 2000 }}
将这个自定义过渡应用到 <div>
元素上,使其在显示和隐藏时会有旋转 360 度、持续 2000 毫秒的过渡效果。
通过以上对 Svelte 模板语法各个方面的详细介绍,相信读者已经对 Svelte 中 HTML 与 JS 的完美结合有了深入的理解,能够更加熟练地使用 Svelte 进行前端开发。