模板语法基础 #
一、插值表达式 #
1.1 文本插值 #
svelte
<script>
let name = 'Svelte';
let count = 42;
</script>
<p>Hello {name}!</p>
<p>Count: {count}</p>
1.2 表达式插值 #
svelte
<script>
let a = 10;
let b = 20;
let items = ['a', 'b', 'c'];
let user = { name: 'Alice', age: 25 };
</script>
<p>Sum: {a + b}</p>
<p>Product: {a * b}</p>
<p>Items: {items.length}</p>
<p>User: {user.name}, Age: {user.age}</p>
<p>Method: {name.toUpperCase()}</p>
<p>Ternary: {a > b ? 'a大' : 'b大'}</p>
1.3 HTML 插入 #
svelte
<script>
let htmlContent = '<strong>加粗文本</strong>';
let markdown = '<a href="#">链接</a>';
</script>
<p>普通文本: {htmlContent}</p>
<p>HTML内容: {@html htmlContent}</p>
{@html markdown}
二、属性绑定 #
2.1 基本属性 #
svelte
<script>
let src = 'https://example.com/image.jpg';
let alt = 'Example Image';
let href = 'https://example.com';
</script>
<img {src} {alt} />
<a {href}>Link</a>
<button disabled>Disabled Button</button>
<input type="text" placeholder="Enter text" />
2.2 动态属性 #
svelte
<script>
let src = 'https://example.com/image.jpg';
let disabled = true;
let className = 'active';
</script>
<img src={src} alt="Dynamic Image" />
<button disabled={disabled}>Disabled</button>
<div class={className}>Dynamic Class</div>
2.3 属性展开 #
svelte
<script>
let attrs = {
id: 'my-input',
class: 'form-control',
placeholder: 'Enter text',
disabled: false
};
</script>
<input {...attrs} />
2.4 style 指令 #
svelte
<script>
let color = 'red';
let fontSize = 16;
let isActive = true;
</script>
<p style="color: {color}; font-size: {fontSize}px;">
Inline Style
</p>
<p style:color={color} style:font-size="{fontSize}px">
Style Directive
</p>
<p style:background-color={isActive ? 'green' : 'gray'}>
Conditional Style
</p>
2.5 class 指令 #
svelte
<script>
let isActive = true;
let isDisabled = false;
let theme = 'dark';
let size = 'large';
</script>
<button class:active={isActive} class:disabled={isDisabled}>
Toggle Button
</button>
<div class="box {theme}" class:highlight={isActive}>
Mixed Classes
</div>
<div class="btn" class="btn-{size}" class:btn-active={isActive}>
Button
</div>
三、双向绑定 #
3.1 表单输入绑定 #
svelte
<script>
let text = '';
let number = 0;
let email = '';
</script>
<input type="text" bind:value={text} placeholder="Text" />
<input type="number" bind:value={number} />
<input type="email" bind:value={email} />
<p>Text: {text}</p>
<p>Number: {number}</p>
<p>Email: {email}</p>
3.2 复选框绑定 #
svelte
<script>
let checked = false;
let hobbies = [];
</script>
<label>
<input type="checkbox" bind:checked={checked} />
Agree to terms
</label>
<fieldset>
<legend>Hobbies</legend>
<label>
<input type="checkbox" value="reading" bind:group={hobbies} />
Reading
</label>
<label>
<input type="checkbox" value="gaming" bind:group={hobbies} />
Gaming
</label>
<label>
<input type="checkbox" value="sports" bind:group={hobbies} />
Sports
</label>
</fieldset>
<p>Checked: {checked}</p>
<p>Hobbies: {hobbies.join(', ')}</p>
3.3 单选框绑定 #
svelte
<script>
let selected = '';
let size = 'medium';
</script>
<fieldset>
<legend>Choose Size</legend>
<label>
<input type="radio" value="small" bind:group={size} />
Small
</label>
<label>
<input type="radio" value="medium" bind:group={size} />
Medium
</label>
<label>
<input type="radio" value="large" bind:group={size} />
Large
</label>
</fieldset>
<p>Selected: {size}</p>
3.4 选择框绑定 #
svelte
<script>
let selected = '';
let selectedMultiple = [];
let options = ['Apple', 'Banana', 'Orange', 'Grape'];
</script>
<select bind:value={selected}>
<option value="">Select a fruit</option>
{#each options as option}
<option value={option}>{option}</option>
{/each}
</select>
<select multiple bind:value={selectedMultiple}>
{#each options as option}
<option value={option}>{option}</option>
{/each}
</select>
<p>Selected: {selected}</p>
<p>Multiple: {selectedMultiple.join(', ')}</p>
3.5 文本域绑定 #
svelte
<script>
let content = '';
</script>
<textarea bind:value={content} placeholder="Enter your message"></textarea>
<p>Characters: {content.length}</p>
<pre>{content}</pre>
3.6 内容可编辑元素 #
svelte
<script>
let html = '<p>Edit this text</p>';
</script>
<div bind:innerHTML={html} contenteditable="true"></div>
<pre>{html}</pre>
四、元素引用 #
4.1 bind:this #
svelte
<script>
let inputRef;
let canvasRef;
function focusInput() {
inputRef.focus();
}
function drawOnCanvas() {
const ctx = canvasRef.getContext('2d');
ctx.fillStyle = 'red';
ctx.fillRect(10, 10, 50, 50);
}
</script>
<input bind:this={inputRef} placeholder="Click button to focus" />
<button onclick={focusInput}>Focus Input</button>
<canvas bind:this={canvasRef} width="200" height="200"></canvas>
<button onclick={drawOnCanvas}>Draw</button>
4.2 组件引用 #
svelte
<script>
import Modal from './Modal.svelte';
let modalRef;
function openModal() {
modalRef.open();
}
</script>
<button onclick={openModal}>Open Modal</button>
<Modal bind:this={modalRef} />
五、媒体绑定 #
5.1 音频/视频属性 #
svelte
<script>
let audioRef;
let currentTime = 0;
let duration = 0;
let paused = true;
let volume = 1;
</script>
<audio
bind:this={audioRef}
bind:currentTime
bind:duration
bind:paused
bind:volume
src="audio.mp3"
/>
<p>Current: {currentTime.toFixed(2)}s</p>
<p>Duration: {duration.toFixed(2)}s</p>
<p>Status: {paused ? 'Paused' : 'Playing'}</p>
<p>Volume: {(volume * 100).toFixed(0)}%</p>
<button onclick={() => audioRef.play()}>Play</button>
<button onclick={() => audioRef.pause()}>Pause</button>
5.2 视频尺寸 #
svelte
<script>
let videoWidth = 0;
let videoHeight = 0;
</script>
<video
bind:videoWidth
bind:videoHeight
src="video.mp4"
/>
<p>Size: {videoWidth}x{videoHeight}</p>
六、尺寸绑定 #
6.1 元素尺寸 #
svelte
<script>
let clientWidth = 0;
let clientHeight = 0;
let offsetWidth = 0;
let offsetHeight = 0;
</script>
<div
bind:clientWidth
bind:clientHeight
bind:offsetWidth
bind:offsetHeight
class="box"
>
Resize me
</div>
<p>Client: {clientWidth}x{clientHeight}</p>
<p>Offset: {offsetWidth}x{offsetHeight}</p>
<style>
.box {
resize: both;
overflow: auto;
width: 200px;
height: 100px;
border: 1px solid #ccc;
}
</style>
6.2 窗口绑定 #
svelte
<script>
let innerWidth = 0;
let innerHeight = 0;
let outerWidth = 0;
let outerHeight = 0;
let scrollX = 0;
let scrollY = 0;
</script>
<svelte:window
bind:innerWidth
bind:innerHeight
bind:outerWidth
bind:outerHeight
bind:scrollX
bind:scrollY
/>
<p>Inner: {innerWidth}x{innerHeight}</p>
<p>Outer: {outerWidth}x{outerHeight}</p>
<p>Scroll: ({scrollX}, {scrollY})</p>
七、表单修饰符 #
7.1 事件修饰符 #
svelte
<script>
function handleSubmit() {
console.log('Form submitted');
}
function handleClick() {
console.log('Button clicked');
}
</script>
<form onsubmit|preventDefault={handleSubmit}>
<button type="submit">Submit</button>
</form>
<button onclick|once={handleClick}>
Click once
</button>
<div onclick={() => console.log('div')}>
<button onclick|stopPropagation={() => console.log('button')}>
Click me
</button>
</div>
7.2 修饰符列表 #
| 修饰符 | 说明 |
|---|---|
preventDefault |
调用 event.preventDefault() |
stopPropagation |
调用 event.stopPropagation() |
stopImmediatePropagation |
调用 event.stopImmediatePropagation() |
capture |
使用捕获模式 |
once |
只触发一次 |
self |
只在 event.target 是元素本身时触发 |
passive |
设置 passive 为 true |
nonpassive |
设置 passive 为 false |
trusted |
只在 event.isTrusted 为 true 时触发 |
7.3 组合修饰符 #
svelte
<button onclick|preventDefault|stopPropagation|once={handleClick}>
Multiple Modifiers
</button>
八、完整示例:表单组件 #
svelte
<script>
let form = $state({
username: '',
email: '',
password: '',
confirmPassword: '',
gender: '',
hobbies: [],
country: '',
bio: '',
agree: false
});
let errors = $state({});
let passwordStrength = $derived(() => {
const pwd = form.password;
if (!pwd) return '';
if (pwd.length < 6) return 'weak';
if (pwd.length < 10) return 'medium';
return 'strong';
});
function validate() {
const newErrors = {};
if (!form.username) newErrors.username = '用户名必填';
if (!form.email) newErrors.email = '邮箱必填';
if (!form.password) newErrors.password = '密码必填';
if (form.password !== form.confirmPassword) {
newErrors.confirmPassword = '密码不匹配';
}
if (!form.agree) newErrors.agree = '必须同意条款';
errors = newErrors;
return Object.keys(newErrors).length === 0;
}
function handleSubmit(e) {
if (validate()) {
console.log('Form submitted:', form);
}
}
</script>
<form onsubmit|preventDefault={handleSubmit}>
<div>
<label>Username</label>
<input type="text" bind:value={form.username} />
{#if errors.username}
<span class="error">{errors.username}</span>
{/if}
</div>
<div>
<label>Email</label>
<input type="email" bind:value={form.email} />
{#if errors.email}
<span class="error">{errors.email}</span>
{/if}
</div>
<div>
<label>Password</label>
<input type="password" bind:value={form.password} />
<span class="strength {passwordStrength()}">
{passwordStrength()}
</span>
{#if errors.password}
<span class="error">{errors.password}</span>
{/if}
</div>
<div>
<label>Confirm Password</label>
<input type="password" bind:value={form.confirmPassword} />
{#if errors.confirmPassword}
<span class="error">{errors.confirmPassword}</span>
{/if}
</div>
<fieldset>
<legend>Gender</legend>
<label>
<input type="radio" value="male" bind:group={form.gender} />
Male
</label>
<label>
<input type="radio" value="female" bind:group={form.gender} />
Female
</label>
</fieldset>
<fieldset>
<legend>Hobbies</legend>
<label>
<input type="checkbox" value="reading" bind:group={form.hobbies} />
Reading
</label>
<label>
<input type="checkbox" value="gaming" bind:group={form.hobbies} />
Gaming
</label>
<label>
<input type="checkbox" value="sports" bind:group={form.hobbies} />
Sports
</label>
</fieldset>
<div>
<label>Country</label>
<select bind:value={form.country}>
<option value="">Select</option>
<option value="cn">China</option>
<option value="us">USA</option>
<option value="uk">UK</option>
</select>
</div>
<div>
<label>Bio</label>
<textarea bind:value={form.bio}></textarea>
</div>
<div>
<label>
<input type="checkbox" bind:checked={form.agree} />
I agree to the terms
</label>
{#if errors.agree}
<span class="error">{errors.agree}</span>
{/if}
</div>
<button type="submit">Register</button>
</form>
<style>
form {
max-width: 400px;
margin: 0 auto;
}
div {
margin-bottom: 1rem;
}
label {
display: block;
margin-bottom: 0.25rem;
}
input, select, textarea {
width: 100%;
padding: 0.5rem;
border: 1px solid #ccc;
border-radius: 4px;
}
.error {
color: red;
font-size: 0.8rem;
}
.strength {
font-size: 0.8rem;
margin-left: 0.5rem;
}
.strength.weak { color: red; }
.strength.medium { color: orange; }
.strength.strong { color: green; }
</style>
九、总结 #
| 语法 | 说明 |
|---|---|
{expression} |
插值表达式 |
{@html html} |
插入 HTML |
{prop} |
属性简写 |
bind:value |
双向绑定 |
bind:this |
元素引用 |
class:name |
条件类名 |
style:name |
条件样式 |
| `on:event | modifier` |
模板语法要点:
- 使用
{}进行插值 bind:实现双向绑定class:和style:简化条件样式- 使用修饰符简化事件处理
bind:this获取元素引用
最后更新:2026-03-28