子组件怎么获取父组件ajax回来的数据
来源:6-8 首页 - 登录
 
			慕容4022837
2017-04-06

子组件源代码:
<template>
    <div class="slide" @mouseover="clearInv" @mouseout="runInv" ref="slide">
        <div class="slide-img">
            <a class="clearFloat" :href="options.slides[nowIndex].href">
                <transition name="slide-trans">
                    <img v-if="isShow" :src="options.slides[nowIndex].src" ref="slideImg">
                </transition>
                <transition name="slide-trans-old">
                    <img v-if="!isShow" :src="options.slides[nowIndex].src">
                </transition>
            </a>
        </div>
        <div class="title">{{options.slides[0].title}}</div>
        <ul class="page-nub">
            <li @click="goToSlide(prevIndex)"><</li>
            <li v-for="(slide,index) in options.slides" @click="goToSlide(index)" :class="{active: index === nowIndex}">
                {{index + 1}}
 </li>
            <li @click="goToSlide(nextIndex)">></li>
        </ul>
    </div>
</template>
<script type="text/ecmascript-6">
    import Vue from 'vue'
 export default {
        data() {
            return {
                nowIndex: 0,
                isShow: true
 }
        },
        props: {
            options: {
                type: Object,
                default(){
                    return {
                        slides: [],
                        invTime: 1000
 }
                }
            }
        },
        computed: {
            prevIndex () {
                if (this.nowIndex === 0) {
                    return this.options.slides.length - 1
 }
                else {
                    return this.nowIndex - 1
 }
            },
            nextIndex () {
                if (this.nowIndex === this.options.slides.length - 1) {
                    return 0
 }
                else {
                    return this.nowIndex + 1
 }
            }
        },
        watch:{
            /*
            options(){
                this.runInv();
            }
            */
 },
        mounted() {
            console.log(this.options.invTime);   //结果是:undefined     怎么从这个位置获取this.options.invTime?且页面不报错?
 setTimeout(() => {
                console.log(this.options.invTime);   //结果是:2000
 this.setSlideHeight();
                this.runInv();
            },20);
        },
        methods: {
            goToSlide(index){
                this.isShow = false;
                setTimeout(() => {
                    this.isShow = true;
                    this.nowIndex = index;
                }, 10)
            },
            runInv () {
                this.invId = setInterval(() => {
                    this.goToSlide(this.nextIndex)
                }, this.options.invTime)
            },
            clearInv () {
                clearInterval(this.invId)
            },
            setSlideHeight(){
                let slideImg = this.$refs.slideImg;
                let slide = this.$refs.slide;
                slideImg.onload = function () {
                    let imgHeight = slideImg.getBoundingClientRect().height + 'px';
                    slide.style.height = imgHeight;
                };
            }
        }
    };
</script>
<style lang="less" type="text/css" rel="stylesheet/less" scoped>
    .slide {
        width: 100%;
        position: relative;
        overflow: hidden;
        color: #fff;
        .slide-img {
            img {
                position: absolute;
                display: block;
                width: 100%;
            }
            .slide-trans-enter-active {
                transition: all .5s;
            }
            .slide-trans-enter {
                transform: translateX(100%);
            }
            .slide-trans-old-leave-active {
                transition: all .5s;
                transform: translateX(-100%);
            }
        }
        .title {
            position: absolute;
            left: 0;
            bottom: 0;
            background: rgba(0, 0, 0, 0.5);
            width: 100%;
            height: 50px;
            line-height: 50px;
            text-align: left;
            padding-left: 15px;
        }
        .page-nub {
            position: absolute;
            right: 30px;
            bottom: 0;
            height: 50px;
            line-height: 50px;
            li {
                float: left;
                padding: 0 10px;
                &.active {
                    color: #fff700;
                }
            }
        }
    }
</style>
父组件源代码:
<template>
    <div class="index-wrap">
        <div class="index-left">
            <div class="index-left-block">
                <h2>全部产品</h2>
                <template v-for="product in productList">
                    <h3>{{ product.title}}</h3>
                    <ul>
                        <li v-for="item in product.list">
                            <a :href="item.url">{{ item.name }}</a>
                            <span v-if="item.hot" class="hot-tag">HOT</span>
                        </li>
                    </ul>
                    <div v-if="!product.last" class="hr"></div>
                </template>
            </div>
            <div class="index-left-block lastest-news">
                <h2 class="news">最新消息</h2>
                <ul>
                    <li v-for="item in newsList">
                        <a :href="item.url" class="new-item">{{ item.title }}</a>
                    </li>
                </ul>
            </div>
        </div>
        <div class="index-right">
            <slide :options="options" ref="indexSlide"></slide>
            <div class="index-board-list">
                <div class="index-board-item" v-for="(item, index) in boardList"
 :class="[{'line-last' : index % 2 !== 0}]">
                    <div class="index-board-item-inner" :class="['index-board-' + item.id]">
                        <h2>{{ item.title }}</h2>
                        <p>{{ item.description }}</p>
                        <div class="index-board-button">
                            <router-link class="button" :to="{path: 'detail/' + item.toKey}">立即购买</router-link>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>
<script type="text/ecmascript-6">
    import slide from '@/components/slide';
    export default {
        created () {
            this.fetchData();
        },
        data(){
            return {
                options: {},
                boardList: [],
                newsList: [],
                productList: {}
            }
        },
        methods: {
            fetchData () {
                const url = 'api/getIndexData';
                this.$http.post(url).then((res) => {
                    this.newsList = res.data.newsList;
                    this.boardList = res.data.boardList;
                    this.productList = res.data.productList;
                    //this.options = res.data.options;
 this.$set(this,'options',res.data.options);
                    //console.log(this.$refs.indexSlide.options);
                    //this.$refs.indexSlide.al();
 }).catch((err) => {
                    console.log(err)
                })
            }
        },
        components: {
            slide
        }
    };
</script>
<style lang="less" type="text/css" rel="stylesheet/less" scoped>
    .index-wrap {
        width: 100%;
        display: flex;
        .index-left {
            flex: 1 0 0;
            .index-left-block {
                margin: 15px 15px 15px 0;
                background: #fff;
                box-shadow: 0 0 1px #ddd;
                &.lastest-news {
                    max-height: 461px;
                }
                h2 {
                    background: #4fc08d;
                    color: #fff;
                    padding: 10px 15px;
                    margin-bottom: 20px;
                }
                h3 {
                    padding: 0 15px 5px 15px;
                    font-weight: bold;
                    color: #222;
                }
                .hr {
                    margin-bottom: 20px;
                }
                .news {
                    margin-bottom: 5px;
                }
                ul {
                    padding: 10px 15px;
                    li {
                        padding: 5px;
                        .new-item {
                            display: block;
                            text-overflow: ellipsis;
                            white-space: nowrap;
                            overflow: hidden;
                            width: 235px;
                        }
                    }
                    .hot-tag {
                        display: inline-block;
                        font-size: 12px;
                        height: 18px;
                        line-height: 18px;
                        font-weight: 300;
                        background: #ff0000;
                        color: #fff;
                        padding: 0 5px;
                    }
                }
            }
        }
        .index-right {
            flex: 3 0 0;
            margin-top: 15px;
            .index-board-list {
                margin-top: 15px;
                overflow: hidden;
                .index-board-item {
                    float: left;
                    width: 400px;
                    background: #fff;
                    box-shadow: 0 0 1px #ddd;
                    padding: 20px;
                    margin-right: 20px;
                    margin-bottom: 20px;
                    &.line-last {
                        margin-right: 0;
                    }
                    .index-board-item-inner {
                        min-height: 125px;
                        padding-left: 120px;
                        &.index-board-car {
                            background: url(../assets/img/1.png) no-repeat;
                        }
                        &.index-board-loud {
                            background: url(../assets/img/2.png) no-repeat;
                        }
                        &.index-board-earth {
                            background: url(../assets/img/3.png) no-repeat;
                        }
                        &.index-board-hill {
                            background: url(../assets/img/4.png) no-repeat;
                        }
                        h2 {
                            font-size: 18px;
                            font-weight: bold;
                            color: #000;
                            margin-bottom: 15px;
                        }
                        .index-board-button {
                            margin-top: 20px;
                            .button {
                                background: #4fc08d;
                                color: #fff;
                                display: inline-block;
                                padding: 10px 20px;
                                cursor: pointer;
                            }
                        }
                    }
                }
            }
        }
    }
</style>
老师子组件要怎么获取props里面的数据且页面不报错?
2回答
- 
				
				- 首先,子组件里options的default没有生效,因为父组件options是个空对象已经传进去了,只有options这个字段没有的时候,子组件才回去使用default值 
- 你的思路是,所有幻灯片的options都来自服务端,ajax异步请求,这其实并不合理,比如间隔时间invTime,这显然是前端控制的事情,修改起来也更加灵活,这是其一,其二,options,数据列表等不同的数据从同一个接口返回,也不合理,前端压力很大,结构不清晰,所以我觉得有必要改成invTime就是父组件的一个同步选项,不需要异步获取。 
- 顺着你的逻辑来说,就是invTime是异步获取的,子组件只有拿到invTime才能runInv。我刚才试了一下watch,好像对props不生效,那么我能想到的办法,如果不用vuex的话就是eventBus了,我在最后一刻有讲到。 
 两个组件都引入 import { eventBus } from '../../eventBus'异步拿到invTime后,发一个全局事件, 这里也可以把invtime设计成另外一个接口,在子组件里调用 created: function () { this.$http.get('api/getNewsList') .then((res) => { this.newsList = res.data // this.options.dt = res.data // this.invTime = 5000 eventBus.$emit('afterGetInvTime', res.data.invTime) }, (err) => { console.log(err) }) },子组件监听这个事件,回调里调用runInv mounted () { eventBus.$on('afterGetInvTime', (invTime) => { this.inv = invTime this.runInv() }) }*正如代码里写的一样,通过eventBus 都不需要保存invTime,完全作为事件的参数从父组件传到子组件 152017-04-10
- 
				  慕容4022837 提问者 2017-04-07 谢谢老师的回答,就算invTime不从后台异步获取! 图片信息应该是从后台异步获取的吧! 我这里涉及到一个获取图片高度的问题!只有拿到图片的高度才好设置轮播图的高度!因为图片是position: absolute;脱离了文档流没有高度!所以需要拿到图片高度来设置轮播图最外层高度!要不然看不到轮播图!这个要怎么处理?也是得用到vuex或者eventBus吗?后面的vuex还没看!是在不行那就用vuex来实现吧! 其实好多组件的数据都是后台获取的!比如那个下拉选框组件!里面的数据基本是从后端过来的! 00
相似问题
