Vue 动态组件&&异步组件的用法和理解

动态组件

vue中的component有:is属性,它就是控制渲染哪个组件,当is的值为注册的值,就会把对应的组件渲染出来,达到条件判断的动态组件渲染的效果

<component :is="iscomponent"></component>
import child from '@/componets/child'
import childOne from '@/componets/childOne'
export default {
    componets:{
        child,
             childOne 
    },
    data(){
        iscomponent: 'child'     //当iscomponent="child"就显示child组件,当iscomponent="childOne "就像是childOne组件,可以动态改变iscomponent的值就实现动态组件的加载
    }
}
</script>

代码

动态组件代码

我们先写出动态组件出来
子组件

<template>
    <div class="m-detail">
        <component :is="item.component" v-for="(item, index) in detailArr" :key="index" :data="item.data"
        v-bind="$attrs" v-on="$listeners">
        </component>
    </div>
</template>

<script>
import importComponent from '@/utils/importComponent'
export default {
    title: 'store',
    props: {
        detailData: {
            type: Array,
            default() {
                return []
            }
        }
    },
    data() {
        return {}
    },
    computed: {
        detailArr() {
            const arr = []
            for (var i = 0; i < this.detailData.length; i++) {
                (i => {
                    const item = this.detailData[i]
                    var _type = this.detailData[i].type
                    const detailMap = {
                        BlockList: {
                            products:item.products
                        },
                        FloatList: {
                            products:item.products
                        }
                    }
                    const obj = {
                        component: importComponent(`components/Store/${_type}.vue`),
                        data: {
                            ...detailMap[_type]
                        }
                    }
                    arr.push(obj)
                })(i)
            }
            return arr
        }
    }
}
</script>

<style lang="less" scoped>
.m-detail {
    min-height: 400px;
}
</style>

异步组件代码

importComponent是一个把我们想要的组件动态出来:

export default (path, callback) => {
    return resolve => require([`@/${path}`], Module => {
        callback && callback(Module)
        resolve(Module)
    })
}

孙组件

此时我们只需要在‘@/components/Store/’下面建立孙组件;

<template>
    <view class="bank-card">
        <view class="item text-center">
            <text class="text-gray cuIcon-roundleftfill-copy roundleftfil" @click="hanldSwiper('left')"></text>
            <text class="text-gray cuIcon-roundrightfill roundrightfill" @click="hanldSwiper('right')"></text>
            <view class="item-title font-weight">图片</view>
            <swiper class="swiper" :current="current">
                <swiper-item v-for="(item,index) in data.products" :key="index">
                     <view class="swiper-item uni-bg-red" :style="`background-image: url(${item.productPic});`"></view>
                </swiper-item>
            </swiper>
            <view>
                <text class="spot">123</text>
                <text class="spot">123</text>
                <text class="spot">123</text>
            </view>
            <view class="bg-grey flex justify-between footer">
                <view class="text-center">个人邀请</view>
                <text class="line"></text>
                <view @click="posterShare()">海报分享</view>
            </view>
        </view>
    </view>
</template>

<script>
export default{
    name: 'BankCard',
    props: {
        data: {
            type: Object
        }
    },
    data(){
        return{
            current:0
        }
    },
    methods: {
        hanldSwiper(item){
            if(item == 'left' && this.current > 0){
                this.current -= 1
                return
            }
            if(item == 'right' && this.current < this.data.products.length-1){
                this.current += 1
                return
            }
        },
        posterShare(){
            this.$emit('toShare','val')
        }
    }
}
</script>

<style lang="less">
.bank-card{
    .nav{
        margin: 30upx 0;
        .title{
            font-weight: 700;
            font-size: 32upx;
        }
    }
    .item{
        width: 100%;
        height: 500upx;
        border: 1px solid #CCCCCC;
        display: inline-block;
        margin-right: 30upx;
        border-radius: 30upx;
        padding: 30upx 0;
        position: relative;
        overflow: hidden;
        .item-title{
            margin-bottom: 30upx;
            color:#000000
        }
        .roundleftfil{
            position: absolute;
            left:80upx;
            top:180upx;
            font-size: 50upx;
        }
        .roundrightfill{
            position: absolute;
            right:80upx;
            top:180upx;
            font-size: 50upx;
        }
        .footer{
            width: 100%;
            height: 60upx;
            line-height: 60upx;
            position: absolute;
            bottom: 0;
            >view {
                width: 49%;
            }
        }
    }
    .spot{
        margin:0 10upx;
        vertical-align: center;
    }
}
.swiper{
    width: 340upx;
    height: 240upx;
    margin:auto;
    border-radius: 30upx;
    overflow: hidden;
    .swiper-item{
        width: 100%;
        height: 100%;
        background-size: cover;
        background-repeat: round;
    }
}
</style>

因为祖孙 组件的传值,如果使用this.&emit向父亲暴露,父亲再通过this.$emit向爷爷暴露是很麻烦的,因此我们使用$attrs $listeners

<Store :detailData="storeData" @toShare='toShare'></Store>

this.storeData = [
            {
                type: 'BlockList',
                products:[
                    {
                        newId:'13',         productPic:'https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=229065980,2895464780&fm=26&gp=0.jpg'
                    },
                    {
                        newId:'14',
                        productPic:'https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=2350817201,1137116540&fm=26&gp=0.jpg'
                    },
                    {
                        newId:'15',                 productPic:'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.zcool.cn%2Fcommunity%2F031156f5aeb21a8a801207fa1bc9eac.jpg&refer=http%3A%2F%2Fimg.zcool.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1618385640&t=bc51aaaa2dc72dd8e565807935529732'
                    }
                    
                ]
            }
        ]

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,137评论 6 511
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,824评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,465评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,131评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,140评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,895评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,535评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,435评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,952评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,081评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,210评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,896评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,552评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,089评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,198评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,531评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,209评论 2 357

推荐阅读更多精彩内容