不定期更新
目录
1、弹出框/对话框
-
创建一个子组件,在父组件上引用
-
在子组件写布局样式,并在标题和内容区域插入
<slot name="####”></slot>
插槽 -
在父组件定义show变量,默认为false,并定义标题,内容区域内容
-
点击按钮,show为true让组件显示
-
点击不同按钮,让其对应标题,内容区域内容显示
-
点击
X
/取消
/确定
通过子传父,当其触发,让show的值为false,隐藏
//父组件
<template>
<div>
<dlog v-show="show" @clo="clo">
<template #title>
<span>{{ titles }}</span>
</template>
<template #content>
<span>{{ slots }}<button>按钮</button></span>
</template>
</dlog>
<van-button type="primary" @click="open1">btn1</van-button>
<van-button type="primary" @click="open2">btn2</van-button>
</div>
</template>
<script setup>
import dlog from "../components/dlog.vue";
import start from "../components/start.vue";
import { ref } from "vue";
const show = ref(false);
const slots = ref();
const titles = ref();
const open1 = () => {
show.value = true;
titles.value = "点击了btn1";
slots.value = "btn1内容";
};
const open2 = () => {
titles.value = "点击了btn2";
show.value = true;
slots.value = "btn2内容";
};
const clo = () => {
console.log(1);
show.value = false;
};
</script>
<style>
.van-button {
margin-left: 20px;
}
.star {
margin: 20px;
font-size: 20px;
display: flex;
color: #f00;
}
</style>
//子组件
<template>
<div class="dlog">
<div class="box">
<div class="t">
<p><slot name="title"></slot></p>
<span @click="close">X</span>
</div>
<div class="m">
<slot name="content"></slot>
</div>
<div class="f">
<van-button @click="close" plain type="primary">取消</van-button>
<van-button @click="close" type="primary">确定</van-button>
</div>
</div>
</div>
</template>
<script setup>
const s = defineEmits(["clo"]);
const close = () => {
s("clo");
};
</script>
<style lang="scss" scoped>
.dlog {
position: fixed;
top: 0;
z-index: 999;
left: 0;
width: 100vw;
height: 100vh;
background-color: rgba(0, 0, 0, 0.297);
display: flex;
align-items: center;
justify-content: center;
.box {
width: 40%;
background-color: #fff;
border-radius: 20px;
padding: 20px;
box-sizing: border-box;
.t {
width: 100%;
display: flex;
height: 18%;
font-size: 20px;
justify-content: space-between;
align-items: center;
span {
cursor: pointer;
}
}
.m {
padding: 20px 0;
}
.f {
float: right;
.van-button {
margin-left: 20px;
}
}
}
}
</style>
2、星星评分
-
创建一个子组件,在父组件上引用
-
子组件逻辑:写了两个星星图标,第一个循环5,第二个循环一个变量(sum),并让其默认为0
-
利用定位让其重叠
-
点击循环第一个,并传递他的下标,在事件内赋值,让sum为下标+1(index+1),此时当你点击那个就会出现已经点击过的样式
-
但是此时有一个问题,点击之后不能取消选中
-
点击循环的第二个,并传递他的下标,在事件内赋值,让sum为下标+1(index+1)
-
此时能点击,能取消,最后写一个子传父的事件,并把其sum传递到父组件(sum及已选中几颗星),在父组件可进行渲染/判断逻辑处理
//子组件
<template>
<div class="box">
<van-icon
v-for="(item, index) in 5"
@click="click(index)"
:key="item"
name="star"
/>
<div class="ok">
<van-icon
class="h"
@click="h(index)"
name="star"
v-for="(item, index) in sum"
:key="index"
/>
</div>
</div>
</template>
<script setup>
import { ref } from "vue";
const sum = ref(0);
const s = defineEmits(["startnum"]);
const click = (i) => {
console.log(i);
sum.value = i + 1;
console.log("总", sum.value);
s("startnum", sum.value);
};
const h = (i) => {
console.log(i);
sum.value = i + 1;
console.log("总", sum.value);
s("startnum", sum.value);
};
</script>
<style>
.van-icon {
font-size: 20px;
margin-right: 10px;
color: #999;
}
.box {
position: relative;
}
.ok {
position: absolute;
top: 0;
left: 0;
z-index: 999;
}
.h {
color: #ffa940;
}
</style>
3、返回顶部
-
创建一个子组件,在父组件上引用
-
在父组件写一个超出试图的元素内容,滚动时带有滚动条
-
在子组件自定义一个滚动事件,使用
document.documentElement.scrollTop
获取到元素滚动到都,方便图标的显示隐藏const handle = () => { if (document.documentElement.scrollTop > 200) { show.value = true; } else if (document.documentElement.scrollTop < 200) { show.value = false; } // console.log(document.documentElement.scrollTop); };
-
在子组件使用onMounted(()=>{})里面监听滚动事件
onMounted(() => {
window.addEventListener("scroll", handle)
});
5.子传父传递一个事件,在父组件接受,当父组件接收并处罚后,让其滚动高度为0,也可以设置平滑滚动过渡
let timer = setInterval(() => {
let top = document.documentElement.scrollTop
let animation = top / 5
document.documentElement.scrollTop = top - animation
if (top === 0) {
clearInterval(timer)
}
}, 50);
//父组件
<template>
<div id="box">
<h2>返回顶部</h2>
<ul>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
<li>li</li>
</ul>
<gotopcom @bt="bt"></gotopcom>
</div>
</template>
<script setup>
import gotopcom from "../components/gotopcom.vue";
const bt = () => {
// document.documentElement.scrollTop = 0
let timer = setInterval(() => {
let top = document.documentElement.scrollTop
let animation = top / 5
document.documentElement.scrollTop = top - animation
if (top === 0) {
clearInterval(timer)
}
}, 50);
};
</script>
<style lang="scss" scoped>
li {
width: 100%;
text-align: center;
height: 50px;
background-color: palevioletred;
font-size: 20px;
color: #fff;
margin-bottom: 20px;
}
</style>
//子组件
<template>
<div v-show="show">
<img
src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fbpic.136pic.com%2Fkimg%2F481%2F2015%2F3%2F2%2Fe2241f6b6452c99bfe4428302005de86.jpg&refer=http%3A%2F%2Fbpic.136pic.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1665021440&t=0b459cd983097a2d5360d28f7053eea8"
alt="" @click="oncli" />
</div>
</template>
<script setup>
import { ref, defineEmits, onMounted } from "vue";
const show = ref(false);
const s = defineEmits(["bt"]);
const oncli = () => {
s("bt");
};
const handle = () => {
if (document.documentElement.scrollTop > 200) {
show.value = true;
} else if (document.documentElement.scrollTop < 200) {
show.value = false;
}
// console.log(document.documentElement.scrollTop);
};
onMounted(() => {
window.addEventListener("scroll", handle)
});
</script>
<style lang="scss" scoped>
img {
width: 50px;
height: 50px;
position: fixed;
right: 20px;
bottom: 50px;
}
</style>
4、toast
-
创建一个子组件,在父组件上引用
-
在父组件定义一个show状态,默认为false,使用v-show绑定
-
写一个按钮,当点击时,让show为true,显示弹框
-
消失:子传父,传递一个事件,在点击 X 时 在父组件接收传过来的事件,并让show为false
-
停留三秒消失:在子组件的onMounted生命周期里,定义一个 setInterval,设置事件3s,当到达三秒,调用取消按钮事件
//停留3s
onMounted(() => {
setInterval(() => {
hide()
}, 3000);
})
//父组件
<template>
<div>
<button @click="btn">testtost</button>
<toast v-show="show" @hid="hid">测试 toast</toast>
</div>
</template>
<script setup>
import toast from '../components/toast.vue'
import { ref } from 'vue'
const show = ref(false)
const btn = () => {
show.value = true
}
const hid = (e) => {
show.value = e
}
</script>
//子组件
<template>
<div>
<van-icon name="warning" />
<p>
<slot></slot>
</p>
<span @click="hide">X</span>
</div>
</template>
<script setup>
import { onMounted } from 'vue';
const s = defineEmits(['hid'])
const hide = () => {
s('hid', false)
}
onMounted(() => {
setInterval(() => {
hide()
}, 3000);
})
</script>
<style lang="scss" scoped>
div {
background-color: #edf2fc;
color: #909399;
display: flex;
align-items: center;
width: 30%;
margin: 100px auto;
justify-content: space-around;
height: 60px;
border-radius: 10px;
p {
width: 50%;
}
span {
cursor: pointer;
}
}
</style>
5、select下拉
-
创建一个子组件,在父组件上引用
-
在父组件创建一个数组,或者接口上获取一个,传递到子组件
-
子组件接收后,v-for循环渲染选项
-
定义一个属性show,默认为false并为选项绑定v-show
-
点击盒子,让show为true
-
点击选项,传递名字参数,把参数赋值给盒子,使用v-text,之后在将show为false
-
在点击选项时,子组件像父组件传递事件和参数
-
父组件接收后,可获取选中的选项内容
//父组件
<template>
<div>
<selects :item="arr" @gpo="gpo"></selects>
<div>{{item?`已选中${item}`:''}}</div>
</div>
</template>
<script setup>
import selects from '../components/select.vue'
import { ref } from 'vue';
const arr = ref(['黄金糕', '双皮奶', '蚵仔煎', '龙须面', '北京烤鸭'])
const item = ref()
const gpo = (e) => {
item.value = e
console.log(e);
}
</script>
//子组件
<template>
<div class="box">
<!-- <input type="text" @click="open" disabled v-model="inp"> -->
<div class="inp" v-text="inp" @click="open"></div>
<van-icon name="arrow-down" />
<div class="div" v-show="show">
<p v-for="(item,index) in pro.item" :key="index" @click="slec(item)">{{item}}</p>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue';
const pro = defineProps({
item: {
type: Object,
default: [1, 2]
}
})
const s = defineEmits(['gpo'])
const inp = ref()
const show = ref(false)
const slec = (item) => {
inp.value = item
show.value = false
s('gpo', item)
}
const open = () => {
console.log('====================================');
console.log(5);
console.log('====================================');
show.value = true
}
</script>
<style lang="scss" scoped>
.box {
padding: 20px;
box-sizing: border-box;
position: relative;
}
.inp {
width: 200px;
height: 40px;
border: #409eff;
border-radius: 5px;
border: 2px #409eff solid;
line-height: 40px;
}
.van-icon {
position: absolute;
left: 190px;
top: 35px;
}
.div {
width: 200px;
background-color: rgb(226, 226, 226);
p {
background-color: #f5f7fa;
margin-bottom: 10px;
line-height: 40px;
color: #409eff;
height: 40px;
padding-left: 20px;
box-sizing: border-box
}
}
</style>
6、封装tabs
-
在父组件引入子组件
-
父组件的数据内容传递给子组件
-
子组件渲染tabs列表
-
子组件列表内容根据点击tabs的下标来进行显示隐藏内容块
//父组件
<template>
<!-- vue实例外创建 -->
<div>
<tab :lis="lis" :conts="conts" @handel="handel"></tab>
<div>{{indexid?`选择了第${indexid}项`:'默认第一项'}}</div>
</div>
</template>
<!-- 调用 <mycom></mycom> -->
<script setup>
import tab from '../components/tab.vue'
import { ref } from 'vue'
const indexid = ref()
const lis = ref(['第一项', '第二项', '第三项', '第四项'])
const conts = ref(['内容1', '内容2', '内容3', '内容4'])
const handel = (index) => {
indexid.value = index + 1
}
</script>
//子组件
<template>
<div>
<ul>
<li v-for="(item,index) in pro.lis" :class="index===indexi?'bgc':''" @click="changli(index)" :key="index">
{{item}}</li>
</ul>
<div class="cont">
<div>{{!contcent?`${pro.conts[0]}`:`${contcent}`}}</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
const pro = defineProps({
lis: {
type: Object,
default: [1, 2]
},
conts: {
type: Object,
default: [3, 4]
}
})
const contcent = ref()
const indexi = ref(0)
const d = defineEmits(['handel'])
const changli = (index) => {
indexi.value = index
contcent.value = pro.conts[index]
d('handel', index)
}
</script>
<style lang="scss" scoped>
ul {
height: 30px;
margin-top: 20px;
li {
float: left;
list-style-type: none;
width: 100px;
height: 30px;
margin-left: 30px;
line-height: 30px;
text-align: center;
border: 1px #f00 solid;
// &:nth-child(1) {
// background-color: palevioletred;
// color: #fff;
// }
}
}
.cont {
border: 1px #f00 solid;
width: 800px;
height: 500px;
margin-top: 10px;
}
.bgc {
background-color: palevioletred;
color: #fff;
}
</style>
7、轮播图
-
在父组件引入子组件,我们这个总的来说,就是依靠下标来进行循环切换,以及点击切换
-
父组件的数据内容传递给子组件
-
子组件渲染 li按钮,根据传过来的长度,
-
当点击li的某一项时,传递其下标
-
定一个变量,吧这个传过来的arr[index]赋值给上面的图片
-
此时能够点击来进行切换图片
-
自动播放
-
在onMounted使用setinterval设置5000ms时间
onMounted(() => {
setInterval(() => {
indexi.value++ //每过5s让下标++
let ar = ref(pro.imgs[indexi.value])
img.value = ar._value //赋值给上边图片
if (indexi.value >= pro.imgs.length) {
循环,当这个下标大于等于这个总长度时(即:等跳转到最后一项,此时我们应该可以循环播放
indexi.value = 0 ,然后将indexi置为0,
img.value = pro.imgs[0] mg.value置为第一个初始图)
}
s('changea', indexi.value) 调用子传父,告知我们这个是跳转到第几个图片了
}, 5000);
})
//父组件
<template>
<div>
<bannerimg :imgs="imgs" @changea="changea"></bannerimg>
<div>选择{{ind+1}}个</div>
</div>
</template>
<script setup>
import bannerimg from '../components/bannerimg.vue'
import { ref } from 'vue'
const imgs = ref(['../../public/1.jpg', '../../public/2.png', '../../public/3.jpg', '../../public/4.jpg'])
const ind = ref(1)
const changea = (index) => {
ind.value = index
}
</script>
<style lang="scss" scoped>
</style>
//子组件
<template>
<div class="box">
<img :src=img>
<ul>
<li @click="changli(index)" :class="indexi==index?'bgc':''" v-for="(item,index) in pro.imgs.length"
:key="index">{{index}}</li>
</ul>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
const pro = defineProps({
imgs: {
type: Object,
default: [1, 2]
}
})
const s = defineEmits(['changea'])
const img = ref(pro.imgs[0])
const indexi = ref(0)
const changli = (index) => {
indexi.value = index
let ar = ref(pro.imgs[index])
img.value = ar._value
console.log(img.value);
s('changea', index)
}
onMounted(() => {
setInterval(() => {
indexi.value++
let ar = ref(pro.imgs[indexi.value])
img.value = ar._value
if (indexi.value >= pro.imgs.length) {
indexi.value = 0
img.value = pro.imgs[0]
}
s('changea', indexi.value)
}, 5000);
})
</script>
<style lang="scss" scoped>
.box {
border: 10px pink solid;
margin: 0 auto;
width: 500px;
position: relative;
}
img {
height: 280px;
width: 500px;
}
ul {
width: 100%;
position: absolute;
display: flex;
justify-content: center;
bottom: 20px;
li {
cursor: pointer;
letter-spacing: none;
background-color: palevioletred;
width: 20px;
float: left;
margin-left: 20px;
height: 20px;
text-align: center;
line-height: 20px;
border-radius: 20px;
}
}
.bgc {
background-color: pink;
}
</style>