组件之间传递数据失败

组件之间传递数据失败

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

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

slider.js

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
<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

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
<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

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
<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

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
159
160
161
162
163
164
165
166
167
<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下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号

在线咨询

领取优惠

免费试听

领取大纲

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