最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Access child data from parent with AlpineJS - Stack Overflow

programmeradmin2浏览0评论

AlpineJS' x-data can be nested, so one can access parent data inside a child.

But can one access child data from its parent?

Contrived example:

<script defer src="/[email protected]/dist/cdn.min.js"></script>

<div x-data="{ get nAvailable() { return $el.querySelectorAll('.product.avail').length },
               get nSoldOut()   { return $el.querySelectorAll('.product:not(.avail)').length },
             }">

  <div x-data="{ avail: true }"  class="product" x-bind:class="avail && 'avail'">Product 1</div>
  <div x-data="{ avail: true }"  class="product" x-bind:class="avail && 'avail'">Product 2</div>
  <div x-data="{ avail: true }"  class="product" x-bind:class="avail && 'avail'">Product 3</div>
  <div x-data="{ avail: true }"  class="product" x-bind:class="avail && 'avail'">Product 4</div>
  <div x-data="{ avail: false }" class="product" x-bind:class="avail && 'avail'">Product 5 <span x-text="avail || '(sold out)'"></span></div>

  <br/>
  <div>Available: <span x-text="nAvailable"></span></div>
  <div>Sold out: <span x-text="nSoldOut"></span></div>
</div>

AlpineJS' x-data can be nested, so one can access parent data inside a child.

But can one access child data from its parent?

Contrived example:

<script defer src="https://cdn.jsdelivr/npm/[email protected]/dist/cdn.min.js"></script>

<div x-data="{ get nAvailable() { return $el.querySelectorAll('.product.avail').length },
               get nSoldOut()   { return $el.querySelectorAll('.product:not(.avail)').length },
             }">

  <div x-data="{ avail: true }"  class="product" x-bind:class="avail && 'avail'">Product 1</div>
  <div x-data="{ avail: true }"  class="product" x-bind:class="avail && 'avail'">Product 2</div>
  <div x-data="{ avail: true }"  class="product" x-bind:class="avail && 'avail'">Product 3</div>
  <div x-data="{ avail: true }"  class="product" x-bind:class="avail && 'avail'">Product 4</div>
  <div x-data="{ avail: false }" class="product" x-bind:class="avail && 'avail'">Product 5 <span x-text="avail || '(sold out)'"></span></div>

  <br/>
  <div>Available: <span x-text="nAvailable"></span></div>
  <div>Sold out: <span x-text="nSoldOut"></span></div>
</div>

That works.

But child state is converted to a class (.avail) that the parent can detect by scanning the DOM. In a large page that is slow.

Is it possible to do this without that class?

Share Improve this question asked Mar 14 at 13:25 lonixlonix 21.4k29 gold badges139 silver badges281 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

Data typically flows downward from parent to child components, following a unidirectional data flow pattern. This "props down, events up" approach means that while parents can easily pass data to their children, accessing child state from a parent component usually requires additional mechanisms such as event emission, callbacks, or state lifting.

So, instead of trying to send state up, a better approach would be to maintain the state in the parent so that all child components can update:

<script defer src="https://cdn.jsdelivr/npm/[email protected]/dist/cdn.min.js"></script>

<div x-data="{ 
  products: [
    { id: 1, name: 'Product 1', avail: true },
    { id: 2, name: 'Product 2', avail: true },
    { id: 3, name: 'Product 3', avail: true },
    { id: 4, name: 'Product 4', avail: true },
    { id: 5, name: 'Product 5', avail: false }
  ],
  get nAvailable() { 
    return this.products.filter(p => p.avail).length 
  },
  get nSoldOut() { 
    return this.products.filter(p => !p.avail).length 
  }
}">
  <template x-for="product in products" :key="product.id">
    <div class="product" x-bind:class="product.avail && 'avail'">
      <span x-text="product.name"></span>
      <span x-show="!product.avail"> (sold out)</span>
      <!-- toggle btn -->
      <button x-on:click="product.avail = !product.avail">Toggle Availability</button>
    </div>
  </template>

  <br/>
  <div>Available: <span x-text="nAvailable"></span></div>
  <div>Sold out: <span x-text="nSoldOut"></span></div>
</div>

Here i'm using many alpine features so if in doubt please reefer to the docs

发布评论

评论列表(0)

  1. 暂无评论