DOM 中 div 的响应式重组

Responsive reorganizing of divs in DOM

我的项目使用 Tailwind + Vue 2。我使用 Vue 遍历列表并显示多行。每行开始时都是折叠的,并且可以选择展开。

每个折叠的行中有 3 个可见元素和 1 个隐藏元素 div。展开时,隐藏的 div 变为可见。我希望从每行中取出 2 个可见的 div 元素,并在移动设备上将它们移动到隐藏的下拉列表 div 中。在移动设备上展开时,我希望移动的元素可见。我还希望他们在从移动视图切换到桌面视图时向后移动。

预期行为如下:

这张照片展示了我想要实现的目标。

到目前为止,这些是我的尝试:

  1. CSS / Duplicate - 复制元素。使一个在移动设备上隐藏并在桌面上可见,另一个在移动设备上可见并在桌面上隐藏。虽然这不是一个干净的方法,但它似乎可以工作——直到我使用拨动开关。它失去了功能(我想是因为它被重复了)。
  2. Tailwind/CSS order - 正如实用程序名称所暗示的那样,页面上的顺序确实会改变,但这不会将所需的元素移动到一个隐藏元素;而是将其移动 above/below 隐藏元素。
  3. Vue Teleport - 这适用于 Vue 3,但也有适用于 Vue 2 的软件包,例如 portal-vue。我试过了,由于行正在迭代,所有元素最终都被推到最后一行的展开视图中。我不想使用包。
  4. Javascript - 类似于 teleport/portal:标记 divs “move-from”和“move-to”并找到它们getElementsByClassName。遍历每个 move-medropdown 标签(每个 dropdown 标签有 2 个 move-me 标签)。为 window 添加事件侦听器调整大小并检查页面宽度是否 < 768。问题是,像 teleport/portal,它也会将所有元素填充到最后一行的展开视图中。
if (this.width < 768) {
  const moveMeParent = document.getElementsByClassName('move-me') // there are 20 of these
  const dropdownParent = document.getElementsByClassName('dropdown') // there are 10 of these
  for (let i = 0; i < dropdownParent.length; i++) {
    for (let j = 0; j < 2; j++) {
      dropdownParent[i].appendChild(moveMeParent[0])
    }
  }
}

只是提供一个答案,以便将其标记为已解决:

当您需要在桌面和移动设备之间使用不同的布局(即 html 标记)时,有一些解决方案:

  1. 复制元素,以便它们在 DOM 中同时位于桌面和移动位置。 使用 CSS 通过媒体查询隐藏一个或另一个。

+ 优点:易于设置,非常适合 SSR,不需要 js。
- 缺点:向 DOM 添加了额外的标记,如果执行太多次,可能会减慢页面呈现速度。

That's the solution I advise in OP's case

  1. 使用 javascript 动态渲染组件 在一个地方或另一个地方。在 vue 中,这意味着使用 v-if="isMobile".

+ 优点:避免 DOM 中的重影标记,如解决方案 1.
- 缺点:导致 SSR 闪烁(它在服务器上呈现为桌面或移动设备,然后在水合时更新为另一个布局)。

  1. 在某些情况下,仅使用 css 来移动 您的元素。喜欢 flex-direction: row-reverseorder: n.

+ 优点:易于设置,无需 js。
- 缺点:仅适用于兄弟元素。