Commit 68a82b73dfc685851f8e08db7580e16447e3eab7
1 parent
cef4684d
Exists in
master
and in
1 other branch
修复校准锚点导航定位跳转准确度
Showing
2 changed files
with
29 additions
and
18 deletions
Show diff stats
examples/views/layout/component.vue
| ... | ... | @@ -19,7 +19,7 @@ |
| 19 | 19 | <router-view></router-view> |
| 20 | 20 | </el-main> |
| 21 | 21 | <el-aside class="layout-aside__preview" width="200px"> |
| 22 | - <a class="anchor" :class="{ 'active': item.hash === currentAnchor }" v-for="(item, index) in anchorList" :key="index" :href="item.hash">{{ item.text }}</a> | |
| 22 | + <a class="anchor" :class="{ 'active': item.hash === currentAnchor }" v-for="(item, index) in anchorList" :key="index" @click="jumpAnchor(item)">{{ item.text }}</a> | |
| 23 | 23 | </el-aside> |
| 24 | 24 | </el-container> |
| 25 | 25 | </el-container> |
| ... | ... | @@ -29,6 +29,8 @@ |
| 29 | 29 | import LayoutHeader from './components/header'; |
| 30 | 30 | import { guides, components } from '@/router/routes'; |
| 31 | 31 | |
| 32 | +const headerHeight = 80; | |
| 33 | + | |
| 32 | 34 | export default { |
| 33 | 35 | name: 'componentLayout', |
| 34 | 36 | components: { LayoutHeader }, |
| ... | ... | @@ -47,21 +49,21 @@ export default { |
| 47 | 49 | }, |
| 48 | 50 | mounted() { |
| 49 | 51 | this.initAnchorList(); |
| 50 | - window.onscroll = ((e) => { | |
| 51 | - if (!this.isBottom()) { | |
| 52 | - for (let index in this.anchorList) { | |
| 53 | - let anchor = this.anchorList[index] || {}; | |
| 54 | - if (window.pageYOffset <= anchor.offsetTop - 65) { | |
| 55 | - this.currentAnchor = (anchor || this.anchorList[0]).hash; | |
| 56 | - break; | |
| 57 | - } | |
| 52 | + window.onscroll = (e) => { | |
| 53 | + let rangeIndex = 0; | |
| 54 | + for (let index in this.anchorList) { | |
| 55 | + let anchor = this.anchorList[index] || {}; | |
| 56 | + const dom = document.querySelector(anchor.hash) || { offsetTop: 0 }; | |
| 57 | + if (window.pageYOffset >= dom.offsetTop - headerHeight) { | |
| 58 | + rangeIndex = index | |
| 58 | 59 | } |
| 59 | 60 | } |
| 60 | - }); | |
| 61 | + this.currentAnchor = this.anchorList[rangeIndex].hash; | |
| 62 | + }; | |
| 61 | 63 | // 初次加载时根据url hash跳转到指定锚点 |
| 62 | 64 | if (this.$route.hash) { |
| 63 | 65 | const anchor = document.querySelector(this.$route.hash); |
| 64 | - document.documentElement.scrollTop = anchor.offsetTop - 65; | |
| 66 | + document.documentElement.scrollTop = anchor.offsetTop - headerHeight; | |
| 65 | 67 | } |
| 66 | 68 | }, |
| 67 | 69 | watch:{ |
| ... | ... | @@ -70,11 +72,6 @@ export default { |
| 70 | 72 | if (to.path !== from.path) { |
| 71 | 73 | this.$nextTick(this.initAnchorList); |
| 72 | 74 | } |
| 73 | - if (!this.isBottom()) { | |
| 74 | - setTimeout(() => { | |
| 75 | - window.scrollBy(0, -65); | |
| 76 | - }, 1); | |
| 77 | - } | |
| 78 | 75 | } |
| 79 | 76 | }, |
| 80 | 77 | computed: { |
| ... | ... | @@ -98,11 +95,19 @@ export default { |
| 98 | 95 | return scrollTop + windowHeight === scrollHeight; |
| 99 | 96 | }, |
| 100 | 97 | initAnchorList() { |
| 98 | + document.documentElement.scrollTop = 0; | |
| 101 | 99 | this.anchorList = []; |
| 102 | 100 | const domList = document.querySelectorAll('.header-anchor'); |
| 103 | 101 | let anchorList = []; |
| 104 | 102 | for (let index in domList) { |
| 105 | 103 | let dom = domList[index] || {}; |
| 104 | + dom.addEventListener('click', e => { | |
| 105 | + // 阻止a标签的默认行为 | |
| 106 | + e = e || window.event; | |
| 107 | + e.preventDefault(); | |
| 108 | + document.documentElement.scrollTop = dom.offsetTop - headerHeight; | |
| 109 | + this.$router.replace({ path: this.$route.path, hash: dom.hash }); | |
| 110 | + }); | |
| 106 | 111 | if (dom.parentNode) { |
| 107 | 112 | const text = `${dom.parentNode.innerHTML}`.replace(/<\/?.*[^>]*>/g, '').trim(); |
| 108 | 113 | if (text === 'API') { |
| ... | ... | @@ -112,7 +117,6 @@ export default { |
| 112 | 117 | text: `${dom.parentNode.innerHTML}`.replace(/<\/?.*[^>]*>/g, '').trim(), |
| 113 | 118 | href: dom.href, |
| 114 | 119 | hash: dom.hash, |
| 115 | - offsetTop: dom.offsetTop, | |
| 116 | 120 | }); |
| 117 | 121 | } |
| 118 | 122 | } |
| ... | ... | @@ -120,6 +124,11 @@ export default { |
| 120 | 124 | this.anchorList = anchorList; |
| 121 | 125 | this.currentAnchor = (anchorList[0] || {}).hash; |
| 122 | 126 | }, |
| 127 | + jumpAnchor({ hash, offsetTop }) { | |
| 128 | + this.$router.replace({ path: this.$route.path, hash }); | |
| 129 | + const dom = document.querySelector(hash) || { offsetTop: 0 }; | |
| 130 | + document.documentElement.scrollTop = dom.offsetTop - headerHeight; | |
| 131 | + }, | |
| 123 | 132 | handleSelect(key) { |
| 124 | 133 | this.$router.push({ name: key }); |
| 125 | 134 | } |
| ... | ... | @@ -181,7 +190,9 @@ export default { |
| 181 | 190 | color: $text; |
| 182 | 191 | transition: all 300ms; |
| 183 | 192 | border-left: 1px solid $border; |
| 193 | + cursor: pointer; | |
| 184 | 194 | } |
| 195 | + .anchor:hover, | |
| 185 | 196 | .active { |
| 186 | 197 | color: $primary; |
| 187 | 198 | border-left: 1px solid $primary; | ... | ... |