需求:
点击按钮弹出右侧抽屉,弹出抽屉后点击左侧空白处以及右上角的×进行关闭抽屉。
实现:
组件代码:
<!--Sider.vue-->
<template>
<div
:style="'width:' + browidth + 'px;height:' + broheight + 'px'"
:class="status === false ? 'main-right' : 'main-left'"
@click="closeDrawer"
>
<div
class="drawer"
:class="status === false ? 'drawer-right' : 'drawer-left'"
@click="clickBlank"
>
<div><span @click="closeDrawer"></span></div>
<div>
<ul>
<li v-for="(item, index) in arr" :key="index">
<span v-html="item.icon"></span>
<span>{{ item.text }}</span>
</li>
</ul>
</div>
</div>
</div>
</template>
<script>
import { reactive, toRefs } from "vue";
export default {
props: {
status: {
type: Boolean,
default: false,
},
},
emits: ["update:status"],
setup(props, context) {
const state = reactive({
browidth: window.innerWidth,
broheight: window.innerHeight,
arr: [
{
text: "历史成绩",
icon: "",
},
{
text: "雷达图示",
icon: "",
},
{
text: "趋势图示",
icon: "",
},
{
text: "成绩排名",
icon: "",
},
{
text: "修改密码",
icon: "",
},
],
});
const clickBlank = (event) => {
event.stopPropagation();
};
const closeDrawer = (event) => {
event.stopPropagation();
context.emit("update:status", false);
};
return {
...toRefs(state),
closeDrawer,
clickBlank,
};
},
};
</script>
<style>
@font-face {
font-family: "iconfont"; /* Project id 3062537 */
src: url("//at.alicdn.com/t/font_3062537_lzgm1f4z4wb.woff2?t=1640444212722")
format("woff2"),
url("//at.alicdn.com/t/font_3062537_lzgm1f4z4wb.woff?t=1640444212722")
format("woff"),
url("//at.alicdn.com/t/font_3062537_lzgm1f4z4wb.ttf?t=1640444212722")
format("truetype");
}
.main-right {
position: fixed;
top: 0;
left: 0;
z-index: -1;
}
.main-left {
position: fixed;
top: 0;
left: 0;
background-color: rgba(61, 59, 59, 0.3);
transition: all 1s;
}
.drawer {
width: 250px;
height: 100vh;
background-color: white;
transition: transform 0.3s cubic-bezier(0.7, 0.3, 0.1, 1),
box-shadow 0.3s cubic-bezier(0.7, 0.3, 0.1, 1);
display: flex;
flex-direction: column;
align-items: center;
/* justify-content: space-around; */
}
.drawer > div:nth-child(1) {
height: 6%;
width: 100%;
display: flex;
align-items: center;
justify-content: flex-end;
}
.drawer > div:nth-child(1) > span {
padding: 20px;
font-family: "iconfont";
cursor: pointer;
}
.drawer > div:nth-child(2) {
height: 90%;
width: 100%;
}
.drawer-right {
position: fixed;
top: 0;
right: -250px;
}
.drawer-left {
box-shadow: 4px 4px 15px rgb(61, 59, 59);
position: fixed;
top: 0;
right: -250px;
transform: translateX(-250px);
}
ul {
list-style-type: none;
padding: 0;
margin: 0;
}
li {
height: 50px;
padding: 20px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
border-bottom: #cccccc 1px solid;
}
li:hover {
background-color: antiquewhite;
}
li > span {
font-family: "iconfont";
padding: 10px;
font-size: 1.3rem;
}
</style>
引用:
<!--Home.vue-->
<template>
<div class="home">
<button @click="click">点击</button>
<HelloWorld v-model:status="status" />
</div>
</template>
<script lang="ts">
import HelloWorld from "@/components/Sider.vue"; // @ is an alias to /src
import { reactive, toRefs } from "@vue/reactivity";
// import HelloWorld from '@/components/HelloWorld.vue'; // @ is an alias to /src
export default {
components: {
HelloWorld,
},
setup() {
const state = reactive({
status: false,
});
const click = () => {
state.status = true;
};
return {
...toRefs(state),
click,
};
},
};
</script>
注意:要考虑到事件冒泡,事件冒泡通过event.stopPropagation()进行阻止。
我会将自己平时项目中常见的问题以及笔试面试的知识在CSDN与大家分享,一起进步,加油。
|