绑定
Text inputsbind:value
<script> let name = 'world'; </script> <input value={name}> <h1>Hello {name}!</h1>
对比vue:v-model==>bind:value=
Numeric inputsbind:value
<script> let a = 1; let b = 2; </script> <label> <input type=number bind:value={a} min=0 max=10> <input type=range bind:value={a} min=0 max=10> </label> <label> <input type=number bind:value={b} min=0 max=10> <input type=range bind:value={b} min=0 max=10> </label> <p>{a} + {b} = {a + b}</p>
复选框bind:checked
<script> let yes = false; </script> <label> <input type=checkbox bind:checked={yes}> Yes! Send me regular email spam </label> {#if yes} <p>Thank you. We will bombard your inbox and sell your personal details.</p> {:else} <p>You must opt in to continue. If you're not paying, you're the product.</p> {/if} <button disabled={!yes}> Subscribe </button>
输入框组绑定(单选框组、复选框组)bind:group
<script> let scoops = 1; let flavours = ['Mint choc chip']; function join(flavours) { if (flavours.length === 1) return flavours[0]; return `${flavours.slice(0, -1).join(', ')} and ${flavours[flavours.length - 1]}`; } let menus = [ 'Cookies and cream', 'Mint choc chip', 'Raspberry ripple' ]; </script> <h2>Size</h2> <label> <input type=radio bind:group={scoops} value={1}> One scoop </label> <label> <input type=radio bind:group={scoops} value={2}> Two scoops </label> <label> <input type=radio bind:group={scoops} value={3}> Three scoops </label> <h2>Flavours</h2> {#each menus as menu} <label> <input type=checkbox bind:group={flavours} value={menu}> {menu} </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 {join(flavours)} </p> {/if}
文本域绑定(多行文本)bind:value
<script>
let value = `Some words are *italic*, some are bold`;
</script>
<style>
textarea { width: 100%; height: 200px; }
</style>
<textarea bind:value={value}></textarea>
{@html value}
选择框绑定(多选框)bind:value
<script> let questions = [ { id: 1, text: `Where did you go to school?` }, { id: 2, text: `What is your mother's name?` }, { id: 3, text: `What is another personal fact that an attacker could easily find with Google?` } ]; let selected; let answer = ''; function handleSubmit() { alert(`answered question ${selected.id} (${selected.text}) with "${answer}"`); } </script> <style> input { display: block; width: 500px; max-width: 100%; } </style> <h2>Insecurity questions</h2> <form on:submit|preventDefault={handleSubmit}> <select bind:value={selected} on:change="{() => answer = ''}"> {#each questions as question} <option value={question}> {question.text} </option> {/each} </select> <input bind:value={answer}> <button disabled={!answer} type=submit> Submit </button> </form> <p>selected question {selected ? selected.id : '[waiting...]'}</p>
选择框的multiple属性
选择框含有一个名为 multiple 的属性,在这种情况下,它将会被设置为数组而不是单值。
<script> let scoops = 1; let flavours = ['Mint choc chip']; let menus = [ 'Cookies and cream', 'Mint choc chip', 'Raspberry ripple' ]; function join(flavours) { if (flavours.length === 1) return flavours[0]; return `${flavours.slice(0, -1).join(', ')} and ${flavours[flavours.length - 1]}`; } </script> <select multiple bind:value={flavours}> {#each menus as menu} <option value={menu}>{menu}</option> {/each} </select> {flavours}
contenteditable的绑定bind:innerHTML
支持 contenteditable="true"属性的标签,可以使用 textContent 与 innerHTML 属性的绑定:
<script>
let html = '<p>Write some text!</p>';
</script>
<div contenteditable="true" bind:innerHTML={html}></div>
<pre>{html}</pre>
<style>
[contenteditable] {
padding: 0.5em;
border: 1px solid #eee;
border-radius: 4px;
}
</style>
媒体标签的绑定bind:currentTime、bind:duration
和 同样支持部分的属性绑定
<video poster="https://sveltejs.github.io/assets/caminandes-llamigos.jpg" src="https://sveltejs.github.io/assets/caminandes-llamigos.mp4" on:mousemove={handleMousemove} on:mousedown={handleMousedown} bind:currentTime={time} bind:duration bind:paused ></video>
尺寸的绑定bind:clientWidth
每个块级标签都可以对 clientWidth、clientHeight、offsetWidth 以及 offsetHeight 属性进行绑定:
<div bind:clientWidth={w} bind:clientHeight={h}> <span style="font-size: {size}px">{text}</span> </div>
this
this可以绑定到任何标签 (或组件) 并允许你获取对渲染标签的引用。 例如,我们对<canvas> 标签进行绑定
<script> import { onMount } from 'svelte'; let canvas; onMount(() => { const ctx = canvas.getContext('2d'); let frame; (function loop() { frame = requestAnimationFrame(loop); const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); for (let p = 0; p < imageData.data.length; p += 4) { const i = p / 4; const x = i % canvas.width; const y = i / canvas.height >>> 0; const t = window.performance.now(); const r = 64 + (128 * x / canvas.width) + (64 * Math.sin(t / 1000)); const g = 64 + (128 * y / canvas.height) + (64 * Math.cos(t / 1000)); const b = 128; imageData.data[p + 0] = r; imageData.data[p + 1] = g; imageData.data[p + 2] = b; imageData.data[p + 3] = 255; } ctx.putImageData(imageData, 0, 0); }()); return () => { cancelAnimationFrame(frame); }; }); </script> <style> canvas { width: 100%; height: 100%; background-color: #666; -webkit-mask: url(svelte-logo-mask.svg) 50% 50% no-repeat; mask: url(svelte-logo-mask.svg) 50% 50% no-repeat; } </style> <canvas bind:this={canvas} width={32} height={32} ></canvas>
组件绑定
正如可以绑定到DOM素的属性一样,你也可以将组件的属性绑定。例如,我们能绑定位于<Keypad>组件内的 value 属性,就如同一个表单标签一般:
<script> import Keypad from './Keypad.svelte'; let pin; $: view = pin ? pin.replace(/\d(?!$)/g, '•') : 'enter your pin'; function handleSubmit() { alert(`submitted ${pin}`); } </script> <h1 style="color: {pin ? '#333' : '#ccc'}">{view}</h1> <Keypad bind:value={pin} on:submit={handleSubmit}/>
生命周期
onMount
它在组件首次呈现到 DOM 后运行
<script> import { onMount } from 'svelte'; let photos = []; onMount(async () => { const res = await fetch(`https://jsonplaceholder.typicode.com/photos?_limit=20`); photos = await res.json(); }) </script> <style> .photos { width: 100%; display: grid; grid-template-columns: repeat(5, 1fr); grid-gap: 8px; } figure, img { width: 100%; margin: 0; } </style> <h1>Photo album</h1> <div class="photos"> {#each photos as photo} <figure> <img src={photo.thumbnailUrl} alt={photo.title}> <figcaption>{photo.title}</figcaption> </figure> {:else} <!-- this block renders when photos.length === 0 --> <p>loading...</p> {/each} </div>
onDestroy
在组件被销毁时运行
<script> import { onDestroy } from 'svelte'; let seconds = 0; const interval = setInterval(() => seconds += 1, 1000); onDestroy(() => { clearInterval(interval) }) </script> <p> The page has been open for {seconds} {seconds === 1 ? 'second' : 'seconds'} </p>
beforeUpdate和afterUpdate
beforeUpdate 函数实现在DOM渲染完成前执行。afterUpdate函数则相反,它会运行在你的异步数据加载完成后。
let div; let autoscroll; beforeUpdate(() => { autoscroll = div && (div.offsetHeight + div.scrollTop) > (div.scrollHeight - 20); }); afterUpdate(() => { if (autoscroll) div.scrollTo(0, div.scrollHeight); });
tick
tick函数不同于其他生命周期函数,因为你可以随时调用它,而不用等待组件首次初始化。它返回一个带有resolve方法的 ,每当组件pending状态变化便会立即体现到DOM中 (除非没有pending状态变化)。
import { tick } from 'svelte'; await tick(); this.selectionStart = selectionStart; this.selectionEnd = selectionEnd;
Stores
Writable stores
- writable
import { writable } from 'svelte/store'; export const count = writable(0);
- update
<script> import { count } from './stores.js'; function increment() { // TODO increment the count count.update(n => n+1); } </script> <button on:click={increment}> + </button>
- set
<script> import { count } from './stores.js'; function reset() { // TODO reset the count count.set(0) } </script> <button on:click={reset}> reset </button>
- subscribe
<script> import { count } from './stores.js'; import Incrementer from './Incrementer.svelte'; import Decrementer from './Decrementer.svelte'; import Resetter from './Resetter.svelte'; let count_value; const unsubscribe = count.subscribe(value => { count_value = value; }); </script> <h1>The count is {count_value}</h1> <Incrementer/> <Decrementer/> <Resetter/>
Auto-subscriptions
$xxx:包含订阅和取消订阅
<script> import { count } from './stores.js'; import Incrementer from './Incrementer.svelte'; import Decrementer from './Decrementer.svelte'; import Resetter from './Resetter.svelte'; let count_value; const unsubscribe = count.subscribe(value => { count_value = value; }); </script> <h1>The count is {$count}</h1> <Incrementer/> <Decrementer/> <Resetter/>
readable stores
并非所有stores都需要在其他地方写入,比如,你可能有一个代表鼠标位置或者用户地理位置的stores,这样的stores从其他地方写入并无意义,对于这种情况,我们有 只读(readable) stores。
到 stores.js 选项卡, 第一个参数 readable可以一个是个初始值,也可以为 null 或 undefined ,第二个参数是 start 函数,该函数有个 set 回调方法,并返回一个 stop函数。 当stores首次被subscriber 时调用start函数,stop则是最后当subscriber被unsubscribes时调用。
export const time = readable(new Date(), function start(set) { const interval = setInterval(() => { set(new Date()); }, 1000); return function stop() { clearInterval(interval); }; });
stores derived
你可以创建一个stores,其内的值可以派生(derived)于一个或多个 其他 stores。在前面的示例的基础上,我们可以创建派生时间到其他页面:
export const elapsed = derived( time, $time => Math.round(($time - start) / 1000) );
自定义stores(封装)
只要一个对象正确的使用 subscribe ,它就是可以称之为store。因此,使用特定语法来创建自定义 stores变得非常容易。
例如, 这个 count store 在前面的例子中包含 increment、 decrement 和 reset组件,以防止暴露 set 和update方法,让我们改写一下:
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();
使用:
<script> import { count } from './stores.js'; </script> <h1>The count is {$count}</h1> <button on:click={count.increment}>+</button> <button on:click={count.decrement}>-</button> <button on:click={count.reset}>reset</button>
绑定Store
如果 store可写入的(即具有set方法),则可以绑定其值,就像可以绑定局部组件状态一样。
<input bind:value={$name}> <button on:click="{() => $name += '!'}"> Add exclamation mark! </button> 今天的文章
Svelte之基础知识二:绑定、生命周期、Stores分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ji-chu/92666.html