AlpineJs:无法读取未定义的属性(读取 'focus')
AlpineJs : Cannot read properties of undefined (reading 'focus')
我在 codepen 中将此代码用于 OTP 输入字段
此代码在 alpine@v2.3.5 中运行良好,但升级到 v3 后显示此错误
无法读取未定义的属性(读取 'focus')
<div
x-data="pinHandler()"
x-init="$nextTick(() => { $refs[0].focus() })"
class="flex items-start justify-center min-h-screen w-full bg-white p-16 pt-64">
<div class="relative p-10 pb-8 bg-indigo-500 mx-auto max-w-md rounded-lg shadow-2xl z-50">
<label
for="enter-pin"
class="block text-3xl mb-2 text-white font-extrabold text-center">Enter PIN</label>
<form
id="enter-pin"
class="flex flex-row flex-wrap justify-center space-x-4"
@submit.prevent="handleSubmit()"
@paste.prevent="handlePaste($event)">
<template x-for="(input, index) in Array.from({ length: length })" :key="index">
<input
@input.prevent="handleInput($event.target)"
@keydown.backspace="$event.target.value || focusPreviousRef($event.target.getAttribute('x-ref'))"
autocomplete="off"
:aria-label="`Pin ${index + 1}`"
data-lpignore="true"
:x-ref="index"
class="w-12 mb-4 rounded border border-gray-200 p-3 text-center appearance-none"
type="text"
maxlength="1">
</template>
</form>
</div>
<p class="absolute bottom-0" x-text="`value: ${value}`"></p>
</div>
根据 Alpine.js 升级指南,$refs 对动态创建元素的支持已弃用。
见Alpine.js Upgrade guide from V2
因此,要运行上面的代码,您应该像下面这样静态地创建输入元素。 (以下代码适用于 laravel blade 模板)
<form id="enter-pin" class="flex flex-row flex-wrap justify-center space-x-4" x-on:submit.prevent="handleSubmit()" x-on:paste.prevent="handlePaste($event)">
@for($i = 1; $i <= 6; $i++)
<input x-on:input.prevent="handleInput($event.target)" x-on:keydown.backspace="$event.target.value || focusPreviousRef($event.target.getAttribute('x-ref'))" autocomplete="off" data-lpignore="true" x-ref="{{ $i }}" class="w-12 mb-4 rounded border border-gray-200 p-3 text-center appearance-none" type="text" maxlength="1">
@endfor
绑定id怎么样?
$root.querySelector(
#pin-${上一个})
document.getElementById(
pin-${上一个})
<input
@input.prevent="handleInput($event.target)"
@keydown.backspace="$event.target.value || focusPreviousRef(index)"
autocomplete="off"
:aria-label="`Pin ${index + 1}`"
data-lpignore="true"
{{-- :x-ref="index" --}}
:id="`pin-${index}`"
class="w-12 mb-4 rounded border border-gray-200 p-3 text-center appearance-none"
type="text"
maxlength="1">
----
focusPreviousRef(index) {
const previous = parseInt(index, 10) - 1
previous_element=this.$root.querySelector(`#pin-${previous}`);
previous_element.focus()
previous_element.select()
},
我在 codepen 中将此代码用于 OTP 输入字段
此代码在 alpine@v2.3.5 中运行良好,但升级到 v3 后显示此错误
无法读取未定义的属性(读取 'focus')
<div
x-data="pinHandler()"
x-init="$nextTick(() => { $refs[0].focus() })"
class="flex items-start justify-center min-h-screen w-full bg-white p-16 pt-64">
<div class="relative p-10 pb-8 bg-indigo-500 mx-auto max-w-md rounded-lg shadow-2xl z-50">
<label
for="enter-pin"
class="block text-3xl mb-2 text-white font-extrabold text-center">Enter PIN</label>
<form
id="enter-pin"
class="flex flex-row flex-wrap justify-center space-x-4"
@submit.prevent="handleSubmit()"
@paste.prevent="handlePaste($event)">
<template x-for="(input, index) in Array.from({ length: length })" :key="index">
<input
@input.prevent="handleInput($event.target)"
@keydown.backspace="$event.target.value || focusPreviousRef($event.target.getAttribute('x-ref'))"
autocomplete="off"
:aria-label="`Pin ${index + 1}`"
data-lpignore="true"
:x-ref="index"
class="w-12 mb-4 rounded border border-gray-200 p-3 text-center appearance-none"
type="text"
maxlength="1">
</template>
</form>
</div>
<p class="absolute bottom-0" x-text="`value: ${value}`"></p>
</div>
根据 Alpine.js 升级指南,$refs 对动态创建元素的支持已弃用。
见Alpine.js Upgrade guide from V2
因此,要运行上面的代码,您应该像下面这样静态地创建输入元素。 (以下代码适用于 laravel blade 模板)
<form id="enter-pin" class="flex flex-row flex-wrap justify-center space-x-4" x-on:submit.prevent="handleSubmit()" x-on:paste.prevent="handlePaste($event)">
@for($i = 1; $i <= 6; $i++)
<input x-on:input.prevent="handleInput($event.target)" x-on:keydown.backspace="$event.target.value || focusPreviousRef($event.target.getAttribute('x-ref'))" autocomplete="off" data-lpignore="true" x-ref="{{ $i }}" class="w-12 mb-4 rounded border border-gray-200 p-3 text-center appearance-none" type="text" maxlength="1">
@endfor
绑定id怎么样?
$root.querySelector(
#pin-${上一个})
document.getElementById(
pin-${上一个})
<input
@input.prevent="handleInput($event.target)"
@keydown.backspace="$event.target.value || focusPreviousRef(index)"
autocomplete="off"
:aria-label="`Pin ${index + 1}`"
data-lpignore="true"
{{-- :x-ref="index" --}}
:id="`pin-${index}`"
class="w-12 mb-4 rounded border border-gray-200 p-3 text-center appearance-none"
type="text"
maxlength="1">
----
focusPreviousRef(index) {
const previous = parseInt(index, 10) - 1
previous_element=this.$root.querySelector(`#pin-${previous}`);
previous_element.focus()
previous_element.select()
},