【问题标题】:Nested components in Livewire with AlpineJS and @entangle directive使用 AlpineJS 和 @entangle 指令在 Livewire 中嵌套组件
【发布时间】:2021-11-19 01:12:32
【问题描述】:

我目前正在使用 Livewire 和 AlpineJS 开发一个项目。

我必须使用 contenteditable 设置为“true”的 div 来访问和修改我的数据模型。

我想要什么

我想使用 @entangle 在 Livewire 和 Alpine 之间共享状态。

我的代码

我的代码分为两部分。 第一部分依赖于full-Page component,我只是在其中注册了一组$fruits。 第二个是一个包含“表单”的组件,允许我通过 @entangle 和一个将 contenteditable 设置为 true 的 div 访问和修改数据。

<?php

namespace App\Http\Livewire;

use Livewire\Component;

class ListFruit extends Component
{

    protected $listeners = ['addFruit'];

    public array $fruits = [];

    public function mount()
    {
        $this->addFruit();
    }

    public function addFruit()
    {
        $this->fruits[] = $this->makeBlankFruit();
    }



    public function makeBlankFruit(): array
    {
        return [
            'type' => '',
            'color' => ''
        ];
    }

      public function render()
    {
        return view('livewire.list-fruit');
    }
}

views/livewire/list-fruit.blade.php 文件

<div  class="w-full container mx-auto">

    <h3 class="text-2xl font-sembibold">
          Fruits
    </h3>

    <div id="fruits">
       @foreach($fruits as $fruitIndex=> $fruit)

         <livewire:fruit :fruitIndex="$fruitIndex" :fruit="fruit" :wire:key="$fruitIndex" >

       @endforeach
    </div>

</div>

水果成分

<?php

namespace App\Http\Livewire;

use Livewire\Component;

class Fruit extends Component
{

    public array $fruit = [];

    public string $fruitIndex;

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

views/livewire/fruit.blade.php 文件



<div x-data="{type: @entangle('fruit.type'), color: @entangle('fruit.color')}"
    x-init="console.log(type)"
>
    <div>
        <div x-on:blur="type = $event.target.innerHTML" contenteditable="true">{{ $fruit['type'] }}</div>
        <div x-on:blur="color = $event.target.innerHTML" contenteditable="true">{{ $fruit['color'] }}</div>
    </div>

    <div>
        $type @ Livewire: {{ $fruit['type'] }}
        $color @ Livewire: {{ $fruit['color']  }}
    </div>
    <div>
        type @ AlpineJS: <span x-text="type"></span>
        color @ AlpineJS: <span x-text="color"></span>
    </div>
</div>

如果我的主要组件中只有一个具有某些属性的数组,假设:

 public array $fruit = [
  'type' => '',
  'color' => '',
 ];

我可以使用我的fruit.blade.php 访问它们

我也尝试过这样做。

{type: @entangle('fruits.'. $fruitIndex.'.color'), color: @entangle('fruits.'. $fruitIndex.'.type')}

我得到了什么

在我的 AlpineJs 组件中,我读取了一个 [object Object] 代理,并且在修改我的 fruit.color 或 fruit.type 属性时,livewire 部分没有更新。

我不知道为什么。 在我的最后一次尝试中,我尝试将我的水果分成多个子组件,以便我在一个数组上工作。

我正在寻找死胡同,所以提前感谢您的帮助。 狸猫

【问题讨论】:

    标签: laravel laravel-blade laravel-livewire alpine.js


    【解决方案1】:

    我认为你应该简化你的例子。尽管您的实际代码可能比您的(无疑是人为的)水果示例更复杂,但在我看来,这里没有嵌套 Livewire 组件。保留一个 PHP/Livewire 类和一个 Blade 文件要简单得多。然后,不要使用 Blade 来循环使用 @foreach 的数据,而是使用 Alpine 的 x-for。与当前趋势相反,我并不总是认为保持文件大小较小是可取的,如果成本是一层一层地嵌套(越来越难以调试)刀片模板(或 Livewire 组件)。

    不管怎样,除此之外,让我们回到您在这里试图建立的原则,即如何将 PHP/Livewire 数组与 Javascript/Alpine 变量纠缠在一起。

    答案非常简单:您可以将任意复杂的 PHP 数据结构(又名数组)与单个 JavaScript 变量纠缠在一起。如您所料,如果您自己构建了框架,PHP 数组将简单地映射到 JSON 对象。

    首先,设置您复杂的后端数据结构:

    <?php
    
    namespace App\Business\Tbd;
    
    use Livewire\Component;
    
    class StartLw extends Component
    {
        public array $fruits = [];
    
        public function mount() {
    
            $fruit_template = ['apple', 'banana', 'garlic'];
            $fruit_colours  = ['green', 'yellow', 'pink'];
            $health_benefit = [
                'keeps doctor away',
                'the bend keeps you flexible',
                'None.  It\'s not really a fruit, though there is that vampire thing'
            ];
    
            foreach ($fruit_template as $id => $fruit) {
                $this->fruits[$fruit] = [
                    'colour'    => $fruit_colours[$id],
                    'benefit'   => $health_benefit[$id],
                    'bought_by' => array_slice(['Jim', 'John', 'Sue'], 0, $id+1),
                ];
            }
        }
    
        public function render()
        {
            return view('my.livewire.template');
        }
    }
    

    那么下面的 Blade 模板会告诉你所有你需要知道的关于 JavaScript/JSON 对象的内容(它最初是用 PHP 创建的)。

    <div class="container-fluid">
        <div class="row" x-data="{ fruits: @entangle('fruits') }">
            <div class="col-11" id="main">
    
                <p>Type of fruit: <span x-text="typeof fruits"></span></p>
    
                <template x-for="(fruit_info, fruit) in fruits" :key="fruit">
                    <code>
                        Fruit type: <span x-text="fruit"></span><br />
                        Colour: <span x-text="fruit_info.colour"></span><br />
                        Health Superstitions: <span x-text="fruit_info.benefit"></span><br />
                        Bought by:
                        <template x-for="(pers, id) in fruit_info.bought_by" :key="id">
                            <span>
                                <span x-text="id"></span> => <span x-text="pers"></span>,&nbsp;
                            </span>
                        </template>
                        <br />
                        <br />
                    </code>
                </template>
    
            </div>
        </div>
    </div>
    

    如您所见,如果您以足够的灵活性构建 Blade 模板,它们可能会与底层数据结构无关,这(在模块化应用程序中)意味着它们可以反复使用。

    【讨论】:

      猜你喜欢
      • 2021-01-15
      • 1970-01-01
      • 2023-04-06
      • 2021-06-19
      • 2018-08-08
      • 2022-11-17
      • 1970-01-01
      • 2021-08-28
      • 1970-01-01
      相关资源
      最近更新 更多