今天要封装一个弹出层,在父组件调用,我要在弹出层里面展示轮播图。
首先子组件的封装
<template>
<el-dialog
v-model="dialogVisible"
:title="title"
width="1000px"
style="height: 80vh"
custom-class="openAnimAbcd"
draggable
>
<div class="change-img" @mouseover="stopChange" @mouseleave="startChange">
<div class="img-container">
<img
:src="img"
alt=""
v-for="(img, index) in props.images"
:key="index"
/>
</div>
<div class="prev" @click="goPrev">《</div>
<div class="next" @click="goNext">》</div>
<ul class="icon">
<li
v-for="(item, index) in images"
:key="index"
@click="changeImg(index)"
ref="indexRef"
>
{
{ index }}
</li>
</ul>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">下次再提醒</el-button>
<el-button @click="dialogVisible = false"> 不再提醒 </el-button>
</span>
</template>
</el-dialog>
</template>
<script setup>
const props = defineProps({
images: {
type: [String, Array],
// default: NaN,
},
title: {
type: String,
default: "",
},
});
const currentIndex = ref(0);
const dialogVisible = ref(false);
const t = ref(null);
// 轮播图自动切换:每隔2秒切换图片
function autoChange() {
t.value = setInterval(() => {
if (currentIndex.value === props.images.length - 1) {
currentIndex.value = 0;
} else {
currentIndex.value++;
}
changeImg(currentIndex.value);
}, 5000);
}
// 切换图片
function changeImg(i) {
document.querySelector(".img-container").style.transform = `translate(${
-900 * i
}px)`;
changeIcomColor(i);
}
// 鼠标移入容器内,停止自动切换图片
function stopChange() {
clearInterval(t.value);
}
// 鼠标移出容器内,继续自动切换图片
function startChange() {
autoChange();
}
// 点击上一张图片
function goPrev() {
if (currentIndex.value === 0) {
currentIndex.value = props.images.length - 1;
} else {
currentIndex.value--;
}
changeImg(currentIndex.value);
}
// 点击下一张图片
function goNext() {
if (currentIndex.value === props.images.length - 1) {
currentIndex.value = 0;
} else {
currentIndex.value++;
}
changeImg(currentIndex.value);
}
// 切换图片,同时执行索引按钮显示红色的函数
// 根据当前图片索引,对应按钮变成红色
function changeIcomColor(i) {
this.$refs.indexRef.forEach((l) => {
l.style.backgroundColor = "";
});
this.$refs.indexRef[i].style.backgroundColor = "red";
}
const open = () => {
dialogVisible.value = true;
};
defineExpose({
open,
});
autoChange();
</script>
<style scoped>
/* 轮播图 */
.change-img {
width: 900px;
height: 65%;
position: relative;
overflow: hidden;
}
.img-container {
/* 图片列表容器宽度:图片高度*图片个数 */
width: 2700px;
height: 450px;
display: flex;
}
.img-container img {
width: 900px;
height: 100%;
}
.change-img .prev,
.change-img .next {
position: absolute;
top: 45%;
width: 20px;
height: 30px;
background: #666;
color: #fff;
line-height: 30px;
cursor: pointer;
}
.change-img .prev {
left: 5px;
text-align: left;
}
.change-img .next {
right: 5px;
text-align: right;
}
.change-img .icon {
position: absolute;
bottom: 10px;
right: 25%;
}
.change-img .icon li {
float: left;
list-style: none;
width: 20px;
height: 20px;
background: #666;
color: #fff;
margin-left: 10px;
text-align: center;
line-height: 20px;
border-radius: 50%;
overflow: hidden;
cursor: pointer;
}
</style>
来具体说一下必须的内容,const props=defineProps({})这个是子组件必需的,相当于vue2 的props,大括号里面写着接收的具体值。另外引入父组件传过来的值是,不需要加.value,但是要加props.xxx
const props=defineProps({
images: {
type: [String, Array],
default: NaN,
},
title: {
type: String,
default: "",
},
});
const dialogVisible = ref(false);是定义弹出层的显示的,和vue2中定义不一样了,vue3是即用即定义。写一个open方法让弹出层出现,需要注意的是,一定要写defineExpose,不然父组件调用不到哦~
const open = () => {
dialogVisible.value = true;
};
defineExpose({
open,
});
接下来开始父组件啦
正常引入之后就可以直接用,不需要注册,
<SlideShow ref="childRef" :images="images" :title="title" /> 使用
const childRef = ref(null); //这个必须是在js中注册的
onMounted(() => {
setTimeout(() => {
//设置定时器
childRef.value.open(); 调用子组件的方法打开弹出层
}, 1000);
});