Vue advanced component packaging-dynamic components & & asynchronous components

Preface

Want to use data to drive the rendering of the component, at this time choose to use dynamic components and implementation

Ideas

Dynamic component

Component has: is attribute, which controls which component to be rendered, that is, when the value of is is the registered value, the component will be rendered in to achieve dynamic component rendering

<component :is="component"></component>
<script>
import child from '@/componets/child'
export default {
    
    
	componets:{
    
    
		child
	},
	data(){
    
    
		component: 'child'
	}
}
</script>

import child from ‘@/componets/child’

But the child needs to be added manually.
At this time, there will be a problem: unneeded components will be loaded. When a component is too large, we don't need to load it, because it will affect our performance.
This is not elegant enough, then we have Is there no way to load different grandchildren components in? Yes, we are going to use asynchronous components

Asynchronous component

In large applications, we may need to divide the application into smaller code blocks and load a module from the server only when needed. To simplify, Vue allows you to define your component as a factory function, which will parse your component definition asynchronously. Vue will trigger the factory function only when the component needs to be rendered, and will cache the result for future re-rendering.

Code

Dynamic component code

Let's write the dynamic components first, the
sub-components

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

Asynchronous component code

importComponent is to load components asynchronously: just
import

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

Sun component

At this time, we only need to create grandchildren under'@/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>

Because the pass value of the grandchildren component, if you use this.&emit to expose to the father, it is very troublesome for the father to expose to the grandfather through this.&emit, so we use
$attrs / $listeners (component pass value) to achieve

Ancestor component

At this point we can use storeData to dynamically render components

<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'
					}
					
				]
			}
		]

Guess you like

Origin blog.csdn.net/weixin_43236062/article/details/114887062