<script setup lang=“ts“>+uniapp实现轮播(swiper)效果

效果图1:

代码:

复制代码
<template>
 <view class="carousel-container">
    <!-- 姓名导航栏移至轮播上方 -->
    <view class="name-nav">
        <view
            v-for="(item, index) in personList"
            :key="index"
            :class="{ active: activeIndex === index }"
            @click="activeIndex = index"
        >
            {{ item.name }}
        </view>
    </view>

    <!-- 轮播内容区域 -->
    <swiper class="swiper" :current="activeIndex" :autoplay="true" @change="handleSwiperChange">
        <swiper-item v-for="(item, index) in personList" :key="index">
            <view class="card">
                <image :src="item.avatar" class="avatar" mode="aspectFit" />
                <view class="info">
                    <view class="item">姓名:{{ item.name }}</view>
                    <view class="item">性别:{{ item.gender }}</view>
                    <view class="item">民族:{{ item.nation }}</view>
                    <view class="item">出生:{{ item.birth }}</view>
                    <view class="item">住址:{{ item.address }}</view>
                    <view class="item">身份证号:{{ item.idNo }}</view>
                </view>
                <image :src="item.signature" class="signature" mode="aspectFit" />
            </view>
        </swiper-item>
    </swiper>
</view>
</template>

<script setup lang="ts">
import { ref } from 'vue';

// 轮播数据列表
const personList = [
    {
        name: '韦小宝',
        gender: '男',
        nation: '汉',
        birth: '1654年12月20日',
        address: '北京市东城区景山前街4号紫禁城敬事房',
        idNo: '110101165412200001',
        avatar: '/static/weixiaobao.png', // 替换为实际头像路径
        signature: '/static/signature1.png', // 替换为实际签名路径
    },
    {
        name: '多隆',
        gender: '男',
        nation: '满',
        birth: '1652年05月10日',
        address: '北京市西城区西单大街5号',
        idNo: '110102165205100002',
        avatar: '/static/duolong.png',
        signature: '/static/signature2.png',
    },
    {
        name: '小双',
        gender: '女',
        nation: '汉',
        birth: '1656年08月15日',
        address: '北京市朝阳区建国路8号',
        idNo: '110105165608150003',
        avatar: '/static/xiaoshuang.png',
        signature: '/static/signature3.png',
    },
];

// 激活的索引
const activeIndex = ref(0);

// 轮播切换时同步索引
const handleSwiperChange = (e: { detail: { current: number } }) => {
  activeIndex.value = e.detail.current;
};
</script>

<style scoped>
.carousel-container {
    width: 100%;
    display: flex;
    flex-direction: column;
    gap: 15rpx; /* 姓名栏与轮播的间距 */
    padding: 20rpx;
    box-sizing: border-box;
}

/* 姓名导航栏样式(顶部) */
.name-nav {
    display: flex;
    justify-content: center; /* 姓名居中分布 */
    gap: 30rpx; /* 姓名之间的间距 */
    padding: 10rpx 0;
    background-color: #f5f5f5;
    border-radius: 12rpx;
    width: 100%;
    overflow-x: auto; /* 姓名过多时可横向滚动 */
    white-space: nowrap; /* 防止姓名换行 */
}

.name-nav view {
    font-size: 28rpx;
    padding: 5rpx 15rpx; /* 增加点击区域 */
    color: #666;
    position: relative;
    transition: color 0.3s;
}

/* 选中姓名的高亮样式 */
.name-nav view.active {
    color: #007AFF; /* 主题色高亮 */
    font-weight: bold;
}

/* 可选:添加底部指示线增强选中效果 */
.name-nav view.active::after {
    content: '';
    position: absolute;
    bottom: 0;
    left: 50%;
    transform: translateX(-50%);
    width: 20rpx;
    height: 4rpx;
    background-color: #007AFF;
    border-radius: 2rpx;
}

/* 轮播区域样式 */
.swiper {
    width: 100%;
    height: 500rpx; /* 轮播高度可根据内容调整 */
    border-radius: 12rpx;
    overflow: hidden;
}

.card {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 20rpx;
    background-color: #fff;
    height: 100%;
    box-sizing: border-box;
}

.avatar {
    width: 160rpx;
    height: 160rpx;
    border-radius: 50%;
    margin-bottom: 20rpx;
    border: 2rpx solid #eee;
}

.info {
    width: 100%;
    margin-bottom: 20rpx;
}

.item {
    font-size: 26rpx;
    line-height: 40rpx;
    color: #333;
    padding-left: 10rpx;
}

.signature {
    width: 100%;
    height: 120rpx;
    margin-top: auto; /* 签名区域靠下 */
}
</style>

效果图2:

代码:

复制代码
<template>
  <view class="carousel-container">
    <!-- 轮播内容区域 -->
    <swiper
      class="swiper"
      :current="activeIndex"
      :autoplay="true"
      @change="handleSwiperChange"
    >
      <swiper-item v-for="(item, index) in personList" :key="index">
        <view class="card">
          <image :src="item.avatar" class="avatar" mode="aspectFit" />
          <view class="info">
            <view class="item">姓名:{{ item.name }}</view>
            <view class="item">性别:{{ item.gender }}</view>
            <view class="item">民族:{{ item.nation }}</view>
            <view class="item">出生:{{ item.birth }}</view>
            <view class="item">住址:{{ item.address }}</view>
            <view class="item">身份证号:{{ item.idNo }}</view>
          </view>
         
        </view>
      </swiper-item>
    </swiper>

    <!-- 姓名导航栏(默认展示所有姓名,选中高亮) -->
    <view class="name-nav">
      <view
        v-for="(item, index) in personList"
        :key="index"
        :class="{ active: activeIndex === index }"
        @click="activeIndex = index"
      >
        {{ item.name }}
      </view>
    </view>
  </view>
</template>

<script setup lang="ts">
import { ref } from 'vue';

// 轮播数据列表
const personList = [
  {
    name: '韦小宝',
    gender: '男',
    nation: '汉',
    birth: '1654年12月20日',
    address: '北京市东城区景山前街4号紫禁城敬事房',
    idNo: '110101165412200001',

  },
  {
    name: '多隆',
    gender: '男',
    nation: '满',
    birth: '1652年05月10日',
    address: '北京市西城区西单大街5号',
    idNo: '110102165205100002',
  
  },
  {
    name: '小双',
    gender: '女',
    nation: '汉',
    birth: '1656年08月15日',
    address: '北京市朝阳区建国路8号',
    idNo: '110105165608150003',
  
  },
];

// 激活的索引
const activeIndex = ref(0);

// 轮播切换时同步索引
const handleSwiperChange = (e: { detail: { current: number } }) => {
  activeIndex.value = e.detail.current;
};
</script>

<style scoped>
.carousel-container {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 20rpx;
  padding: 20rpx;
}

.swiper {
  width: 100%;
  height: 500rpx;
}

.card {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 20rpx;
  background-color: #fff;
  border-radius: 12rpx;
  box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
}

.avatar {
  width: 200rpx;
  height: 200rpx;
  border-radius: 50%;
  margin-bottom: 10rpx;
}

.info {
  width: 100%;
  margin-bottom: 20rpx;
}

.item {
  font-size: 28rpx;
  line-height: 40rpx;
  margin-bottom: 8rpx;
}

.signature {
  width: 100%;
  height: 150rpx;
}

.name-nav {
  display: flex;
  justify-content: space-around;
  height: 80rpx;
  line-height: 80rpx;
  background-color: #f5f5f5;
  border-radius: 12rpx;
}

.name-nav view {
  font-size: 28rpx;
  cursor: pointer;
}

.name-nav view.active {
  color: #007AFF;
  font-weight: bold;
  border-bottom: 4rpx solid #007AFF;
}
</style>
相关推荐
雪芽蓝域zzs几秒前
分页组件 + el-config-provider 中文国际化 + 靠右布局
前端·javascript·vue.js
恋猫de小郭4 分钟前
iPhone Duo 适配详解,需要改变的不止是布局模型
前端·flutter·ios
萧行之15 分钟前
Observable Plot 源码深度解析——4 核心抽象逐项学习
前端·学习·数据可视化
今日无bug32 分钟前
为什么大模型回答总是一个字一个字蹦出来?聊聊 SSE 流式输出与 BFF 层的那些事
前端·llm
志尊宝32 分钟前
Vue3 零基础每日笔记(016):v-for 列表渲染——key 的作用与为什么不能用 index
javascript·vue.js·笔记
CIO_Alliance36 分钟前
AI微调系列(1)| 全量微调、LoRA、QLoRA 三种方案怎么选
前端·人工智能·神经网络·机器学习·embedding·企业ai转型
hanbo17C237 分钟前
企业官网能不能看出公司实力?选建站公司前,先看这6条硬标准
运维·服务器·前端
zzzll11111 小时前
LLM 学习第 24 课:Agent Harness
前端·人工智能·学习
Bmob后端云1 小时前
Bmob后端云实战|Python实现SSE流式输出,给备忘录AI加上打字机效果
前端·github
nunumaymax1 小时前
【第九章-React Router 6】
前端·react.js