[svelte]绑定

[svelte]绑定在 bind grop 中 同一组的单选框值是互斥的 但同一组的复选框会成为一个数组

文本输入

一般来说,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之间的值。
尺寸的绑定

每个块级标签都可以对 clientWidthclientHeightoffsetWidth 以及 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 父组件的数据将会立刻获得更新。

今天的文章 [svelte]绑定分享到此就结束了,感谢您的阅读。
编程小号
上一篇 2025-01-02 07:40
下一篇 2025-01-02 07:33

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ji-chu/99843.html