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,7 +19,7 @@ | ||
| 19 | <router-view></router-view> | 19 | <router-view></router-view> |
| 20 | </el-main> | 20 | </el-main> |
| 21 | <el-aside class="layout-aside__preview" width="200px"> | 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 | </el-aside> | 23 | </el-aside> |
| 24 | </el-container> | 24 | </el-container> |
| 25 | </el-container> | 25 | </el-container> |
| @@ -29,6 +29,8 @@ | @@ -29,6 +29,8 @@ | ||
| 29 | import LayoutHeader from './components/header'; | 29 | import LayoutHeader from './components/header'; |
| 30 | import { guides, components } from '@/router/routes'; | 30 | import { guides, components } from '@/router/routes'; |
| 31 | 31 | ||
| 32 | +const headerHeight = 80; | ||
| 33 | + | ||
| 32 | export default { | 34 | export default { |
| 33 | name: 'componentLayout', | 35 | name: 'componentLayout', |
| 34 | components: { LayoutHeader }, | 36 | components: { LayoutHeader }, |
| @@ -47,21 +49,21 @@ export default { | @@ -47,21 +49,21 @@ export default { | ||
| 47 | }, | 49 | }, |
| 48 | mounted() { | 50 | mounted() { |
| 49 | this.initAnchorList(); | 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 | // 初次加载时根据url hash跳转到指定锚点 | 63 | // 初次加载时根据url hash跳转到指定锚点 |
| 62 | if (this.$route.hash) { | 64 | if (this.$route.hash) { |
| 63 | const anchor = document.querySelector(this.$route.hash); | 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 | watch:{ | 69 | watch:{ |
| @@ -70,11 +72,6 @@ export default { | @@ -70,11 +72,6 @@ export default { | ||
| 70 | if (to.path !== from.path) { | 72 | if (to.path !== from.path) { |
| 71 | this.$nextTick(this.initAnchorList); | 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 | computed: { | 77 | computed: { |
| @@ -98,11 +95,19 @@ export default { | @@ -98,11 +95,19 @@ export default { | ||
| 98 | return scrollTop + windowHeight === scrollHeight; | 95 | return scrollTop + windowHeight === scrollHeight; |
| 99 | }, | 96 | }, |
| 100 | initAnchorList() { | 97 | initAnchorList() { |
| 98 | + document.documentElement.scrollTop = 0; | ||
| 101 | this.anchorList = []; | 99 | this.anchorList = []; |
| 102 | const domList = document.querySelectorAll('.header-anchor'); | 100 | const domList = document.querySelectorAll('.header-anchor'); |
| 103 | let anchorList = []; | 101 | let anchorList = []; |
| 104 | for (let index in domList) { | 102 | for (let index in domList) { |
| 105 | let dom = domList[index] || {}; | 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 | if (dom.parentNode) { | 111 | if (dom.parentNode) { |
| 107 | const text = `${dom.parentNode.innerHTML}`.replace(/<\/?.*[^>]*>/g, '').trim(); | 112 | const text = `${dom.parentNode.innerHTML}`.replace(/<\/?.*[^>]*>/g, '').trim(); |
| 108 | if (text === 'API') { | 113 | if (text === 'API') { |
| @@ -112,7 +117,6 @@ export default { | @@ -112,7 +117,6 @@ export default { | ||
| 112 | text: `${dom.parentNode.innerHTML}`.replace(/<\/?.*[^>]*>/g, '').trim(), | 117 | text: `${dom.parentNode.innerHTML}`.replace(/<\/?.*[^>]*>/g, '').trim(), |
| 113 | href: dom.href, | 118 | href: dom.href, |
| 114 | hash: dom.hash, | 119 | hash: dom.hash, |
| 115 | - offsetTop: dom.offsetTop, | ||
| 116 | }); | 120 | }); |
| 117 | } | 121 | } |
| 118 | } | 122 | } |
| @@ -120,6 +124,11 @@ export default { | @@ -120,6 +124,11 @@ export default { | ||
| 120 | this.anchorList = anchorList; | 124 | this.anchorList = anchorList; |
| 121 | this.currentAnchor = (anchorList[0] || {}).hash; | 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 | handleSelect(key) { | 132 | handleSelect(key) { |
| 124 | this.$router.push({ name: key }); | 133 | this.$router.push({ name: key }); |
| 125 | } | 134 | } |
| @@ -181,7 +190,9 @@ export default { | @@ -181,7 +190,9 @@ export default { | ||
| 181 | color: $text; | 190 | color: $text; |
| 182 | transition: all 300ms; | 191 | transition: all 300ms; |
| 183 | border-left: 1px solid $border; | 192 | border-left: 1px solid $border; |
| 193 | + cursor: pointer; | ||
| 184 | } | 194 | } |
| 195 | + .anchor:hover, | ||
| 185 | .active { | 196 | .active { |
| 186 | color: $primary; | 197 | color: $primary; |
| 187 | border-left: 1px solid $primary; | 198 | border-left: 1px solid $primary; |