文本输入
一般来说,Svelte中的数据流是自上而下的,父组件可以在子组件上设置属性,组件可以在 素上设置属性,但反过来就不行了
下面的例子,就类似于双向绑定
<script> let name = 'world'; </script> <input bind:value={name}> <h1>Hello {name}!</h1>
name的值的改变会同步影响到最后页面的输出显示
使用了 Svelte 的双向绑定语法
bind:value
,将文本框的值绑定到了名为inputValue
的变量上。这意味着当用户在文本框中输入内容时,inputValue
的值会自动更新为文本框中的内容,并且当inputValue
的值改变时,文本框中的内容也会相应地更新。
数字输入
在DOM中,一切都是字符串,也就是说处理数字输入的时候,我们需要对它进行强制类型转换
<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>
type="range"
是 HTML 中用于创建拖动条(滑块)的一种输入类型,可以使用这种输入类型来创建拖动条,并通过双向绑定来与组件中的数据属性关联起来
复选框
我们不仅可以使用input.value
,也可以将复选状态绑定input.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>
type=chackbox可以创建一个复选框,并使用双向绑定bind:checked将复选框的状态绑定到yes变量上,
输入框组绑定
如果需要绑定更多的值,可以使用bind:grop将value属性放在一起。在bind:grop中,同一组的单选框值是互斥的,但同一组的复选框会成为一个数组
<script> let scoops = 1; let flavours = ['Mint choc chip']; let menu = [ '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> <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 menu as flavour} <label> <input type=checkbox bind:group={flavours} value={flavour}> {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 {join(flavours)} </p> {/if}
文本域绑定
<textarea>
标签在 Svelte 也可使用bind:value
进行绑定
如果变量名和值是相同的,也可以用简写的形式
<script>
import marked from 'marked';
let value = `Some words are *italic*, some are bold`;
</script>
<style>
textarea { width: 100%; height: 200px; }
</style>
<textarea bind:value></textarea>
{@html marked(value)}
选择框绑定
可以利用 bind:value
对 <select>
标签进行绑定,即使 <option>
中的值是对象而非字符串, Svelte 对它进行绑定也不会有任何困难。
<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>
由于我们没有
selected
设置为初始值,因此绑定会自动将其(列表中的第一个)设置为默认值。 但也要注意,在绑定的目标未初始化前,selected
仍然是未定义的,因此我们应该谨慎的使用诸如selected.id
中的内容。
选择框的multiple属性
选择框含有一个名为 multiple
的属性,在这种情况下,它将会被设置为数组而不是单值。
<script> let scoops = 1; let flavours = ['Mint choc chip']; let menu = [ '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> <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> <select multiple bind:value={flavours}> {#each menu as flavour} <option value={flavour}> {flavour} </option> {/each} </select> {#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}
contenteditable绑定
contenteditable="true" 是 HTML 中一个属性,用于使素的内容可编辑。当将 contenteditable 属性设置为 "true" 时,用户可以直接在指定的素中输入文本、删除文本以及执行其他编辑操作
常见的可编辑素包括 <div>、<p>、<span> 等素,以及 <iframe> 素中的内容。 这个属性可以应用于单个素,也可以应用于整个文档。
<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>
Each绑定
在 JavaScript 中,each
块通常指的是在使用类似 jQuery 或类似的库中的方法,用于迭代数组或对象的每个素,并对其执行指定的操作。
<script> let todos = [ { done: false, text: 'finish Svelte tutorial' }, { done: false, text: 'build an app' }, { done: false, text: 'world domination' } ]; function add() { todos = todos.concat({ done: false, text: '' }); } function clear() { todos = todos.filter(t => !t.done); } $: remaining = todos.filter(t => !t.done).length; </script> <style> .done { opacity: 0.4; } </style> <h1>Todos</h1> {#each todos as todo} <div class:done={todo.done}> <input type=checkbox bind:checked={todo.done} > <input placeholder="What needs to be done?" bind:value={todo.text} > </div> {/each} <p>{remaining} remaining</p> <button on:click={add}> Add new </button> <button on:click={clear}> Clear completed </button>
媒体标签的绑定
<audio>
和 <video>
同样支持部分的属性绑定
<script> // These values are bound to properties of the video let time = 0; let duration; let paused = true; let showControls = true; let showControlsTimeout; function handleMousemove(e) { // Make the controls visible, but fade out after // 2.5 seconds of inactivity clearTimeout(showControlsTimeout); showControlsTimeout = setTimeout(() => showControls = false, 2500); showControls = true; if (!(e.buttons & 1)) return; // mouse not down if (!duration) return; // video not loaded yet const { left, right } = this.getBoundingClientRect(); time = duration * (e.clientX - left) / (right - left); } function handleMousedown(e) { // we can't rely on the built-in click event, because it fires // after a drag — we have to listen for clicks ourselves function handleMouseup() { if (paused) e.target.play(); else e.target.pause(); cancel(); } function cancel() { e.target.removeEventListener('mouseup', handleMouseup); } e.target.addEventListener('mouseup', handleMouseup); setTimeout(cancel, 200); } function format(seconds) { if (isNaN(seconds)) return '...'; const minutes = Math.floor(seconds / 60); seconds = Math.floor(seconds % 60); if (seconds < 10) seconds = '0' + seconds; return `${minutes}:${seconds}`; } </script> <style> div { position: relative; } .controls { position: absolute; top: 0; width: 100%; transition: opacity 1s; } .info { display: flex; width: 100%; justify-content: space-between; } span { padding: 0.2em 0.5em; color: white; text-shadow: 0 0 8px black; font-size: 1.4em; opacity: 0.7; } .time { width: 3em; } .time:last-child { text-align: right } progress { display: block; width: 100%; height: 10px; -webkit-appearance: none; appearance: none; } progress::-webkit-progress-bar { background-color: rgba(0,0,0,0.2); } progress::-webkit-progress-value { background-color: rgba(255,255,255,0.6); } video { width: 100%; } </style> <h1>Caminandes: Llamigos</h1> <p>From <a href="https://cloud.blender.org/open-projects">Blender Open Projects</a>. CC-BY</p> <div> <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> <div class="controls" style="opacity: {duration && showControls ? 1 : 0}"> <progress value="{(time / duration) || 0}"/> <div class="info"> <span class="time">{format(time)}</span> <span>click anywhere to {paused ? 'play' : 'pause'} / drag to seek</span> <span class="time">{format(duration)}</span> </div> </div> </div>
在网页中, 会将
currentTime
用于对timeupdate
的事件监听并跟踪。但是这些事件很少触发,导致UI不稳定。 Svelte 使用currentTime
对requestAnimationFrame
进行查验,进而避免了此问题。
针对 <audio>
和 <video>
的 readonly 属性绑定 :
duration
(readonly) :视频的总时长,以秒为单位。buffered
(readonly) :数组{start, end}
的对象。表示已缓冲的媒体时间范围seekable
(readonly) :返回一个TimeRanges
对象,表示已经播放的部分。played
(readonly) :返回一个TimeRanges
对象,表示可以进行跳转的部分。seeking
(readonly) :布尔值。返回媒体是否正在进行跳转操作。ended
(readonly) :布尔值。返回媒体是否已经播放完毕。paused
(readonly) : 返回媒体是否处于暂停状态。currentTime
(readonly): 返回当前媒体的播放位置(以秒为单位)。
4个双向绑定:
currentTime
:视频中的当前点,以秒为单位。playbackRate
:播放视频的倍速,1
为 '正常'。paused
:暂停。volume
:音量,0到1之间的值。
尺寸的绑定
每个块级标签都可以对 clientWidth
、clientHeight
、offsetWidth
以及 offsetHeight
属性进行绑定:
<script> let w; let h; let size = 42; let text = 'edit me'; </script> <style> input { display: block; } div { display: inline-block; } span { word-break: break-all; } </style> <input type=range bind:value={size}> <input bind:value={text}> <p>size: {w}px x {h}px</p> <div bind:clientWidth={w} bind:clientHeight={h}> <span style="font-size: {size}px">{text}</span> </div>
这些绑定是只读的,更改w
和 h
的值不会有任何效果。
This
this
可以绑定到任何标签 (或组件) 并允许获取对渲染标签的引用。
<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>
使用
bind:this
指令可以将 DOM 素绑定到组件中的变量,以便在组件中对其进行引用和操作。这样可以方便地在组件中访问 DOM 素的属性、方法和事件
组件绑定
正如可以绑定到DOM素的属性一样,也可以将组件的属性绑定。例如,我们能绑定位于<Keypad>
组件内的 value
属性,就如同一个表单标签一般:
<Keypad bind:value={pin} on:submit={handleSubmit}/>
Keypad.svelte
<script> import { createEventDispatcher } from 'svelte'; export let value = ''; const dispatch = createEventDispatcher(); const select = num => () => value += num; const clear = () => value = ''; const submit = () => dispatch('submit'); </script> <style> .keypad { display: grid; grid-template-columns: repeat(3, 5em); grid-template-rows: repeat(4, 3em); grid-gap: 0.5em } button { margin: 0 } </style> <div class="keypad"> <button on:click={select(1)}>1</button> <button on:click={select(2)}>2</button> <button on:click={select(3)}>3</button> <button on:click={select(4)}>4</button> <button on:click={select(5)}>5</button> <button on:click={select(6)}>6</button> <button on:click={select(7)}>7</button> <button on:click={select(8)}>8</button> <button on:click={select(9)}>9</button> <button disabled={!value} on:click={clear}>clear</button> <button on:click={select(0)}>0</button> <button disabled={!value} on:click={submit}>submit</button> </div>
App.svelte
<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}/>
现在,当用户键盘数字时,pin
父组件的数据将会立刻获得更新。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ji-chu/99843.html