如何在Svelte中聚焦于从组件加载的输入字段?

10
在加载具有输入字段的组件后,我该如何聚焦到那个特定的字段?
TextField.svelte
<script>

  export let label = ''
  export let name = ''
  export let placeholder = ''
  export let value = ''

</script>

<div class="field">
  <label for={name}>{label}</label>
  <input {placeholder} type="text" {name} bind:value={value} >
  <slot></slot>
</div>

App.svelte

<script>
  import TextField from './TextField'
  import {onMount} from 'svete'

  onMount(() => {
    // This line is funny.. I know
    document.querySelector('[name="firstname"]').focus()
  })

</script>

<TextField label="First Name" name="firstname" />

我的问题有错别字。请参考下面的答案。 - Yousuf Iqbal Hashim
这个回答解决了你的问题吗?如何在Svelte中专注于新添加的输入? - sleighty
3个回答

17

您可以使用bind:this获取输入 DOM 节点的引用,并将其作为 prop 导出并在父组件中使用。

示例

<!-- TextField.svelte -->
<script>
  export let label = '';
  export let name = '';
  export let placeholder = '';
  export let value = '';
  export let ref = null;
</script>

<div class="field">
  <label for={name}>{label}</label>
  <input {placeholder} type="text" {name} bind:value={value} bind:this={ref} >
  <slot></slot>
</div>

<!-- App.svelte -->
<script>
  import TextField from './TextField.svelte';
  import { onMount } from 'svelte';
    
  let ref;
    
  onMount(() => {
    ref.focus(); 
  });      
</script>

<TextField label="First Name" name="firstname" bind:ref />

2
你试过这段代码吗?对我来说,"ref.focus()" 似乎无法工作,而我能够使用 "ref" 更改元素的其他属性。 - Yousuf Iqbal Hashim
'ref' 是什么意思?使用更好的变量名可能会更清晰明了。 - mikemaccana
1
@mikemaccana - ref只是reference的缩写,但在这个上下文中通常被使用,所以为了举例而言应该没问题。 - Lissy93
1
@Lissy93 ref 是指什么?一个元素(猜测)?使用 textfieldtextfieldElement 或其他完整单词会更清晰明了。 - mikemaccana

6
您的App.svelte实际上有几个拼写错误。
首先,导入组件。
import TextField from './TextField'

应该是这样的:

import TextField from './TextField.svelte';

其次,是Svelte包本身。

import {onMount} from 'svete'

应该是这样的:

import { onMount } from 'svelte';

好的,现在我们准备开始编码。

由于应该避免使用autofocus属性,因此我们可以参考Tholle的答案。

TextField.svelte中,您处理了autofocus

<script>
    import { onMount } from 'svelte';

    export let focused = false;
    export let label = '';
    export let name = '';
    export let placeholder = '';
    export let value = '';

    let elm;

    onMount(function() {
        elm.focus();
    });
</script>

<div class="field">
    <label for={name}>{label}</label>
    <input {placeholder} type="text" {name} bind:value={value} bind:this={elm}/>
    <slot/>
</div>

App.svelte 中,你调用了该组件。
<script>
  import TextField from './TextField.svelte';
</script>

<TextField label="First Name" name="firstname" focused/>
<TextField label="Last Name" name="lastname" focused/>

Svelte REPL上提供了演示。

我的答案和Tholle的区别在于,focus()应该在TextField组件中执行,因为它是组件特定功能。


不要因为愚蠢的拼写错误而编辑我的问题,以便您所写的宝贵行保持相关:) - Yousuf Iqbal Hashim
请注意,应该避免的不是autofocus属性,而是_autofocus_本身,这也是这个答案所做的。所有这些只是为了消除警告。此外,在调用焦点之前,您应该在其前面加上await tick(),否则您的元素可能不存在。最后,在调用elm.focus()之前,您可能想要检查if (focused),否则该属性就没有意义了。 - sleighty

2
你可以使用"autofocus"属性。最初的回答中已经提到了这一点。
<script>

  export let label = ''
  export let name = ''
  export let placeholder = ''
  export let value = ''

</script>

<div class="field">
  <label for={name}>{label}</label>
  <input {placeholder} type="text" {name} bind:value={value} autofocus > // <-- here
  <slot></slot>
</div>

但是正如最初的回答所述,从可访问性的角度来看,这可能不是一个好主意。


2
现在这会触发一个警告:A11y: 避免使用autofocussvelte(a11y-autofocus)。所以正如OP所说,这可能不是正确的方法。 - Greg Malcolm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接