组件之间传递数据失败

组件之间传递数据失败

我是在slider组件中获取的页面数据。然后我想传递数据到另外一个子组件detail中。

传递路径slider=>index(父组件)=>detail。但是将数据从index传递给detail时失败了。

slider.js

<template>
  <div class="slider-wrapper">
    <MeLoading v-if="!sliders.length"></MeLoading>
    <me-slider :direction="direction" :loop="loop" :interval="interval" :pagination="pagination" :data="sliders" v-else>
        <swiper-slide v-for="(item,index) in sliders" v-bind:key="index">
            <a href="JavaScript:;" class="slider-link">
                <img :src="item" class="slider-img">
            </a>
        </swiper-slide>
    </me-slider>
  </div>
</template>

<script>
import MeSlider from 'base/slider';
import MeLoading from 'base/loading';
import { swiper,swiperSlide } from "vue-awesome-swiper";
import { getProductDetail } from "api/product.js";

export default {
  name:'productSlider',
  components: {
    MeSlider,
    MeLoading,
    swiper,
    swiperSlide
  },
  data() {
    return {
      direction: 'horizontal',
      loop: true,
      interval: 0,
      pagination: true,
      sliders: []
    }
  },
  props: {
    productId: {
      type: [String,Number],
      default:''
    }
  },
  created() {
    console.log('幻灯片组件接收商品ID成功'+this.productId);
    this.getDetail(this.productId);
  },
  methods: {
    getDetail(id) {
      getProductDetail(id).then(data => {
        console.log(data);
        this.sliders = data.slider;
        this.$emit('loaded', data);//将数据传递给父组件
      })
    }
  }
}
</script>

<style lang="scss" scoped>
  .slider-wrapper {
    // width: 100%;
    height: 360px;
  }
  .slider-link {
    display: block;
  }
  .slider-link,
  .slider-img {
    width: 100%;
    height: 100%;
  }
</style>

index.js

<template>
    <div class="product">
        <header class="g-header-container">
            <product-header/>
        </header>
        <me-scroll>
            <product-slider :productId="productId" @loaded="getDetail"></product-slider>
            <product-detail :productData="productData"></product-detail>
        </me-scroll>
    </div>
</template>
<script>
import productHeader from './header';
import productSlider from './slider';
import productDetail from './detail';
import MeScroll from 'base/scroll';

export default {
    name: 'Product',
    components: {
        productHeader,
        productSlider,
        productDetail,
        MeScroll
    },
    data() {
        return {
            productId: this.$route.params.id,
            productData: null
        }
    },
    methods: {
        getDetail(data) {//接收子组件传递过来的数据
            console.log('父组件接收数据成功');
            console.log(data);
            this.productData = data;
        }
    },
    created() {
        console.log('接收商品id成功:'+this.$route.params.id);
    }
}
</script>
<style lang="scss" scoped>
@import '~assets/scss/mixins';
    .product {
        overflow: hidden;
        position: absolute;
        top:0;
        left: 0;
        z-index: $product-z-index;
        width: 100%;
        height: 100%;
        background-color: $bgc-theme;
    }
</style>

detail.js

<template>
  <div class="detail">
    <div class="detail-price-count">
      <p class="detail-price"><span>¥</span></p>
      <p class="detail-count"></p>
    </div>
    <div class="detail-info">
      <h2 class="detail-title"></h2>
      <div class="detail-infoBox">
        <span class="detail-express"></span>
        <span class="detail-monthCount"></span>
        <span class="detail-site"></span>
      </div>
    </div>
    <div class="detail-comment">
      <h4 class="detail-commentTitle"></h4>
      <div class="detail-keyword">
        <a class="detail"></a>
      </div>
      <div class="detail-userInfo">
        <img class="detail-userIcon" src=""><span class="detail-userName"></span>
      </div>
      <p class="detail-userComment"></p>
      <p class="detail-userTimeType">
        <span class="detail-userTime"></span>
        <span class="detail-userType"></span>
      </p>
    </div>
    <div class="detail-shopInfo">
      <img src="" alt="" class="detail-shopIcon">
      <h4 class="detail-shopTitle"></h4>
      <i class="detail-shopMark"></i>
    </div>
    <p class="detail-service">
      <span class="detail-describe"></span>
      <span class="detail-sellerService"></span>
      <span class="detail-logistics"></span>
    </p>
  </div>
</template>

<script>
export default {
  name:'productDetail',
  props: {
    productData: {
      type:[Array, Object]
    }
  },
  mounted() {
    console.log('detail组件获取到数据!');
    console.log(this.productData);
  }
}
</script>

<style lang="scss" scoped>

</style>

使用$emit将数据从slider传递给index.js成功。但是从index传递给detail又失败了。是因为生命周期函数错误还是什么?获取数据在index获取好还是在slider中获取好啊?

正在回答 回答被采纳积分+1

登陆购买课程后可参与讨论,去登陆

5回答
好帮手慕言 2020-04-03 11:03:32

同学你好,多数情况下,会在父组件获取数据,将数据传递给子组件,老师建议同学使用老师提供的这种方式,没有必要去选择一个舍近求远的发子,另外:可能存在一些其他因素,老师这边测试和同学的效果略有差异,如果同学想使用同学的这种思路实现效果,可以把作业中其他的页面效果完成之后,上传作业,如下:
http://img1.sycdn.imooc.com//climg/5e86a6f709d36a3704900477.jpg

在上传作业时,可以新建一个文本文档,把自己遇到的问题写清楚,有了同学完整的代码,批复作业的老师才可以给出准确的解决方案哦。

祝学习愉快~

好帮手慕言 2020-04-02 19:10:19

同学你好,可以参考下方的思路(同学按照下方红线处和红框中修改即可)
1、index.vue中

http://img1.sycdn.imooc.com//climg/5e85c645098f1d2608090588.jpg

http://img1.sycdn.imooc.com//climg/5e85c7ea09e0b06811520349.jpg

2、detail.vue

http://img1.sycdn.imooc.com//climg/5e85c67c09ab8e0106920148.jpg

祝学习愉快~

  • 提问者 Edward666 #1
    这样的话就是在index.js中获取数据了,不是我这种做法。我这种做法的错误可以解决吗?
    2020-04-02 19:36:27
提问者 Edward666 2020-04-02 17:12:50

和最开始的代码相比主要是detail组件的改变,请老师看一下

detail

<template>
  <div class="detail">
    <div class="detail-price-count">
      <p class="detail-price"><span>¥</span>{{productData.priceText}}</p>
      <p class="detail-count">{{productData.sellCount}}件已售</p>
    </div>
    <div class="detail-info">
      <h2 class="detail-title">{{productData.title}}</h2>
      <div class="detail-infoBox">
        <span class="detail-express">{{productData.postage}}</span>
        <span class="detail-monthCount">月销量{{productData.review.totalCount}}件</span>
        <span class="detail-site">{{productData.from}}</span>
      </div>
    </div>
    <div class="detail-comment">
      <h4 class="detail-commentTitle">商品评价</h4>
      <div class="detail-keyword">
        <a href="JavaScript:;" v-for="(item,index) in productData.review.keywords" :key="index">{{item.word}}</a>
      </div>
      <div class="detail-userInfo">
        <img class="detail-userIcon" :src="productData.review.rateList[0].headPic">
        <span class="detail-userName">{{productData.review.rateList[0].userName}}</span>
      </div>
      <p class="detail-userComment">{{productData.review.rateList[0].content}}</p>
      <p class="detail-userTimeType">
        <span class="detail-userTime">{{productData.review.rateList[0].dateTime}}</span>
        <span class="detail-userType">{{productData.review.rateList[0].skuInfo}}</span>
      </p>
    </div>
    <div class="detail-shopInfo">
      <img :src="productData.seller.shopIcon" class="detail-shopIcon">
      <div class="detail-shopNameMark">
        <h4 class="detail-shopName">{{productData.seller.shopName}}</h4>
        <img class="detail-shopMark" :src="productData.seller.creditLevelIcon">
      </div>
    </div>
    <p class="detail-service">
      <span class="detail-describe">{{productData.seller.evaluates[0].title}}{{productData.seller.evaluates[0].score}}</span>
      <span class="detail-sellerService">{{productData.seller.evaluates[1].title}}{{productData.seller.evaluates[1].score}}</span>
      <span class="detail-logistics">{{productData.seller.evaluates[2].title}}{{productData.seller.evaluates[2].score}}</span>
    </p>
  </div>
</template>

<script>
export default {
  name:'productDetail',
  data() {
    return {
      
    }
  },
  props: {
    productData: {
      type: [Array, Object],
      default:null  
    }
  },
  mounted() {
    setTimeout(() => {
      console.log('detail组件获取到数据!');
      console.log(this.productData);
    },1000)
  }
}
</script>

<style lang="scss" scoped>
  .detail {
    &-price-count {
      background-color: #ef348a;
      height: 45px;
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 0px 10px;
      color: #fff;
    }
    &-price {
      font-size: 14px;
      span {
        font-size: 10px;
      }
    }
    &-count {
      padding: 10px;
      background-color: #cc2e46;
      border-radius: 5px;
    }
    &-info {
      padding: 10px;
      background-color: #fff;
      margin-bottom: 10px;
    }
    &-title {
      margin-bottom: 10px;
      color: #051b28;
    }
    &-infoBox {
      display: flex;
      justify-content: space-between;
      color: #999999;
    }
    //评论
    &-comment {
      background-color: #fff;
      padding: 10px;
      margin-bottom: 10px;
    }
    &-commentTitle {
      margin-bottom: 10px;
    }
    &-keyword {
      a{
        display: inline-block;
        padding: 10px;
        background-color: #ffeeee;
        margin-right: 10px;
        margin-bottom: 10px;
        border-radius: 10px;
      }
    }
    &-userIcon {
      height: 24px;
      width: 24px;
      border-radius: 50%;
    }
    &-userName {
      vertical-align: -5px;
    }
    &-userComment {
      margin: 8px 0;
      color: #051b28;
      line-height: 1.2;
    }
    &-userTimeType {
      color: #999999;
    }
    //商家信息
    &-shopInfo {
      padding: 10px;
      background-color: #fff;
      display: flex;
    }
    &-shopIcon {
      height: 50px;
      width: 50px;
      margin-right: 8px;
    }
    &-shopNameMark {
      display: flex;
      flex-direction: column;
      justify-content: center;
    }
    &-shopMark {
      height: 14px;
      width: 29px;
      margin-top: 8px;
    }
    &-service {
      background-color: #fff;
      padding-bottom: 10px;
      display: flex;
      justify-content: space-around;
    }
  }
</style>

出错信息是这样http://img1.sycdn.imooc.com//climg/5e85ac7409b67e1d07880512.jpg老师你看我的想法对吗?该怎么处理啊?

好帮手慕言 2020-04-02 15:17:28

同学你好,不推荐同学的这种写法,容易出错。建议:在父组件中(index.vue)获取数据,把获取到的数据传递给子组件(slider.vue和detail.vue)。这样写也比较简单。同学可以按照这种思路写一写哦。

祝学习愉快~

  • 提问者 Edward666 #1
    谢谢,我知道了。但是我按照我这种写法除了个错。老师看可以解决吗?好像是因为数据还没有从父组件传递给detail组件,然后detail组件就开始渲染页面出的错。但是页面还是可以展示出来!
    2020-04-02 17:09:38
提问者 Edward666 2020-04-02 13:18:28

急啊急啊急啊

问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师