element-plus/website/pages/component.vue

278 lines
5.9 KiB
Vue
Raw Normal View History

<template>
<el-scrollbar ref="componentScrollBar" class="page-component__scroll">
<div class="page-container page-component">
<el-scrollbar class="page-component__nav">
<side-nav :data="navsData[lang]" :base="`/${lang}/component`" />
</el-scrollbar>
<div class="page-component__content">
<div class="content-wrap">
<router-view class="content" />
</div>
<footer-nav />
</div>
<el-backtop
v-if="showBackToTop"
target=".page-component__scroll .el-scrollbar__wrap"
:right="100"
2021-01-25 11:03:48 +08:00
:bottom="50"
/>
</div>
</el-scrollbar>
</template>
<script lang="ts">
import bus from '../bus'
import navsData from '../nav.config.json'
2020-08-31 15:18:02 +08:00
import { throttle } from 'throttle-debounce'
export default {
data() {
return {
lang: this.$route.meta.lang,
navsData,
scrollTop: 0,
showHeader: true,
componentScrollBar: null,
componentScrollBoxElement: null,
}
},
computed: {
showBackToTop() {
return !this.$route.path.match(/backtop/)
},
},
watch: {
'$route.path'() {
// 触发伪滚动条更新
this.componentScrollBox.scrollTop = 0
this.$nextTick(() => {
this.componentScrollBar.update()
})
},
'$route.hash'() {
this.$nextTick(() => {
this.goAnchor()
})
},
},
created() {
bus.$on('nav-fade', (val) => {
this.navFaded = val
})
},
mounted() {
this.componentScrollBar = this.$refs.componentScrollBar
this.componentScrollBox = this.componentScrollBar.$el.querySelector(
'.el-scrollbar__wrap'
)
this.throttledScrollHandler = throttle(300, this.handleScroll)
this.componentScrollBox.addEventListener(
'scroll',
this.throttledScrollHandler
)
document.body.classList.add('is-component')
2020-12-27 14:19:28 +08:00
this.addContentObserver()
this.goAnchor()
},
unmounted() {
document.body.classList.remove('is-component')
},
beforeUnmount() {
this.componentScrollBox.removeEventListener(
'scroll',
this.throttledScrollHandler
)
2020-12-27 14:19:28 +08:00
this.observer.disconnect()
},
methods: {
2020-12-27 14:19:28 +08:00
addContentObserver() {
this.observer = new MutationObserver((mutationsList) => {
for (const mutation of mutationsList) {
2020-12-27 14:19:28 +08:00
if (mutation.type === 'childList') {
this.renderAnchorHref()
this.goAnchor()
}
}
})
this.observer.observe(document.querySelector('.content-wrap'), {
childList: true,
})
2020-12-27 14:19:28 +08:00
},
renderAnchorHref() {
if (/changelog/g.test(location.href)) return
const anchors = document.querySelectorAll('h2 a,h3 a,h4 a,h5 a')
const basePath = location.href.split('#').splice(0, 2).join('#')
;[].slice.call(anchors).forEach((a) => {
const href = a.getAttribute('href')
2020-12-27 14:19:28 +08:00
if (href.indexOf('#') === 0) {
a.href = basePath + href
}
})
},
goAnchor() {
if (location.href.match(/#/g).length > 1) {
const anchor = location.href.match(/#[^#]+$/g)
if (!anchor) return
const elm = document.querySelector(anchor[0])
if (!elm) return
setTimeout(() => {
this.componentScrollBox.scrollTop = (elm as HTMLElement).offsetTop
}, 50)
}
},
handleScroll() {
const scrollTop = this.componentScrollBox.scrollTop
if (this.showHeader !== this.scrollTop > scrollTop) {
this.showHeader = this.scrollTop > scrollTop
}
if (scrollTop === 0) {
this.showHeader = true
}
if (!this.navFaded) {
bus.$emit('fade-nav')
}
this.scrollTop = scrollTop
},
},
}
</script>
<style lang="scss" scoped>
.page-component__scroll {
height: 100%;
::v-deep(> .el-scrollbar__wrap) {
overflow-x: auto;
}
}
.page-component {
box-sizing: border-box;
height: 100%;
&.page-container {
padding: 40px;
}
.page-component__nav {
width: 240px;
position: absolute;
top: 0;
bottom: 0;
transition: padding-top 0.3s;
::v-deep(> .el-scrollbar__wrap) {
height: 100%;
overflow-x: auto;
}
&.is-extended {
padding-top: 0;
}
}
.side-nav {
height: 100%;
padding-bottom: 50px;
padding-right: 0;
& > ul {
padding-bottom: 50px;
}
}
.page-component__content {
padding-left: 270px;
padding-bottom: 100px;
margin-right: 150px;
box-sizing: border-box;
}
.content-wrap {
min-height: 500px;
}
.content {
::v-deep(>) {
table {
border-collapse: collapse;
width: 100%;
background-color: #fff;
font-size: 14px;
margin-bottom: 45px;
line-height: 1.5em;
strong {
font-weight: normal;
}
td,
th {
border-bottom: 1px solid #dcdfe6;
padding: 15px;
max-width: 250px;
}
th {
text-align: left;
white-space: nowrap;
color: var(--el-text-color-secondary);
font-weight: normal;
}
td {
color: var(--el-text-color-regular);
}
th:first-child,
td:first-child {
padding-left: 10px;
}
}
ul:not(.timeline) {
margin: 10px 0;
padding: 0 0 0 20px;
font-size: 14px;
color: #5e6d82;
line-height: 2em;
}
}
}
}
@media (max-width: 1000px) {
.page-component {
.page-component__content {
margin-right: 0;
}
}
}
@media (max-width: 768px) {
.page-component {
.page-component__nav {
width: 100%;
position: static;
margin-top: 0;
}
.side-nav {
padding-top: 0;
padding-left: 50px;
}
.page-component__content {
padding-left: 10px;
padding-right: 10px;
}
.content {
padding-top: 0;
}
.content > table {
overflow: auto;
display: block;
}
}
}
</style>