Svelte入门

165 阅读1分钟

Svelte基础

1. 基本使用

跟着官网demo学习Svelte随记 在Svelte后缀文件中编写代码:类似vue文件template、script、style三个代码块,svelte也有对应的代码块

<!-- {} 花括号对应vue中的'Mustache 语法' -->
<h1>Hello {name.toUpperCase()}!</h1>

<img {src} alt="{propValue}" />
<!-- 类v-html功能 -->
<p>{@html string}</p>
<!-- 组件使用 -->
<Nested />
<!-- 事件绑定 -->
<button on:click={increment}>
	Clicked {count}
	{count === 1 ? 'time' : 'times'}
</button>
<script>
        //引入组件(组件使用
        import Nested from './Nested.svelte';
        let name = 'Svelte';
        let src = '/xxxx.jpg';
        let propValue = 'some value';
        //类v-html功能
        let string = `this string contains some <strong>HTML!!!</strong>`;
        //事件绑定
        let count = 0;
        function increment() {
            count += 1;
        }
        //计算属性声明
        $: doubled = count * 2;
</script>

<style>
</style>

push、pop、shift、unshift、splice方法不会造成响应式视图的更新, 解决方法:

	function addNumber() {
		numbers = [...numbers, numbers.length + 1];
	}
//这样更新响应式变量无效
// 准则:需要更新的响应式变量名 必须出现在赋值运算符的左边
function addNumber() {
   let foo = obj.foo;
   foo.bar=4;
}
//正确方法
obj.foo.bar = 4;

组件props定义与默认值方式

<script>
export let propName = '默认值';
export let another;
</script>
<p> propName is {propName} </p>
<p> another is {another} </p>

在app引入组件Component

<script>
import Comp from './Component.svelte'
const obj = {
propName: 'aa'
another: 'ss'
}
</script>

<Comp {...obj}/>

类v-if语句: # 是语句开始 ‘/’是语句结束 ‘:’是继续语句

{#if count>5} 
	<p>{count} is {count}</p>
{:else if count < 5}
	<p>{count} is less than 5</p>
{:else}
	<p>{count}</p>
{/if}

for循环,括号赋值key

	{#each colors as color,i (color.id)}
		<button
		aria-current={selected === color}
		aria-label="{color}"
		style="background: {color}"
		on:click={() => selected = color}
	>{i}</button>
	{/each}

await语法

{#await promise}
	<p>...waiting</p>
{:then number}
	<p>The number is {number}</p>
{:catch error}
	<p style="color: red">{error.message}</p>
{/await}

<!-- 简写 -->
{#await promise then number}
	<p>The number is {number}</p>
{/await}

事件监听

<script>
	let m = { x: 0, y: 0 };

	function handleMove(event) {
		m.x = event.clientX;
		m.y = event.clientY;
	}
</script>
<!-- 第一种写法 -->
<div on:pointermove={handleMove}>
	The pointer is at {m.x} x {m.y}
</div>
<!-- 第二种写法 -->
<!-- <div on:pointermove={(e)=>{
	handleMove(e)
}}>
	The pointer is at {m.x} x {m.y}
</div> -->
<div on:pointermove={(e)=>{
	m.x=e.clientX;
	m.y=e.clientY;
}}>
	The pointer is at {m.x} x {m.y}
</div>
<style>
	div {
		position: fixed;
		left: 0;
		top: 0;
		width: 100%;
		height: 100%;
		padding: 1rem;
	}
</style>

事件监听修饰符

<button on:click|once={() => alert('clicked')}>
	Click me
</button>

image.png

组件自定义事件,要引入createEventDispatcher包并创建实例

<script>
	import Inner from './Inner.svelte';

	function handleMessage(event,msg) {
		console.log(event,event.detail.text);
	}
</script>

<Inner on:message={(e,msg)=>{
	handleMessage(e,msg)
}}/>
<script>
	import {createEventDispatcher} from "svelte"
	const dispatch = createEventDispatcher();
	function sayHello() {
		dispatch('message', {
			text: 'Hello!'
		});
	}
</script>

<button on:click={sayHello}>
	Click to say hello
</button>

svelte组件事件触发默认不会向上冒泡,需要在中间组件添加

<script>
import {Inner} from 'Inner.svelte'

</script>
<Inner on:message/>

组件内绑定事件

<BigRedButton on:click={handleClick} />

//BigRedButton.svelte
<button on:click>
	Push
</button>

双向绑定

<script>
	let name = 'world';
</script>

<input bind:value={name} />

<h1>Hello {name}!</h1>

绑定input,radio和checkbox组group,将radio的value 和checkbox值赋值到变量和数组

<script>
	let scoops = 1;
	let flavours = [];

	const formatter = new Intl.ListFormat('en', { style: 'long', type: 'conjunction' });
</script>

<h2>Size</h2>

{#each [1, 2, 3] as number}
	<label>
		<input
			type="radio"
			name="scoops"
			value={number}
			bind:group={scoops}
		/>

		{number} {number === 1 ? 'scoop' : 'scoops'}
	</label>
{/each}

<h2>Flavours</h2>

{#each ['cookies and cream', 'mint choc chip', 'raspberry ripple'] as flavour}
	<label>
		<input
			type="checkbox"
			name="flavours"
			value={flavour}
			bind:group={flavours}
		/>

		{flavour}
	</label>
{/each}

{#if flavours.length === 0}
	<p>Please select at least one flavour</p>
{:else if flavours.length > scoops}
	<p>Can't order more flavours than scoops!</p>
{:else}
	<p>
		You ordered {scoops} {scoops === 1 ? 'scoop' : 'scoops'}
		of {formatter.format(flavours)}
	</p>
{/if}

获取元素即vue中的ref

<script>
let div
</script>
<div class="chat" bind:this={div}>

dom的更新是在微任务中,可以等待tick后即dom更新后再做对应的操作

await tick();

2. 状态管理store


//store.svelte
<script>
    import { writable } from 'svelte/store';
    export const count = writable(0);
</script>
//App.svelte
<script>
	import { count } from './stores.js';
	import Incrementer from './Incrementer.svelte';//更新

	let count_value;

	count.subscribe((value) => { //赋值
		count_value = value;
	});
</script>
//Incrementer.svelte
<script>
	import { count } from './stores.js';

	function increment() {
		count.update((n) => n + 1);
	}
</script>

自动订阅store变量与注销

<script>
	import { count } from './stores.js';
</script>

<h1>The count is {$count}</h1>

store的只读变量与衍生变量

import { readable } from 'svelte/store';

export const time = readable(new Date(), function start(set) {
	const interval = setInterval(() => {
		set(new Date());
	}, 1000);

	return function stop() {
		clearInterval(interval);
	};
});
const start = new Date();

export const elapsed = derived(
	time,
	($time) => Math.round(($time - start) / 1000)
);

自定义导出store变量的实例方法(要有subscribe方法)

import { writable } from 'svelte/store';

function createCount() {
	const { subscribe, set, update } = writable(0);

	return {
		subscribe,
		increment: () => update((n) => n + 1),
		decrement: () => update((n) => n - 1),
		reset: () => set(0)
	};
}

export const count = createCount();

可以在使用的过程中使用“双向绑定”对store的值进行设置和读取

<input bind:value={$name} />