Vite:vite是集成了svelte,初始化的时候选择svelte就行了。
npm init vite
SvelteKit:底层基于vite的更上层框架,类似于nextjs。
npm create svelte@latest my-app cd my-app npm install npm run dev
和vue类似svelte文件是.svelte结尾的文件,比如demo.svelte。代码结构:
<script> let name = 'hello world'; </script> <div class="name"> {name} </div> <style> .name { color: red; } </style>
绑定变量
<script> let name = 'world'; </script> <h1>Hello {name}!</h1>
绑定属性
<script> let src = '/tutorial/image.gif'; let name = '张三'; </script> <img {src} alt="{name} dances.">
绑定事件
<script> let count = 0; function incrementCount() { count += 1; } </script> <button on:click={incrementCount}> Clicked {count} {count === 1 ? 'time' : 'times'} </button>
$:
类似于vue的computed
。例如:
<script> let count = 0; // 定义一个名字叫doubled的变量,当count的值改变时,doubled会改变。doubled变量时响应式的。 $: doubled = count * 2; // 直接这样写d2不是响应式的。 let d2 = count * 2; $: if (count >= 10) { alert('count is dangerously high!'); count = 9; } $: { console.log('the count is ' + count); alert('I SAID THE COUNT IS ' + count); } function handleClick() { count += 1; } </script> <button on:click={handleClick}> Clicked {count} {count === 1 ? 'time' : 'times'} </button> <p>{count} doubled is {doubled}</p> <p> t2 is {d2} </p>
为什么d2
变量不是响应式的,我们会在 svelte响应式原理里面解释。
if/else
<script> let user = { loggedIn: false }; function toggle() { user.loggedIn = !user.loggedIn; } </script> <div> {#if user.loggedIn} <button on:click={toggle}> Log out </button> {:else} <button on:click={toggle}> Log in </button> {/if} </div>
each遍历
<script> let cats = [ { id: 'J---aiyznGQ', name: 'Keyboard Cat' }, { id: 'z_AbfPXTKms', name: 'Maru' }, { id: 'OUtn3pvWmpg', name: 'Henri The Existential Cat' } ]; </script> <h1>The Famous Cats of YouTube</h1> <ul> {#each cats as { id, name }, i} <li><a target="_blank" href="https://www.youtube.com/watch?v={id}" rel="noreferrer"> {i + 1}: {name} </a></li> {/each} </ul>
await
<script> async function getRandomNumber() { const res = await fetch(`/tutorial/random-number`); const text = await res.text(); if (res.ok) { return {val: text}; } else { throw new Error(text); } } let promise = getRandomNumber(); function handleClick() { promise = getRandomNumber(); } </script> <button on:click={handleClick}> generate random number </button> {#await promise} <p>...waiting</p> {:then res} <p>The number is {res.val}</p> {:catch error} <p style="color: red">{error.message}</p> {/await}
双向数据流
<script> let name = 'world'; $: </script> <input bind:value={name}> <h1>Hello {name}!</h1>
使用子组件和父子组件通信
App.svelte
<script lang="ts"> import Child from './child.svelte'; var num = 1; var obj = { count: 1 } function handleAdd() { num = num + 1; obj.count = obj.count + 1; } function handleReset(event) { num = event.detail.val; obj.count = event.detail.val; } </script> <div> 我是父组件 <button on:click={handleAdd}>add num</button> // 也支持...的语法 <Child count={num} on:reset={handleReset} /> <Child {...obj} on:reset={handleReset} /> </div>
Child.svelte
<script> import { createEventDispatcher } from 'svelte'; export let count; const dispatch = createEventDispatcher(); function handleReset() { dispatch('reset', { val: 0 }); } </script> <div> <p>我是子组件,count is {count}</p> <button on:click={handleReset}>reset count</button> </div>
组件中使用双向数据流
App.svelte
<script> import Child from './child.svelte'; var name; </script> <p> name is {name} </p> <Child bind:name />
Child.svelte
<script> export let name; </script> <div> <input bind:value={name} /> </div>
插槽
App.svelte
<script> import Child from './child.svelte'; </script> <Child> <p>i am from App</p> <p slot="tool">i am tool</p> </Child>
Child.svelte
<div> <slot /> <slot name="tool" /> </div>
onMount、onDestroy、beforeUpdate、afterUpdate
<script> import { onMount, onDestroy, beforeUpdate, afterUpdate } from 'svelte'; onMount(() => { //... }); onDestroy(() => { //... }); beforeUpdate(() => { //... }); afterUpdate(() => { //... }); </script> <h1>Photo album</h1>