【问题标题】:AlpineJS x-data overwrittenAlpineJS x 数据被覆盖
【发布时间】:2021-07-27 16:34:03
【问题描述】:

我有以下 HTML 结构:

<div x-data="{selected: 0}">
    <div x-data="{ open: false }"
        @click="open = !open; selected !== 1 ? selected = 1 : selected = 0;"
    >
        test
    </div>
    <div x-data="{ open: false }"
        @click="open = !open; selected !== 2 ? selected = 2 : selected = 0;"
    >
        test
    </div>
</div>

问题是我在 div 子 x-data 中写入后,第一个带有所选 x-data 的 x-data 不再存在。我认为说我覆盖它是正确的。所以问题是,我怎样才能防止这种情况发生?我希望能够保持打开状态并更新所选内容。谢谢

【问题讨论】:

    标签: javascript laravel tailwind-css alpine.js


    【解决方案1】:

    在 Alpine.js 中,您的数据被封装在组件内(这意味着没有父组件会看到它),嵌套组件也不会看到父组件数据。

    目前,此功能不在路线图上。请参阅此 Github 讨论 here。

    事件总线方法

    一种方法是利用 Alpine.js $dispatch 魔术属性并在其他地方使用带有 x-on: 或 @ 别名的事件侦听器。

    <!-- Parent component -->
    <div id="papa" x-data="{isTired: false}" x-on:cry.window="isTired = true">
      <span x-text="'Papa is tired: ' + isTired"></span>
      <!-- New child component scope -->
      <div id="baby" x-data="">
        <button @click="$dispatch('cry')">Make Baby Cry</button>
      </div>
    </div>
    

    CodePen Demo

    这利用了本机浏览器事件bubbling and capturing。

    状态管理存储方法

    如果您熟悉 React 或 Vue.js 等框架,那么您可能熟悉 Redux 或 Vuex 等状态管理库。

    Spruce 是类似 Alpine.js 的精简版本,它的好处是允许您轻松地在组件之间共享数据。

    您可以在其getting started guide 中看到组件之间的通信示例。

    【讨论】:

      【解决方案2】:

      我昨天做了很多研究,是的,AlpineJS 不像 React/Vue/Angular 但我有一个可行的解决方案,这是这样的:

      <div
          x-data="{ count : 0 }"
          x-init="$watch('count', val => $dispatch('new-count', val))"
          x-on:increment="count++"
          x-on:decrement="count--"
      >
          <div>In root component: <span x-text="count"></span></div>
              <div
              x-data="{ count: 0 }"
              x-on:new-count.window="count = $event.detail"
          >
              <div>In nested component <span x-text="count"></span></div>
              <button x-on:click="$dispatch('increment')">Increment</button>
              <button x-on:click="$dispatch('decrement')">Decrement</button>
          </div>
      </div>
      

      使用$dispatch 并在父级中使用$watch 并在其中使用另一个事件名称创建另一个$dispatch。难题的一部分是在window 级别上收听事件。不理想,但工作。我希望它对其他人也有帮助。

      【讨论】:

        【解决方案3】:

        Alpine.js 与 React 或 Vue 不同,不提供任何父子节点 通信模式或原语。 “高山组件”不 从父组件接收任何上下文,每个组件都有自己的 单独和独立的范围,这意味着嵌套不起作用 你会期望来自 Vue/React 甚至 JavaScript (JavaScript 有词法作用域,Alpine 没有)。

        这意味着在 Alpine.js 中没有父子组件 通信仅“兄弟”组件通信。对于兄弟姐妹 通信,这种模式经常在 Caleb 的问题中提出(the Alpine.js 的创建者)和其他贡献者是使用窗口或 文档作为事件总线。

        来源:https://codewithhugo.com/alpinejs-component-communication-event-bus/

        这是他们命名的代码示例:

        <div x-data="{ isOpen: false }">
          <!-- this component can be shown/hidden using a `toggle` event  -->
          <div
            x-show="isOpen"
            x-on:toggle.window="isOpen = !isOpen"
            role="alert"
            >
            <p>This alert is toggled when `toggle` events are dispatched.</p>
            <button @click="isOpen = false">close alert</button>
          </div>
        </div>
        <div x-data="{}">
          <p>The button in this component can toggle the "alert".</p>
          <button @click="$dispatch('toggle')">Toggle alert</button>
        </div>
        <div x-data="{}">
          <p>The button in this component can <strong>also</strong> toggle the "alert".</p>
          <button @click="$dispatch('toggle')">Toggle alert 2</button>
        </div>
        
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2022-10-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-11-17
          • 2011-06-25
          相关资源
          最近更新 更多