Skip to content

Commit 6f8f38b

Browse files
committed
feature sticky pages
1 parent 51030de commit 6f8f38b

File tree

3 files changed

+271
-7
lines changed

3 files changed

+271
-7
lines changed

src/components/Sticky/index.vue

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<template>
2+
<div
3+
:style="{height: height+'px',zIndex: zIndex}"
4+
>
5+
<div
6+
:class="className"
7+
:style="{top: (isSticky ? stickyTop +'px' : ''),zIndex: zIndex,position: position,width: width,height: height+'px'}"
8+
>
9+
<slot>
10+
<div>sticky</div>
11+
</slot>
12+
</div>
13+
</div>
14+
</template>
15+
16+
<script lang="ts">
17+
import { Component, Prop, Vue } from 'vue-property-decorator'
18+
19+
@Component
20+
export default class Sticky extends Vue {
21+
@Prop({ default: 0 }) private stickyTop!: number
22+
@Prop({ default: 1 }) private zIndex!: number
23+
@Prop({ default: '' }) private className!: string
24+
25+
private active = false
26+
private isSticky = false
27+
private position = ''
28+
private width: string | number = ''
29+
private height: string | number = ''
30+
31+
mounted() {
32+
this.height = this.$el.getBoundingClientRect().height
33+
window.addEventListener('scroll', this.handleScroll)
34+
window.addEventListener('resize', this.handleResize)
35+
}
36+
activated() {
37+
this.handleScroll()
38+
}
39+
destroyed() {
40+
window.removeEventListener('scroll', this.handleScroll)
41+
window.removeEventListener('resize', this.handleResize)
42+
}
43+
private sticky() {
44+
if (this.active) {
45+
return
46+
}
47+
this.position = 'fixed'
48+
this.active = true
49+
this.width = this.width + 'px'
50+
this.isSticky = true
51+
}
52+
private handleReset() {
53+
if (!this.active) {
54+
return
55+
}
56+
this.reset()
57+
}
58+
private reset() {
59+
this.position = ''
60+
this.width = 'auto'
61+
this.active = false
62+
this.isSticky = false
63+
}
64+
private handleScroll() {
65+
const width = this.$el.getBoundingClientRect().width
66+
this.width = width || 'auto'
67+
const offsetTop = this.$el.getBoundingClientRect().top
68+
if (offsetTop < this.stickyTop) {
69+
this.sticky()
70+
return
71+
}
72+
this.handleReset()
73+
}
74+
private handleResize() {
75+
if (this.isSticky) {
76+
this.width = this.$el.getBoundingClientRect().width + 'px'
77+
}
78+
}
79+
}
80+
</script>
81+
<style lang="scss" scoped>
82+
.sub-navbar {
83+
height: 50px;
84+
line-height: 50px;
85+
position: relative;
86+
width: 100%;
87+
text-align: right;
88+
padding-right: 20px;
89+
transition: 600ms ease position;
90+
background: linear-gradient(
91+
90deg,
92+
rgba(32, 182, 249, 1) 0%,
93+
rgba(32, 182, 249, 1) 0%,
94+
rgba(33, 120, 241, 1) 100%,
95+
rgba(33, 120, 241, 1) 100%
96+
);
97+
}
98+
</style>

src/router/modules/components.ts

+7-7
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,16 @@ const componentsRouter: RouteConfig = {
4040
// },
4141
{
4242
path: 'dropzone',
43-
component: () => import(/* webpackChunkName: "Dropzone" */ '@/views/components-demo/dropzone.vue'),
43+
component: () => import(/* webpackChunkName: "dropzone" */ '@/views/components-demo/dropzone.vue'),
4444
name: 'DropzoneDemo',
4545
meta: { title: 'dropzone' }
4646
},
47-
// {
48-
// path: 'sticky',
49-
// component: () => import('@/views/components-demo/sticky'),
50-
// name: 'StickyDemo',
51-
// meta: { title: 'Sticky' }
52-
// },
47+
{
48+
path: 'sticky',
49+
component: () => import(/* webpackChunkName: "sticky" */ '@/views/components-demo/sticky.vue'),
50+
name: 'StickyDemo',
51+
meta: { title: 'sticky' }
52+
},
5353
{
5454
path: 'count-to',
5555
component: () => import(/* webpackChunkName: "CountTo" */ '@/views/components-demo/count-to.vue'),

src/views/components-demo/sticky.vue

+166
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
<template>
2+
<div>
3+
<sticky
4+
:z-index="10"
5+
class-name="sub-navbar"
6+
>
7+
<el-dropdown trigger="click">
8+
<el-button plain>
9+
Platform<i class="el-icon-caret-bottom el-icon--right" />
10+
</el-button>
11+
<el-dropdown-menu
12+
slot="dropdown"
13+
class="no-border"
14+
>
15+
<el-checkbox-group
16+
v-model="platforms"
17+
style="padding: 5px 15px;"
18+
>
19+
<el-checkbox
20+
v-for="item in platformsOptions"
21+
:key="item.key"
22+
:label="item.key"
23+
>
24+
{{ item.name }}
25+
</el-checkbox>
26+
</el-checkbox-group>
27+
</el-dropdown-menu>
28+
</el-dropdown>
29+
30+
<el-dropdown trigger="click">
31+
<el-button plain>
32+
Link<i class="el-icon-caret-bottom el-icon--right" />
33+
</el-button>
34+
<el-dropdown-menu
35+
slot="dropdown"
36+
class="no-padding no-border"
37+
style="width: 300px"
38+
>
39+
<el-input
40+
v-model="url"
41+
placeholder="Please enter the content"
42+
>
43+
<template slot="prepend">
44+
Url
45+
</template>
46+
</el-input>
47+
</el-dropdown-menu>
48+
</el-dropdown>
49+
50+
<div class="time-container">
51+
<el-date-picker
52+
v-model="time"
53+
type="datetime"
54+
format="yyyy-MM-dd HH:mm:ss"
55+
placeholder="Release time"
56+
/>
57+
</div>
58+
59+
<el-button
60+
style="margin-left: 10px;"
61+
type="success"
62+
>
63+
publish
64+
</el-button>
65+
</sticky>
66+
67+
<div class="components-container">
68+
<aside>Sticky header, {{ $t('components.stickyTips') }}</aside>
69+
<div>placeholder</div>
70+
<div>placeholder</div>
71+
<div>placeholder</div>
72+
<div>placeholder</div>
73+
<div>placeholder</div>
74+
<div>placeholder</div>
75+
<div>placeholder</div>
76+
<div>placeholder</div>
77+
<div>placeholder</div>
78+
<div>placeholder</div>
79+
<div>placeholder</div>
80+
<div>placeholder</div>
81+
<div>placeholder</div>
82+
<sticky :sticky-top="200">
83+
<el-button
84+
type="primary"
85+
>
86+
placeholder
87+
</el-button>
88+
</sticky>
89+
<div>placeholder</div>
90+
<div>placeholder</div>
91+
<div>placeholder</div>
92+
<div>placeholder</div>
93+
<div>placeholder</div>
94+
<div>placeholder</div>
95+
<div>placeholder</div>
96+
<div>placeholder</div>
97+
<div>placeholder</div>
98+
<div>placeholder</div>
99+
<div>placeholder</div>
100+
<div>placeholder</div>
101+
<div>placeholder</div>
102+
<div>placeholder</div>
103+
<div>placeholder</div>
104+
<div>placeholder</div>
105+
<div>placeholder</div>
106+
<div>placeholder</div>
107+
<div>placeholder</div>
108+
<div>placeholder</div>
109+
<div>placeholder</div>
110+
<div>placeholder</div>
111+
<div>placeholder</div>
112+
<div>placeholder</div>
113+
<div>placeholder</div>
114+
<div>placeholder</div>
115+
<div>placeholder</div>
116+
<div>placeholder</div>
117+
<div>placeholder</div>
118+
<div>placeholder</div>
119+
<div>placeholder</div>
120+
<div>placeholder</div>
121+
<div>placeholder</div>
122+
<div>placeholder</div>
123+
<div>placeholder</div>
124+
<div>placeholder</div>
125+
<div>placeholder</div>
126+
<div>placeholder</div>
127+
</div>
128+
</div>
129+
</template>
130+
<script lang="ts">
131+
import { Component, Vue } from 'vue-property-decorator'
132+
import Sticky from '@/components/Sticky/index.vue'
133+
134+
@Component({
135+
components: {
136+
Sticky
137+
}
138+
})
139+
export default class StickyDemo extends Vue {
140+
private time = Date
141+
private url = ''
142+
private platforms = ['a-platform']
143+
private platformsOptions = [
144+
{ key: 'a-platform', name: 'platformA' },
145+
{ key: 'b-platform', name: 'platformB' },
146+
{ key: 'c-platform', name: 'platformC' }
147+
]
148+
private pickerOptions = {
149+
disabledDate(time: Date) {
150+
return time.getTime() > Date.now()
151+
}
152+
}
153+
}
154+
</script>
155+
<style lang="scss" scoped>
156+
.components-container div {
157+
margin: 10px;
158+
}
159+
160+
.time-container {
161+
display: inline-block;
162+
}
163+
.el-button--mini {
164+
margin: 5px;
165+
}
166+
</style>

0 commit comments

Comments
 (0)