vue2 精细级别判断图片页面

逻辑:listdata 获取 他的宽度 来减去当前一行可以容纳多少 image-item 然后在通过剩余的值去平均分给 image-item 剩余的值

javascript 复制代码
<template>
  <div class="Celebimagecharacter">
    <Row>
      <Col :span="12">
        <div class="basic-info-card-title" style="margin-top: 6px">
          已匹配源人物
          <span style="margin-left: 6px; color: rgb(153, 153, 153); font-size: 12px">{{ 0 }}</span>
        </div>
      </Col>
      <Col :span="12" style="text-align: right; padding-right: 32px">
        <Button type="primary" @click="openCelebimagecharacterDlog">全部</Button>
      </Col>
    </Row>
    <Row>
      <Col :span="24">
        <div ref="listdata" class="listdata">
          <div
            class="image-item"
            v-for="(item, index) in [1,2,3,4,5,5,5,4,5,5,5,5,5,5,5,5,5,5]"
            :key="index"
            :style="itemStyle"
          >
            <img
              :src="defaultImage"
              class="image-content"
              alt="人物图片"
              @error="handleImgError"
            />
          </div>
        </div>
      </Col>
    </Row>
    <!-- <CelebimagecharacterDlog
          ref="CelebimagecharacterDlog"
          :is-edited="editModal.relation"
          :base-ps-id="openTagBasePsId"
          :baseOpType="baseOpType"
          :create-source-ps-id="basePs.createSourcePsId"
          @showSourcePsDetail="showSourcePsDetail"
          @update-source-ps-list-total="handleSourcePsListUpdateTotal"
        ></CelebimagecharacterDlog> -->
    <!-- <CelebimagecharacterDlog ref="CelebimagecharacterDlog"></CelebimagecharacterDlog> -->
  </div>
</template>
<script>
import CelebimagecharacterDlog from './pop-up/CelebimagecharacterDlog.vue';
export default {
  components: {
    CelebimagecharacterDlog,
  },
  props: {
    basePsId: {
      type: String,
      default: '',
    },
    isEdited: {
      type: Boolean,
      default: false,
    },
    baseOpType: {
      type: String,
      default: 'NONE',
    },
    createSourcePsId: {
      type: String,
      default: '',
    },
  },
  data() {
    return {
      drawerVisible: false,
      sourcePsList: [],
      defaultImage: require('../../../../images/add.png'),
      // 调整:默认尺寸与最小尺寸保持一致
      itemWidth: 160,
      resizeTimer: null,
    };
  },
  computed: {
    itemStyle() {
      return {
        width: `${this.itemWidth}px`,
        // 保持1:1.5的宽高比(160x240)
        height: `${Math.floor(this.itemWidth * 1.5)}px`,
        // 调整CSS层防护与JS计算逻辑一致
        maxWidth: '200px',
        maxHeight: '300px',
        minWidth: '160px',  // 修改为160,确保最小尺寸
        minHeight: '240px', // 修改为240,确保最小尺寸
      };
    },
  },
  methods: {
    getSourceCodes() {},
    openCelebimagecharacterDlog() {
      this.$refs.CelebimagecharacterDlog.openDrawer();
    },
    handleImgError(e) {
      // 图片加载失败时降级显示,避免裂图
      e.target.style.objectFit = 'contain';
      e.target.style.padding = '20px';
      e.target.style.opacity = '0.5';
    },
    
    // 调整:动态计算item宽度,以160为基准
    calculateItemWidth() {
      const container = this.$refs.listdata;
      if (!container) return;
      
      const containerWidth = container.clientWidth;
      const gap = 12;
      const targetWidth = 160; // 目标宽度
      const safetyMargin = 4;  // 减少安全余量,避免过度压缩
      
      // 计算一行可容纳多少个160px的项
      const estimatedCount = Math.floor((containerWidth + gap) / (targetWidth + gap));
      const itemsPerRow = Math.max(1, estimatedCount);
      
      // 平均分配宽度,但确保不小于160
      const totalGapWidth = (itemsPerRow - 1) * gap;
      const availableWidth = containerWidth - totalGapWidth - safetyMargin;
      const calculatedWidth = Math.floor(availableWidth / itemsPerRow);
      
      // 应用边界限制:最小160,最大200
      this.itemWidth = Math.max(160, Math.min(200, calculatedWidth));
    },
    
    // 新增:防抖处理的resize监听
    handleResize() {
      clearTimeout(this.resizeTimer);
      // 调整:延长防抖时间,减少计算频率
      this.resizeTimer = setTimeout(() => {
        this.calculateItemWidth();
      }, 300);
    },
  },
  mounted() {
    this.getSourceCodes();
    // 新增:初始化时计算宽度
    this.$nextTick(() => {
      this.calculateItemWidth();
    });
    // 新增:监听窗口变化
    window.addEventListener('resize', this.handleResize);
  },
  beforeDestroy() {
    // 新增:清理事件监听
    window.removeEventListener('resize', this.handleResize);
    clearTimeout(this.resizeTimer);
  },
};
</script>
<style lang="less" scoped>
.listdata {
  width: 100%;
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  padding: 8px 0;
}

.image-item {
  border-radius: 4px;
  overflow: hidden;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  transition: all 0.3s ease;
  cursor: pointer;
  background-color: #f5f5f5;
  flex-shrink: 0;
  
  &:hover {
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
    transform: translateY(-2px);
  }
}

.image-content {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
</style>

要稍微减少一点点 留一点点备用空间

相关推荐
汤米粥1 天前
2026年主流前端技术框架
vue·react·elementplus·tailwind css·angular‌·svelte‌·bootstrap‌
codigger1 天前
Vue nextTick 到底在等什么?一篇讲透原理与那些年踩过的坑
程序员·vue·编程·异步更新·#人工智能
咚咚咚小柒2 天前
【前端】LangChain.js学习
前端·javascript·人工智能·typescript·langchain·vue·ai编程
悟道书生4 天前
若依 RBAC 权限控制学习笔记
java·网络·笔记·sql·学习·vue
mewowaBc4 天前
使用Pinia持久化存储实现用户认证系统
vue·pinia·用户认证系统
gc_22995 天前
使用VS Code终端创建Vue项目报错:“npm : 无法加载文件 ...\npm.ps1,因为在此系统上禁止运行脚本”
vue·vs code
小阿鑫5 天前
尤雨溪 : Vue 4 已经在规划中了!
vue·vite·vite+·程序员海军·vue4
离歌漠6 天前
《我用 Tauri 做了一个本地开发工具箱》
rust·typescript·vue
enjoy编程6 天前
playwright学习-I
typescript·vue·nodejs·1024程序员节·playwright
落花看风雪9 天前
从零开始搭建后台系统(vue3+TypeScript+Vite)01
typescript·vue·js