You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular12中同级组件如何互相监听事件?预订应用结果块展开收起怎么实现

预订应用搜索结果块联动展开功能实现方案

核心逻辑

  • 全局仅维护一个activeBlockId状态变量,用于存储当前处于展开状态的搜索结果块的唯一标识,无展开块时取值为null
  • 每个搜索结果块的乘客数量输入框绑定触发事件,事件触发时校验乘客数量符合要求后,直接将activeBlockId更新为当前块的唯一ID,其余块通过判断自身ID与activeBlockId是否匹配,自动控制表单的显示隐藏
  • 可额外拓展点击页面非结果块区域时重置activeBlockId为null的逻辑,实现点击空白收起所有表单的交互

代码实现示例

原生JavaScript实现

// 预设类名规则:搜索结果块统一使用search-result-block类,每个块添加data-block-id自定义属性存储唯一ID
// 乘客输入框使用passenger-count-input类,用户信息表单使用user-info-form类,隐藏样式使用hidden类
const resultBlocks = document.querySelectorAll('.search-result-block')
let activeBlockId = null

resultBlocks.forEach(block => {
  const passengerInput = block.querySelector('.passenger-count-input')
  const userForm = block.querySelector('.user-info-form')
  
  passengerInput.addEventListener('input', () => {
    const currentBlockId = block.dataset.blockId
    const passengerCount = parseInt(passengerInput.value) || 0
    // 乘客数不符合要求时收起当前块
    if (passengerCount < 1) {
      userForm.classList.add('hidden')
      activeBlockId = activeBlockId === currentBlockId ? null : activeBlockId
      return
    }
    // 先收起之前处于展开状态的块
    if (activeBlockId && activeBlockId !== currentBlockId) {
      document.querySelector(`[data-block-id="${activeBlockId}"] .user-info-form`).classList.add('hidden')
    }
    // 展开当前块
    userForm.classList.remove('hidden')
    activeBlockId = currentBlockId
  })
})

配套CSS:

.hidden {
  display: none;
}
/* 可选:添加展开收起过渡动画 */
.user-info-form {
  transition: all 0.3s ease;
  overflow: hidden;
}

React 实现

import { useState } from 'react'

function SearchResultList({ resultList }) {
  const [activeBlockId, setActiveBlockId] = useState(null)

  return (
    <div className="result-list">
      {resultList.map(item => (
        <div key={item.id} className="search-result-block">
          {/* 搜索结果基础展示内容 */}
          <input
            type="number"
            min={1}
            placeholder="请输入乘客数量"
            onChange={(e) => {
              const count = parseInt(e.target.value) || 0
              setActiveBlockId(count >= 1 ? item.id : (prev => prev === item.id ? null : prev))
            }}
          />
          {/* 仅当前块ID匹配激活ID时展示表单 */}
          {activeBlockId === item.id && (
            <form className="user-info-form">
              {/* 乘客信息表单字段 */}
            </form>
          )}
        </div>
      ))}
    </div>
  )
}

Vue 3 实现

<template>
  <div class="result-list">
    <div 
      v-for="item in resultList" 
      :key="item.id" 
      class="search-result-block"
    >
      <!-- 搜索结果基础展示内容 -->
      <input
        type="number"
        min="1"
        placeholder="请输入乘客数量"
        @input="handlePassengerInput(item.id, $event)"
      />
      <form 
        class="user-info-form"
        v-show="activeBlockId === item.id"
      >
        <!-- 乘客信息表单字段 -->
      </form>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const resultList = ref([]) // 接口返回的搜索结果数组
const activeBlockId = ref(null)

const handlePassengerInput = (blockId, e) => {
  const count = parseInt(e.target.value) || 0
  if (count >= 1) {
    activeBlockId.value = blockId
  } else {
    activeBlockId.value = activeBlockId.value === blockId ? null : activeBlockId.value
  }
}
</script>

交互优化建议

  • 若用户在已展开的表单中输入了内容,切换收起前可增加二次确认提示,避免用户输入内容意外丢失
  • 给表单的展开收起添加CSS过渡动画,提升操作流畅感
  • 新增点击页面空白区域自动重置activeBlockId的逻辑,适配用户常规操作习惯

内容的提问来源于stack exchange,提问作者Takura Chimoyo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 05:30:01