更新 Entangled Livewire 数组数据时抛出 Alpine JS 错误

Alpine JS Error thrown when updating Entangled Livewire array data

这是一个 Alpine 计数器的人为示例,entangled 带有 Livewire 组件数据。

这是我的 Livewire 组件:

<?php

namespace App\Http\Livewire;

use Livewire\Component;

class Foo extends Component
{
    public array $foo = [
        ['id'=>1,'bar'=>10],
        ['id'=>2,'bar'=>11],
        ['id'=>3,'bar'=>12]
    ];

    public function render()
    {
        return view('livewire.foo');
    }
}

在 Blade 模板中:

<div x-data="{ foo: @entangle('foo') }">
    <template x-for="f in foo" :key="f.id">
        <div x-data="{num: 0}" x-model="f.bar" x-modelable="num">
            Foo Counter Value: <div x-text="num"></div>
            <div @click="num ++">Increase</div>
        </div>
    </template>
</div>

如果我点击计数器的任何 Increase,它会在 Livewire 服务器请求后抛出此 JS 错误 returns:

module.esm.js?027e:416 Alpine Expression Error: num is not defined

Expression: "num"

 <div x-data=​"{num:​ 0}​" x-model=​"f.bar" x-modelable=​"num">​…​</div>​
handleError @ module.esm.js?027e:416
eval @ module.esm.js?027e:489
Promise.catch (async)
eval @ module.esm.js?027e:489
tryCatch @ module.esm.js?027e:409
innerGet @ module.esm.js?027e:2233
eval @ module.esm.js?027e:2239
flushHandlers @ module.esm.js?027e:546
stopDeferring @ module.esm.js?027e:551
deferHandlingDirectives @ module.esm.js?027e:554
initTree @ module.esm.js?027e:764
eval @ module.esm.js?027e:2778
mutateDom @ module.esm.js?027e:153
eval @ module.esm.js?027e:2776
runIfTypeOfFunction @ module.esm.js?027e:510
eval @ module.esm.js?027e:491
tryCatch @ module.esm.js?027e:409
loop @ module.esm.js?027e:2692
eval @ module.esm.js?027e:2682
reactiveEffect @ module.esm.js?027e:1571
effect2 @ module.esm.js?027e:1546
effect @ module.esm.js?027e:48
eval @ module.esm.js?027e:1178
wrappedEffect @ module.esm.js?027e:64
eval @ module.esm.js?027e:2682
flushHandlers @ module.esm.js?027e:546
stopDeferring @ module.esm.js?027e:551
deferHandlingDirectives @ module.esm.js?027e:554
initTree @ module.esm.js?027e:764
cloneTree @ module.esm.js?027e:1173
eval @ module.esm.js?027e:1159
dontRegisterReactiveSideEffects @ module.esm.js?027e:1183
clone @ module.esm.js?027e:1158
alpinifyElementsForMorphdomV3 @ SupportAlpine.js:294
alpinifyElementsForMorphdom @ SupportAlpine.js:250
onBeforeElUpdated @ index.js:479
callHook @ morphdom.js:35
morphEl @ morphdom.js:199
(anonymous) @ morphdom.js:332
morphEl @ morphdom.js:219
(anonymous) @ morphdom.js:463
value @ index.js:386
value @ index.js:291
value @ index.js:269
value @ index.js:11
(anonymous) @ index.js:69
Promise.then (async)
(anonymous) @ index.js:64
Promise.then (async)
value @ index.js:62
sendMessage @ index.js:242
value @ index.js:252
later @ debounce.js:8
setTimeout (async)
(anonymous) @ debounce.js:12
value @ index.js:225
value @ index.js:165
(anonymous) @ SupportAlpine.js:202
reactiveEffect @ module.esm.js?027e:1571
flushJobs @ module.esm.js?027e:28
Show 15 more frames
module.esm.js?027e:420
Uncaught ReferenceError: num is not defined
    at eval (eval at safeAsyncFunction (module.esm.js:1:1), <anonymous>:3:32)
    at eval (module.esm.js?027e:489:1)
    at tryCatch (module.esm.js?027e:409:1)
    at innerGet (module.esm.js?027e:2233:1)
    at Function.eval (module.esm.js?027e:2239:1)
    at flushHandlers (module.esm.js?027e:546:1)
    at stopDeferring (module.esm.js?027e:551:1)
    at deferHandlingDirectives (module.esm.js?027e:554:1)
    at initTree (module.esm.js?027e:764:1)
    at eval (module.esm.js?027e:2778:1)
eval @ VM3130:3
eval @ module.esm.js?027e:489
tryCatch @ module.esm.js?027e:409
innerGet @ module.esm.js?027e:2233
eval @ module.esm.js?027e:2239
flushHandlers @ module.esm.js?027e:546
stopDeferring @ module.esm.js?027e:551
deferHandlingDirectives @ module.esm.js?027e:554
initTree @ module.esm.js?027e:764
eval @ module.esm.js?027e:2778
mutateDom @ module.esm.js?027e:153
eval @ module.esm.js?027e:2776
runIfTypeOfFunction @ module.esm.js?027e:510
eval @ module.esm.js?027e:491
tryCatch @ module.esm.js?027e:409
loop @ module.esm.js?027e:2692
eval @ module.esm.js?027e:2682
reactiveEffect @ module.esm.js?027e:1571
effect2 @ module.esm.js?027e:1546
effect @ module.esm.js?027e:48
eval @ module.esm.js?027e:1178
wrappedEffect @ module.esm.js?027e:64
eval @ module.esm.js?027e:2682
flushHandlers @ module.esm.js?027e:546
stopDeferring @ module.esm.js?027e:551
deferHandlingDirectives @ module.esm.js?027e:554
initTree @ module.esm.js?027e:764
cloneTree @ module.esm.js?027e:1173
eval @ module.esm.js?027e:1159
dontRegisterReactiveSideEffects @ module.esm.js?027e:1183
clone @ module.esm.js?027e:1158
alpinifyElementsForMorphdomV3 @ SupportAlpine.js:294
alpinifyElementsForMorphdom @ SupportAlpine.js:250
onBeforeElUpdated @ index.js:479
callHook @ morphdom.js:35
morphEl @ morphdom.js:199
(anonymous) @ morphdom.js:332
morphEl @ morphdom.js:219
(anonymous) @ morphdom.js:463
value @ index.js:386
value @ index.js:291
value @ index.js:269
value @ index.js:11
(anonymous) @ index.js:69
setTimeout (async)
handleError @ module.esm.js?027e:419
eval @ module.esm.js?027e:489
Promise.catch (async)
eval @ module.esm.js?027e:489
tryCatch @ module.esm.js?027e:409
innerGet @ module.esm.js?027e:2233
eval @ module.esm.js?027e:2239
flushHandlers @ module.esm.js?027e:546
stopDeferring @ module.esm.js?027e:551
deferHandlingDirectives @ module.esm.js?027e:554
initTree @ module.esm.js?027e:764
eval @ module.esm.js?027e:2778
mutateDom @ module.esm.js?027e:153
eval @ module.esm.js?027e:2776
runIfTypeOfFunction @ module.esm.js?027e:510
eval @ module.esm.js?027e:491
tryCatch @ module.esm.js?027e:409
loop @ module.esm.js?027e:2692
eval @ module.esm.js?027e:2682
reactiveEffect @ module.esm.js?027e:1571
effect2 @ module.esm.js?027e:1546
effect @ module.esm.js?027e:48
eval @ module.esm.js?027e:1178
wrappedEffect @ module.esm.js?027e:64
eval @ module.esm.js?027e:2682
flushHandlers @ module.esm.js?027e:546
stopDeferring @ module.esm.js?027e:551
deferHandlingDirectives @ module.esm.js?027e:554
initTree @ module.esm.js?027e:764
cloneTree @ module.esm.js?027e:1173
eval @ module.esm.js?027e:1159
dontRegisterReactiveSideEffects @ module.esm.js?027e:1183
clone @ module.esm.js?027e:1158
alpinifyElementsForMorphdomV3 @ SupportAlpine.js:294
alpinifyElementsForMorphdom @ SupportAlpine.js:250
onBeforeElUpdated @ index.js:479
callHook @ morphdom.js:35
morphEl @ morphdom.js:199
(anonymous) @ morphdom.js:332
morphEl @ morphdom.js:219
(anonymous) @ morphdom.js:463
value @ index.js:386
value @ index.js:291
value @ index.js:269
value @ index.js:11
(anonymous) @ index.js:69
Promise.then (async)
(anonymous) @ index.js:64
Promise.then (async)
value @ index.js:62
sendMessage @ index.js:242
value @ index.js:252
later @ debounce.js:8
setTimeout (async)
(anonymous) @ debounce.js:12
value @ index.js:225
value @ index.js:165
(anonymous) @ SupportAlpine.js:202
reactiveEffect @ module.esm.js?027e:1571
flushJobs @ module.esm.js?027e:28
Show 57 more frames

注意:这实际上似乎工作得很好。计数器增加,但抛出此 JS 错误。它似乎只在您第一次单击其中一个“增加”按钮时抛出错误。

我只需要将 wire:ignore 添加到包含 x-datadiv,这样 Livewire 就不会尝试更新 DOM。这很好,因为 Alpine 管理 DOM 所需的一切。

<div x-data="{ foo: @entangle('foo') }" wire:ignore>
    <template x-for="f in foo" :key="f.id">
        <div x-data="{num: 0}" x-model="f.bar" x-modelable="num">
            Foo Counter Value: <div x-text="num"></div>
            <div @click="num ++">Increase</div>
        </div>
    </template>
</div>