• 【Vue项目复习笔记】详情页的展示


    一、跳转详情页并携带iid

    1、点击商品跳转到详情页
    当我们点击GoodListItem中的每一个item,就跳转到对应的页面。我们首先要做的就是监听GoodsListItem的点击
    在GoodsListItem组件中

     <div class="goods-item" @click="itemClick">
    
    • 1

    在methods中跳转到对应的详情页

     itemClick(){
          //跳转到详情页
        }
    
    • 1
    • 2
    • 3

    我们可以先给详情页配置一个路由
    新建datail文件夹,新建Detail.vue,然后在router的index.js里面配置与路由相关的信息

     itemClick(){
          //跳转到详情页
          this.$router.push('/detail')
        }
    
    • 1
    • 2
    • 3
    • 4

    但是我们在跳转详情页的时候还需要传递一些参数,需要把点击商品的id拿到,然后根据这个id去请求更加详细的数据。这个id也就是下面对应商品的iid
    在这里插入图片描述
    我们用动态路由的方式传递这个iid参数

     itemClick(){
          //跳转到详情页
          // this.$router.push('/detail')
          this.$router.push('/detail/'+this.goodsItem.iid)
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    然后在我们的Detail.vue中就要获取这个iid,根据这个iid去请求数据

     data(){
        return{
          iid:null
          }
          }
    
    • 1
    • 2
    • 3
    • 4
    • 5
     created() {
        //保存传入的id
        this.iid=this.$route.params.iid
        }
    
    • 1
    • 2
    • 3
    • 4

    二、详情页导航栏的封装

    新建childComps,新建DetailNavBar.vue,将我们详情页的导航栏相关内容都写在此处

    <template>
    <div>
      <nav-bar>
        <div slot="left" @click="backClick" class="back">
          <img src="~assets/img/common/back.svg" alt="" >
        </div>
        <div slot="center" class="title">
          <div v-for="(item,index) in titles" class="title-item"
          :class="{active:index===currentIndex}"  @click="titleClick(index)"
          >{{item}}</div>
        </div>
      </nav-bar>
    </div>
    </template>
    
    <script>
    import navBar from '@/components/common/navbar/NavBar';
    export default {
      name: 'DetailNavBar',
      components:{
        navBar
      },
      data(){
        return {
          titles:['商品','参数','评论','推荐'],
          currentIndex:0
        }
      },
      methods:{
        titleClick(index){
          this.currentIndex=index;
          this.$emit('titleClick',index)
        },
        backClick(){
          this.$router.go(-1)
          //go(-1)相当于back
        }
      }
    };
    </script>
    
    <style scoped>
    .title {
      display: flex;
      font-size: 13px;
    }
    
    .title-item {
      flex: 1;
    }
    
    .active {
      color: var(--color-high-text)
    }
    
    .back img {
      margin-top: 12px;
    }
    </style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    将该组件导入到Deatail组件中去

    二、数据的请求以及轮播图的展示

    根据iid去请求数据,在network里新建detail.js

    import { request } from "./request";
    
    export function getDetail(iid) {
      return request({
        url: "/detail",
        params: {
          iid,
        },
      });
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    然后将这个getDetail方法导入到Detail.vue中,我们在created中打印请求到达数据

     created() {
        //保存传入的id
        this.iid = this.$route.params.iid
        //根据拿到的iid请求详细数据
        getDetail(this.iid).then(res => {
          console.log(res);
        })
      },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述
    我们要拿到轮播图的数据,在data()中保存一个 topImages

      data() {
        return {
          iid: null,
          topImages:[]
        }
      },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
     getDetail(this.iid).then(res=>{
          console.log(res);
          this.topImages=res.result.itemInfo.topImages
          }
    
    • 1
    • 2
    • 3
    • 4

    得到下面结果:
    在这里插入图片描述

    新建DetailSwiper.vue,将轮播图相关的存到里面
    先要接收轮播图的数据

     props:{
        topImages:{
          type:Array,
          default(){
            return []
          }
        }
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    然后是在Detail.vue导入DetailSwiper.vue,注册,引用,并传值

      <detail-swiper :top-images="topImages"></detail-swiper>
    
    • 1

    DetailSwiper.vue如下:

    <template>
        <swiper class="detail-swiper">
          <swiper-item v-for="item in topImages">
            <img :src="item" alt="">
          </swiper-item>
        </swiper>
    
    </template>
    
    <script>
    import {Swiper, SwiperItem} from 'components/common/swiper'
    
    export default {
      name: 'DetailSwiper',
      components:{
        Swiper,
        SwiperItem
      },
      props:{
        topImages:{
          type:Array,
          default(){
            return []
          }
        }
      }
    };
    </script>
    
    <style scoped>
    .detail-swiper {
      height: 300px;
      overflow: hidden;
    }
    </style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    结果如下:
    请添加图片描述
    我们会发现一个问题:不管点击哪一个item,轮播图里面的内容没有发生变化
    请添加图片描述
    之所以造成这样的原因是因为我们的数据没有发生变化,也就是我们每次进入详情页,它里面的内容都keep-alive了,但是我们希望它每次进入都要重新获取iid,重新请求新的数据,所以我们在App.vue里面要将Detail排除在外

    <div id="app">
        <keep-alive exclude="Detail">
          <router-view></router-view>
        </keep-alive>
        <main-tab-bar></main-tab-bar>
      </div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    结果如下:
    请添加图片描述
    有点轮播图只显示一张图片,是因为它就只有一张图片显示。

    三、商品基本信息的展示

    这部分数据仍然在通过iid拿到的数据里面
    在这里插入图片描述
    因为需要拿到的数据很多,所以我们需要用一个对象把这些东西做一个整合。然后组件面向这一个对象就可以了。
    在我们的detail.js中

    //导出一个class
    export class Goods {
      constructor(itemInfo, columns, services) {
        this.title = itemInfo.title;
        this.desc = itemInfo.desc;
        this.newPrice = itemInfo.price;
        this.oldPrice = itemInfo.oldPrice;
        this.discount = itemInfo.discountDesc;
        this.columns = columns;
        this.services = services;
        this.realPrice = itemInfo.lowNowPrice;
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    然后导入到Detail.vue中,在data()里面定义一个空的goods对象

    goods:{}
    
    • 1

    然后在我们的

    created() {
        getDetail(this.iid).then(res=>{
          ...
          // 获取商品信息
          this.goods=new Goods(data.itemInfo,data.columns,data.shopInfo.services)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    拿到的都是我们想要的数据
    在这里插入图片描述
    我们在DetailBaseInfo.vue中将这些数据进行展示

    <template>
      <div v-if="Object.keys(goods).length !== 0" class="base-info">
        <div class="info-title">{{goods.title}}</div>
        <div class="info-price">
          <span class="n-price">{{goods.newPrice}}</span>
          <span class="o-price">{{goods.oldPrice}}</span>
          <span v-if="goods.discount" class="discount">{{goods.discount}}</span>
        </div>
        <div class="info-other">
          <span>{{goods.columns[0]}}</span>
          <span>{{goods.columns[1]}}</span>
          <span>{{goods.services[goods.services.length-1].name}}</span>
        </div>
        <div class="info-service">
          <span class="info-service-item" v-for="index in goods.services.length-1" :key="index">
            <img :src="goods.services[index-1].icon">
            <span>{{goods.services[index-1].name}}</span>
          </span>
        </div>
      </div>
    </template>
    
    <script>
    	export default {
    		name: "DetailBaseInfo",
        props: {
    		  goods: {
    		    type: Object,
            default() {
    		      return {}
            }
          }
        }
    	}
    </script>
    
    <style scoped>
      .base-info {
        margin-top: 15px;
        padding: 0 8px;
        color: #999;
        border-bottom: 5px solid #f2f5f8;
      }
    
      .info-title {
        color: #222
      }
    
      .info-price {
        margin-top: 10px;
      }
    
      .info-price .n-price {
        font-size: 24px;
        color: var(--color-high-text);
      }
    
      .info-price .o-price {
        font-size: 13px;
        margin-left: 5px;
        text-decoration: line-through;
      }
    
      .info-price .discount {
        font-size: 12px;
        padding: 2px 5px;
        color: #fff;
        background-color: var(--color-high-text);
        border-radius: 8px;
        margin-left: 5px;
    
        /*让元素上浮一些: 使用相对定位即可*/
        position: relative;
        top: -8px;
      }
    
      .info-other {
        margin-top: 15px;
        line-height: 30px;
        display: flex;
        font-size: 13px;
        border-bottom: 1px solid rgba(100,100,100,.1);
        justify-content: space-between;
      }
    
      .info-service {
        display: flex;
        justify-content: space-between;
        line-height: 60px;
      }
    
      .info-service-item img {
        width: 14px;
        height: 14px;
        position: relative;
        top: 2px;
      }
    
      .info-service-item span {
        font-size: 13px;
        color: #333;
      }
    </style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104

    然后在Detail.vue中将该组件进行导入,注册,并传值

    <detail-base-info :goods="goods"></detail-base-info>
    
    • 1

    其结果如下:
    请添加图片描述
    重点是:对数据的整合。

    四、店铺信息的解析和展示

    在detail.js中也对这些数据进行一个整合

    export class Shop {
      constructor(shopInfo) {
        this.logo = shopInfo.shopLogo;
        this.name = shopInfo.name;
        this.fans = shopInfo.cFans;
        this.sells = shopInfo.cSells;
        this.score = shopInfo.score;
        this.goodsCount = shopInfo.cGoods;
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    然后到Detail.vue中创建商铺信息,在这之前,在data里面新建一个shop信息

    shop:{},
    
    • 1

    然后在created里面的getDetail函数里面,创建店铺信息对象

      this.shop=new Shop(data.shopInfo)
    
    • 1

    在这里插入图片描述
    可以看到我们已经拿到了shop对象了,下面我们就可以封装独立的组件了。新建DetailShopInfo.vue

    <template>
      <div class="shop-info">
        <div class="shop-top">
          <img :src="shop.logo">
          <span class="title">{{shop.name}}</span>
        </div>
        <div class="shop-middle">
          <div class="shop-middle-item shop-middle-left">
            <div class="info-sells">
              <div class="sells-count">
                {{shop.sells | sellCountFilter}}
              </div>
              <div class="sells-text">总销量</div>
            </div>
            <div class="info-goods">
              <div class="goods-count">
                {{shop.goodsCount}}
              </div>
              <div class="goods-text">全部宝贝</div>
            </div>
          </div>
          <div class="shop-middle-item shop-middle-right">
            <table>
              <tr v-for="(item, index) in shop.score" :key="index">
                <td>{{item.name}}</td>
                <td class="score" :class="{'score-better': item.isBetter}">{{item.score}}</td>
                <td class="better" :class="{'better-more': item.isBetter}"><span>{{item.isBetter ? '高':'低'}}</span></td>
              </tr>
            </table>
          </div>
        </div>
        <div class="shop-bottom">
          <div class="enter-shop">进店逛逛</div>
        </div>
      </div>
    </template>
    
    <script>
    	export default {
    		name: "DetailShopInfo",
        props: {
    		  shop: {
    		    type: Object,
            default() {
    		      return {}
            }
          }
        },
        filters: {
          sellCountFilter: function (value) {
            if (value < 10000) return value;
            return (value/10000).toFixed(1) + '万'
          }
        }
    	}
    </script>
    
    <style scoped>
      .shop-info {
        padding: 25px 8px;
        border-bottom: 5px solid #f2f5f8;
      }
    
      .shop-top {
        line-height: 45px;
        /* 让元素垂直中心对齐 */
        display: flex;
        align-items: center;
      }
    
      .shop-top img {
        width: 45px;
        height: 45px;
        border-radius: 50%;
        border: 1px solid rgba(0,0,0,.1);
      }
    
      .shop-top .title {
        margin-left: 10px;
        vertical-align: center;
      }
    
      .shop-middle {
        margin-top: 15px;
        display: flex;
        align-items: center;
      }
    
      .shop-middle-item {
        flex: 1;
      }
    
      .shop-middle-left {
        display: flex;
        justify-content: space-evenly;
        color: #333;
        text-align: center;
        border-right: 1px solid rgba(0,0,0,.1);
      }
    
      .sells-count, .goods-count {
        font-size: 18px;
      }
    
      .sells-text, .goods-text {
        margin-top: 10px;
        font-size: 12px;
      }
    
      .shop-middle-right {
        font-size: 13px;
        color: #333;
      }
    
      .shop-middle-right table {
        width: 120px;
        margin-left: 30px;
      }
    
      .shop-middle-right table td {
        padding: 5px 0;
      }
    
      .shop-middle-right .score {
        color: #5ea732;
      }
    
      .shop-middle-right .score-better {
        color: #f13e3a;
      }
    
      .shop-middle-right .better span {
        background-color: #5ea732;
        color: #fff;
        text-align: center;
      }
    
      .shop-middle-right .better-more span {
        background-color: #f13e3a;
      }
    
      .shop-bottom {
        text-align: center;
        margin-top: 10px;
      }
    
      .enter-shop {
        display: inline-block;
        font-size: 14px;
        background-color: #f2f5f8;
        width: 150px;
        height: 30px;
        text-align: center;
        line-height: 30px;
        border-radius: 10px;
      }
    </style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158

    将该组件在Detail.vue中注册,导入,传值

    <detail-shop-info :shop="shop"></detail-shop-info>
    
    • 1

    结果:
    请添加图片描述
    商铺信息就可以正常展示了。

    五、加入滚动效果Scroll

    在详情页下面的首页导航栏就可以不用显示了。但是为什么它依然在我们的详情页展示呢?因为下面的这个tab-control脱离了标准流,它会覆盖到我们的标准流的上方。为了能让它盖上我们对样式进行调整。
    我们给到detail组件一个id值

    #detail {
      position: relative;
      z-index: 9999;
      background-color: #fff;
      /*height: 100vh;*/
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    但是我们又发现我们的头部导航栏没了,因为我们没有对原生的js做一个定位,这个时候我们直接用scroll局部滚动,头部导航栏就不用再动了。
    首先再Detail.vue中导入scroll,注册,使用

    import Scroll from '@/components/common/scroll/Scroll';
    
    • 1
     <scroll class="content" >
      <detail-swiper :top-images="topImages"></detail-swiper>
      <detail-base-info :goods="goods"></detail-base-info>
      <detail-shop-info :shop="shop"></detail-shop-info>
      </scroll>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    用scroll将滚动区域包裹,并且设置高度

    .content {
      height: calc(100% - 44px);
    }
    
    • 1
    • 2
    • 3

    此时这个100%是相对父元素而言的,所以要给父元素一个高度

    #detail {
      position: relative;
      z-index: 9999;
      background-color: #fff;
      height: 100vh;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    此时会发现头部导航栏并没有固定,所以我们还是为其添加样式

    .detail-nav {
      position: relative;
      z-index: 9;
      background-color: #fff;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    最终的结果:
    请添加图片描述

    六、商品详情数据展示

    商品详情的数据都存放在哪呢?可以看出在detailImage的list里面
    在这里插入图片描述
    我们直接在Detail.vue中的data()里面新建一个数据

    detailInfo:{},
    
    • 1

    在created()里面的 getDetail函数里面保存商品的详情数据

    this.detailInfo=data.detailInfo
    
    • 1

    然后再封装一个独立的组件叫做DetailGoodsInfo.vue

    <template>
      <div v-if="Object.keys(detailInfo).length !== 0" class="goods-info">
        <div class="info-desc clear-fix">
          <div class="start">
          </div>
          <div class="desc">{{detailInfo.desc}}</div>
          <div class="end"></div>
        </div>
        <div class="info-key">{{detailInfo.detailImage[0].key}}</div>
        <div class="info-list">
          <img v-for="(item, index) in detailInfo.detailImage[0].list" :key="index" :src="item" @load="imgLoad" alt="">
        </div>
      </div>
    </template>
    
    <script>
    	export default {
    		name: "DetailGoodsInfo",
        props: {
          detailInfo: {
            type: Object
          }
        },
        data() {
    			return {
    				counter: 0,
            imagesLength: 0
          }
        },
        methods: {
    	    imgLoad() {
            // 判断, 所有的图片都加载完了, 那么进行一次回调就可以了.
            if (++this.counter === this.imagesLength) {
              this.$emit('imageLoad');
            }
    	    }
        },
        //watch用来监听某个属性的变化
        watch: {
    	    detailInfo() {
    	      // 获取图片的个数
    	    	this.imagesLength = this.detailInfo.detailImage[0].list.length
    	    }
        }
    	}
    </script>
    
    <style scoped>
      .goods-info {
        padding: 20px 0;
        border-bottom: 5px solid #f2f5f8;
      }
    
      .info-desc {
        padding: 0 15px;
      }
    
      .info-desc .start, .info-desc .end {
        width: 90px;
        height: 1px;
        background-color: #a3a3a5;
        position: relative;
      }
    
      .info-desc .start {
        float: left;
      }
    
      .info-desc .end {
        float: right;
      }
    
      .info-desc .start::before, .info-desc .end::after {
        content: '';
        position: absolute;
        width: 5px;
        height: 5px;
        background-color: #333;
        bottom: 0;
      }
    
      .info-desc .end::after {
        right: 0;
      }
    
      .info-desc .desc {
        padding: 15px 0;
        font-size: 14px;
      }
    
      .info-key {
        margin: 10px 0 10px 15px;
        color: #333;
        font-size: 15px;
      }
    
      .info-list img {
        width: 100%;
      }
    </style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101

    将该组件导入到Detail.vue中,注册,并传值

     <detail-goods-info :detail-info="detailInfo"></detail-goods-info>
    
    • 1

    结果如下:
    请添加图片描述
    我们会发现详情页滚不动的情况,原因是它在最早的时候better-scroll计算可滚动区域的时候只计算一部分高度,后来我们又加载了很多图片,它并没有把我们的图片算在内。
    所以在我们的DetailGoodsInfo.vue里面对图片的加载进行了监听

       methods: {
    	    imgLoad() {
            // 判断, 所有的图片都加载完了, 那么进行一次回调就可以了.
            if (++this.counter === this.imagesLength) {
              this.$emit('imageLoad');
            }
    	    }
        },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    上面的判断条件的意思是当加载之后的counter和我们图片的长度是相等的,也就是图片加载完了,就向外面发送一次imageLoad事件

    然后在我们的Detail.vue中

    <detail-goods-info :detail-info="detailInfo" @imageLoad="imageLoad"></detail-goods-info>
    
    • 1

    在方法里面

      imageLoad(){
          this.$refs.scroll.scroll.refresh()
        },
    
    • 1
    • 2
    • 3

    七、商品参数信息展示

    在detail.js对参数信息做一个整合

    export class GoodsParam {
      constructor(info, rule) {
        // 注: images可能没有值(某些商品有值, 某些没有值)
        this.image = info.images ? info.images[0] : "";
        this.infos = info.set;
        this.sizes = rule.tables;
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    然后导入Detail.vue中.
    在data()里面定义一个

    paramInfo: {},
    
    • 1

    在到created里面获取参数信息

     this. paramInfo=new GoodsParam(data.itemParams.info,data.itemParams.rule)
    
    • 1

    然后新建DetailParamInfo.vue

    <template>
      <div class="param-info" v-if="Object.keys(paramInfo).length !== 0">
        <table v-for="(table, index) in paramInfo.sizes"
               class="info-size" :key="index">
          <tr v-for="(tr, indey) in table" :key="indey">
            <td v-for="(td, indez) in tr" :key="indez">{{td}}</td>
          </tr>
        </table>
        <table class="info-param">
          <tr v-for="(info, index) in paramInfo.infos">
            <td class="info-param-key">{{info.key}}</td>
            <td class="param-value">{{info.value}}</td>
          </tr>
        </table>
        <div class="info-img" v-if="paramInfo.image.length !== 0">
          <img :src="paramInfo.image" alt="">
        </div>
      </div>
    </template>
    
    <script>
    	export default {
    		name: "DetailParamInfo",
        props: {
    		  paramInfo: {
    		    type: Object,
            default() {
    		      return {}
            }
          }
        }
    	}
    </script>
    
    <style scoped>
      .param-info {
        padding: 20px 15px;
        font-size: 14px;
        border-bottom: 5px solid #f2f5f8;
      }
    
      .param-info table {
        width: 100%;
        border-collapse: collapse;
      }
    
      .param-info table tr {
        height: 42px;
      }
    
      .param-info table tr td {
        border-bottom: 1px solid rgba(100,100,100,.1);
      }
    
      .info-param-key {
        /*当value的数据量比较大的时候, 会挤到key,所以给一个固定的宽度*/
        width: 95px;
      }
    
      .info-param {
        border-top: 1px solid rgba(0,0,0,.1);
      }
    
      .param-value {
        color: #eb4868
      }
    
      .info-img img {
        width: 100%;
      }
    </style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72

    导入到Detail.vue里,注册,传值

    <detail-param-info :param-info="paramInfo"></detail-param-info>
    
    • 1

    最后的结果如下:
    请添加图片描述

  • 相关阅读:
    2.2 银行业务队列简单模拟
    山西电力市场日前价格预测【2023-10-18】
    欢迎来到上班休息区,请交出你的程序员专属表情包!
    基本通信设备
    小程序实现人脸识别功能
    1.定义ddos僵尸网络
    编译libigl笔记
    让图片说话SadTalker
    flex布局(弹性盒子二)
    HTML+CSS大作业:使用html设计一个简单好看的公司官网首页 浮动布局
  • 原文地址:https://blog.csdn.net/qq_40992225/article/details/126229513