error: 'type' attribute cannot be dynamic if input uses two-way binding

error: 'type' attribute cannot be dynamic if input uses two-way binding

我试图为我的项目创建一个 Input 组件。我想在 input 元素

上动态设置类型属性

但是当我在 input 上动态设置类型属性时,我得到错误提示 'type' attribute cannot be dynamic if input uses two-way binding

所以有什么解决方法可以动态设置类型属性而不会丢失双向绑定

Input.svelte

<script>
  export let placeholder = "";
  export let label = "";
  export let description = "";
  export let value = "";
  export let type = "text";
</script>

<div class="container">
    <label>{label}</label>
    <input {type} bind:value {placeholder} />
    <p>{description}</p>
</div>

type 双向绑定必须是静态的原因是 Svelte 生成的代码对于不同类型的输入是不同的。例如,numberrange 输入必须将其值强制转换为数字,一些输入需要 change 事件侦听器而不是 input 事件,反之亦然,等等。

但是您可以手动执行生成的代码会执行的相同操作 — 添加一个反映状态的事件侦听器:

<script>
  export let placeholder = "";
  export let label = "";
  export let description = "";
  export let value = "";
  export let type = "text";

  const handleInput = e => {
    // in here, you can switch on type and implement
    // whatever behaviour you need
    value = type.match(/^(number|range)$/)
      ? +e.target.value
      : e.target.value;
  };
</script>

<div class="container">
    <label>{label}</label>
    <input {type} {value} {placeholder} on:input={handleInput} />
    <p>{description}</p>
</div>

一个简单的解决方法:通过 id 获取元素并使用 element.setAttribute(attributename, attributevalue) 设置类型

<script>
  export let id = "";
  export let placeholder = "";
  export let label = "";
  export let description = "";
  export let value = "";
  export let type = "text";
</script>

<div class="container">
    <label>{label}</label>
    <input {type} bind:value {placeholder}
    on:focus="{() => {
       console.log(type)
       let inpt =    document.getElementById(id)
       inpt.setAttribute("type", type)
       console.log(inpt)
    }}"/>
    <p>{description}</p>
</div>

希望对您有所帮助:-)

<!-- InputField.svelte -->
<script>
  export let placeholder = "";
  export let label = "";
  export let description = "";
  export let value = "";
  export let type = "text";

  const handleInputType = (e) => {
    e.target.type = type;
  };
</script>

<div class="container">
    <label>{label}</label>
    <input {value} {placeholder} on:input={handleInputType} />
    <p>{description}</p>
</div>

我遇到了这个,为了简化,我所做的就像上面一样,基本上我删除了输入中的 {type} 并且在输入时我只是修改目标类型,因为这是一个组件,所以在你的 parent/route svelte 文件上。

<InputField type="email" bind:value={emailValue} />

类似的东西怎么样?

export let type: 'email' | 'text' | 'password' | 'number' = 'text'

let ref: HTMLInputElement

onMount(() => {
  if (ref) {
    ref.type = type
  }
})

然后

<input bind:this={ref} />

export let type: 'email' | 'text' | 'password' | 'number' = 'text'

const ref = (node: HTMLInputElement) => {
  node.type = type
}

然后

<input use:ref />

另一种可能的解决方案不是很优雅或 DRY,但不需要自己模拟核心 Svelte 功能是简单地在 type 上分支并相应地呈现不同的输入:

<script>
  export let name;
  export let value;
  export let type = 'text';
</script>


{#if type === 'password'}
  <input
    type="password"
    id={name}
    {name}
    on:change
    on:blur
    bind:value
  />
{:else if type === 'email'}
  <input
    type="email"
    id={name}
    {name}
    on:change
    on:blur
    bind:value
  />
{:else if type === 'number'}
  <input
    type="number"
    id={name}
    {name}
    on:change
    on:blur
    bind:value
  />
{:else if type === 'date'}
  <input
    type="date"
    id={name}
    {name}
    on:change
    on:blur
    bind:value
  />
{:else}
  <input
    type="text"
    id={name}
    {name}
    on:change
    on:blur
    bind:value
  />
{/if}

use 组件中设置节点类型的函数:

Input.svelte:

<script>
    export let type = 'text'
    export let label
    export let value

    function typeAction(node) {
        node.type = type;
    }
</script>

<div class="space-y-1">
    <label>{label}</label>

    <input use:typeAction bind:value class="rounded-md w-full">

    <p class="text-sm text-red-600">errors</p>
</div>

Form.svelte:

    <form on:submit|preventDefault={login}>
        <Input type="email" label="Email" bind:value={values.email}/>
        <Input type="password" label="Password" bind:value={values.password}/>

        <Button type="submit" label="Login"/>
    </form>

将输入导出到独立组件,然后手动处理输入而不是绑定,然后可以设置动态类型。 然后你可以将值绑定到组件。

参见此处示例: https://svelte.dev/repl/77f694a1851d464b85b382f4f152cb8e?version=3.46.4