Skip to content

Commit d4a83b2

Browse files
authored
Merge pull request #2 from Liugq5713/feat/sideBar@lgq
Feat/side bar@lgq
2 parents 74ee753 + c77c083 commit d4a83b2

File tree

8 files changed

+450
-22
lines changed

8 files changed

+450
-22
lines changed

desktop.ini

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[.ShellClassInfo]
2+
IconResource=C:\WINDOWS\System32\SHELL32.dll,4
3+
[ViewState]
4+
Mode=
5+
Vid=
6+
FolderType=Generic

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
},
1010
"dependencies": {
1111
"core-js": "^2.6.5",
12-
"element-ui": "^2.7.2",
12+
"element-ui": "^2.8.2",
1313
"vue": "^2.6.10",
1414
"vue-i18n": "^8.11.2",
1515
"vue-router": "^3.0.3",

src/components/Drawer/Drawer.vue

Lines changed: 333 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,333 @@
1+
<template>
2+
<div class="drawer__container" :class="[positionClass,{'drawer__container--show':show}]">
3+
<div class="drawer__container-bg"/>
4+
<div ref="drawer" class="drawer">
5+
<div class="controls__container" ref="controls__container">
6+
<ul
7+
class="controls"
8+
@click="toggleDrawerShowByClick"
9+
@mouseover="toggleDrawerShowByMouseover"
10+
>
11+
<li
12+
v-for="(control,idx) in controlItems"
13+
class="control"
14+
:class="'control-'+idx"
15+
:key="idx"
16+
>
17+
<template v-if="show">
18+
<slot name="control" v-bind:drawer="{show,control}">{{control.hidden}}</slot>
19+
</template>
20+
<template v-else>
21+
<slot name="control" v-bind:drawer="{show,control}">{{control.show}}</slot>
22+
</template>
23+
</li>
24+
</ul>
25+
</div>
26+
<div class="content" v-if="show">
27+
<slot/>
28+
</div>
29+
</div>
30+
</div>
31+
</template>
32+
33+
<script>
34+
import { setTimeout } from "timers";
35+
export default {
36+
props: {
37+
triggerEvent: {
38+
type: String,
39+
default: "click"
40+
},
41+
controls: {
42+
type: [Object, Array],
43+
default: () => {
44+
return {
45+
show: "显示",
46+
hidden: "隐藏"
47+
};
48+
}
49+
},
50+
position: {
51+
type: String,
52+
default: "right",
53+
validator: function(value) {
54+
return ["top", "right", "bottom", "left"].indexOf(value) !== -1;
55+
}
56+
},
57+
controlOffset: {
58+
type: [String, Number],
59+
default: 400
60+
},
61+
contentSize: {
62+
type: [String, Number],
63+
default: 300
64+
},
65+
openDrawer: {
66+
type: Function
67+
}
68+
},
69+
data() {
70+
return {
71+
show: false,
72+
lock: undefined,
73+
positionClass: this.position
74+
};
75+
},
76+
watch: {
77+
show(value) {
78+
if (value && !this.clickNotClose) {
79+
this.addCloseSidebarListener();
80+
}
81+
if (value) {
82+
document.body.classList.add("hidden_scoll_bar");
83+
} else {
84+
document.body.classList.remove("hidden_scoll_bar");
85+
}
86+
87+
this.$nextTick(() => {
88+
this.updateControlLayout();
89+
});
90+
}
91+
},
92+
computed: {
93+
controlItems() {
94+
if (Array.isArray(this.controls)) {
95+
return this.controls;
96+
} else {
97+
return [this.controls];
98+
}
99+
},
100+
lockedShow: {
101+
get() {
102+
return this.show;
103+
},
104+
set(val) {
105+
if (this.lock) {
106+
return;
107+
} else {
108+
this.lock = setTimeout(() => {
109+
this.lock = undefined;
110+
}, 200);
111+
this.show = val;
112+
}
113+
}
114+
},
115+
isHorizontal() {
116+
return ["left", "right"].includes(this.position);
117+
},
118+
isVertical() {
119+
return ["bottom", "top"].includes(this.position);
120+
}
121+
},
122+
mounted() {
123+
let controlOffset = this.controlOffset;
124+
let contentSize = this.contentSize;
125+
if (typeof controlOffset === "number") {
126+
controlOffset = `${controlOffset}px`;
127+
}
128+
if (typeof contentSize === "number") {
129+
contentSize = `${contentSize}px`;
130+
}
131+
if (this.isVertical) {
132+
this.$refs["controls__container"].style["left"] = controlOffset;
133+
this.$refs["drawer"].style.maxHeight = contentSize;
134+
}
135+
if (this.isHorizontal) {
136+
this.$refs["controls__container"].style["top"] = controlOffset;
137+
this.$refs["drawer"].style.maxWidth = contentSize;
138+
}
139+
this.updateControlLayout();
140+
},
141+
destroyed() {
142+
this.removeCloseSidebarListener();
143+
},
144+
methods: {
145+
toggleDrawerShowByClick(evt) {
146+
if (this.triggerEvent !== "click") {
147+
return;
148+
}
149+
this.show ? this.closeDrawerByControl() : this.openDrawerByControl(evt);
150+
},
151+
toggleDrawerShowByMouseover(evt) {
152+
if (this.triggerEvent !== "mouseover") {
153+
return;
154+
}
155+
this.show ? this.closeDrawerByControl() : this.openDrawerByControl(evt);
156+
},
157+
openDrawerByControl(evt) {
158+
const onOpenDraw = this.openDrawer;
159+
if (!onOpenDraw) {
160+
this.lockedShow = true;
161+
return;
162+
}
163+
const target = evt.target;
164+
const currentTarget = evt.currentTarget;
165+
this.lockedShow = onOpenDraw(target, currentTarget);
166+
},
167+
closeDrawerByControl() {
168+
this.lockedShow = false;
169+
},
170+
closeSidebar(evt) {
171+
const parent = evt.target.closest(".drawer");
172+
if (!parent) {
173+
this.show = false;
174+
this.removeCloseSidebarListener();
175+
}
176+
},
177+
addCloseSidebarListener() {
178+
if (this.triggerEvent === "click") {
179+
window.addEventListener("click", this.closeSidebar);
180+
}
181+
if (this.triggerEvent === "mouseover") {
182+
window.addEventListener("mouseover", this.closeSidebar);
183+
}
184+
},
185+
removeCloseSidebarListener() {
186+
if (this.triggerEvent === "click") {
187+
window.removeEventListener("click", this.closeSidebar);
188+
}
189+
if (this.triggerEvent === "mouseover") {
190+
window.removeEventListener("mouseover", this.closeSidebar);
191+
}
192+
},
193+
updateControlLayout() {
194+
const controlsContainerEl = this.$refs["controls__container"];
195+
const rect = controlsContainerEl.getBoundingClientRect();
196+
if (this.position === "top") {
197+
controlsContainerEl.style["bottom"] = `-${rect.height}px`;
198+
}
199+
if (this.position === "bottom") {
200+
controlsContainerEl.style["top"] = `-${rect.height}px`;
201+
}
202+
if (this.position === "right") {
203+
controlsContainerEl.style["left"] = `-${rect.width}px`;
204+
}
205+
if (this.position === "left") {
206+
controlsContainerEl.style["right"] = `-${rect.width}px`;
207+
}
208+
}
209+
}
210+
};
211+
</script>
212+
213+
<style>
214+
.hidden_scoll_bar {
215+
overflow: hidden;
216+
}
217+
</style>
218+
219+
<style scoped>
220+
.drawer__container--show {
221+
transition: all 0.3s cubic-bezier(0.7, 0.3, 0.1, 1);
222+
}
223+
224+
.drawer__container--show .drawer__container-bg {
225+
opacity: 1;
226+
width: 100%;
227+
height: 100%;
228+
z-index: 20001;
229+
}
230+
231+
.drawer__container--show .drawer {
232+
transform: translate(0) !important;
233+
z-index: 40000;
234+
}
235+
.drawer__container-bg {
236+
position: fixed;
237+
top: 0;
238+
left: 0;
239+
opacity: 0;
240+
transition: opacity 0.3s cubic-bezier(0.7, 0.3, 0.1, 1);
241+
background: rgba(0, 0, 0, 0.2);
242+
z-index: -1;
243+
}
244+
245+
.drawer {
246+
position: fixed;
247+
box-shadow: 0px 0px 15px 0px rgba(0, 0, 0, 0.05);
248+
transition: all 0.4s cubic-bezier(0.7, 0.3, 0.1, 1);
249+
background: #fff;
250+
z-index: 20000;
251+
}
252+
.top .drawer {
253+
height: 100%;
254+
width: 100vw;
255+
transform: translate(0, -100%);
256+
top: 0;
257+
left: 0;
258+
}
259+
.bottom .drawer {
260+
height: 100%;
261+
width: 100vw;
262+
transform: translate(0, 100%);
263+
bottom: 0;
264+
left: 0;
265+
}
266+
.left .drawer {
267+
height: 100vh;
268+
width: 100%;
269+
transform: translate(-100%, 0);
270+
top: 0;
271+
left: 0;
272+
}
273+
.right .drawer {
274+
height: 100vh;
275+
width: 100%;
276+
transform: translate(100%, 0);
277+
top: 0;
278+
right: 0;
279+
}
280+
281+
.controls__container {
282+
position: absolute;
283+
box-sizing: border-box;
284+
color: #606266;
285+
cursor: pointer;
286+
}
287+
288+
.controls {
289+
display: flex;
290+
margin: 0;
291+
padding: 0;
292+
list-style: none;
293+
}
294+
295+
.control {
296+
line-height: 1;
297+
white-space: nowrap;
298+
cursor: pointer;
299+
background: #fff;
300+
border: 1px solid #dcdfe6;
301+
-webkit-appearance: none;
302+
text-align: center;
303+
box-sizing: border-box;
304+
outline: none;
305+
margin: 0;
306+
transition: 0.1s;
307+
font-weight: 500;
308+
-moz-user-select: none;
309+
-webkit-user-select: none;
310+
-ms-user-select: none;
311+
padding: 12px 20px;
312+
font-size: 14px;
313+
border-radius: 4px;
314+
}
315+
316+
.top .control,
317+
.bottom .control {
318+
margin-left: 10px;
319+
}
320+
.left .control,
321+
.right .control {
322+
margin-top: 10px;
323+
}
324+
325+
.left .controls,
326+
.right .controls {
327+
flex-direction: column;
328+
}
329+
330+
.content {
331+
padding: 10px;
332+
}
333+
</style>

src/components/Drawer/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import Drawer from './Drawer.vue'
2+
3+
export default Drawer

src/mock/test.vue

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<template>
2+
<el-form :model="defaultFormObj" ref="defaultRef" :rules="rules" label-width="80px">
3+
<el-form-item>
4+
<el-button size="mini" type="primary" @click="defaultMethod('defaultRef')">创建</el-button>
5+
</el-form-item>
6+
</el-form>
7+
</template>
8+
9+
<script>
10+
export default {
11+
data() { return { defaultFormObj:{ }, rules:{ } } }, methods: { defaultMethod(formName) { this.$refs[formName].validate(async (valid) => { if (valid) { await defaultMethod(this.defaultFormObj) this.$message.success('创建成功') } else { console.log('error submit!!'); return false; } }); } } }</script>

0 commit comments

Comments
 (0)