mirror of
https://github.com/tusen-ai/naive-ui.git
synced 2025-01-18 12:34:25 +08:00
refactor(anchor): target => listen-to, fix scroll listener is not unregistered
This commit is contained in:
parent
f0ac1d30c1
commit
52f58d9dac
@ -15,7 +15,7 @@ scrollto
|
||||
|affix|`boolean`|`false`|If it works like a affix. If set to `true`, it will recieve props from [affix](n-affix#Props)|
|
||||
|bound|`number`|`12`||
|
||||
|ignore-gap|`boolean`|`false`| If set to `true`, it will be displayed on the exact href |
|
||||
|target|`() => HTMLElement`|A function that returns the nearest scrollable ascendant element|The element that anchor listens to scroll event. (If you want affix & anchor to listen to different target, manually warp anchor in affix instead.)|
|
||||
|listen-to|`string \| HTMLElement`|`undefined`|The scrolling element to listen scrolling. If not set it will listen to the nearest scrollable ascendant element.|
|
||||
|theme|`'light' \| 'dark' \| string`|`undefined`||
|
||||
|
||||
## Methods
|
||||
|
@ -14,7 +14,7 @@ scrollto
|
||||
|affix|`boolean`|`false`|Anchor 是否像 Affix 一样展示,如果设定为 `true`,它还会接受 [Affix](n-affix#Props) 的 Props|
|
||||
|bound|`number`|`12`||
|
||||
|ignore-gap|`boolean`|`false`| 如果设定为 `true`, 导航将显示在准确的href区域 |
|
||||
|target|`() => HTMLElement`|一个返回最邻近可滚动祖先元素的函数|需要监听滚动的元素(如果你希望 Anchor 和 Affix 分别监听不同的元素,可以手动的组合 Anchor 和 Affix)|
|
||||
|listen-to|`string \| HTMLElement`|`undefined`|需要监听滚动的元素,如果未设定则会监听最近的可滚动祖先元素|
|
||||
|theme|`'light' \| 'dark' \| string`|`undefined`||
|
||||
|
||||
## Methods
|
||||
|
@ -116,11 +116,11 @@ export default {
|
||||
},
|
||||
x: {
|
||||
type: Number,
|
||||
default: null
|
||||
default: undefined
|
||||
},
|
||||
y: {
|
||||
type: Number,
|
||||
default: null
|
||||
default: undefined
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
@ -2,6 +2,8 @@
|
||||
<n-base-anchor
|
||||
v-if="!affix"
|
||||
ref="anchor"
|
||||
:theme="theme"
|
||||
:listen-to="listenTo"
|
||||
:bound="bound"
|
||||
:target="target"
|
||||
:ignore-gap="ignoreGap"
|
||||
@ -10,18 +12,21 @@
|
||||
</n-base-anchor>
|
||||
<n-affix
|
||||
v-else
|
||||
:target="target"
|
||||
:listen-to="listenTo"
|
||||
:top="top"
|
||||
:bottom="bottom"
|
||||
:offset-top="offsetTop"
|
||||
:offset-bottom="offsetBottom"
|
||||
:position="position"
|
||||
:target="target"
|
||||
>
|
||||
<n-base-anchor
|
||||
ref="anchor"
|
||||
:theme="theme"
|
||||
:bound="bound"
|
||||
:target="target"
|
||||
:listen-to="listenTo"
|
||||
:ignore-gap="ignoreGap"
|
||||
:target="target"
|
||||
>
|
||||
<slot />
|
||||
</n-base-anchor>
|
||||
@ -31,10 +36,7 @@
|
||||
<script>
|
||||
import NBaseAnchor from './BaseAnchor.vue'
|
||||
import NAffix from '../../affix'
|
||||
import usecssr from '../../_mixins/usecssr'
|
||||
import themeable from '../../_mixins/themeable'
|
||||
import withapp from '../../_mixins/withapp'
|
||||
import styles from './styles'
|
||||
import { themeable } from '../../_mixins'
|
||||
|
||||
export default {
|
||||
name: 'Anchor',
|
||||
@ -43,18 +45,12 @@ export default {
|
||||
NAffix
|
||||
},
|
||||
mixins: [
|
||||
withapp,
|
||||
themeable,
|
||||
usecssr(styles)
|
||||
themeable
|
||||
],
|
||||
props: {
|
||||
top: {
|
||||
type: Number,
|
||||
default: null
|
||||
},
|
||||
target: {
|
||||
type: Function,
|
||||
default: null
|
||||
default: undefined
|
||||
},
|
||||
affix: {
|
||||
type: Boolean,
|
||||
@ -83,6 +79,17 @@ export default {
|
||||
ignoreGap: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
listenTo: {
|
||||
type: [String, Object],
|
||||
default: undefined
|
||||
},
|
||||
// deprecated
|
||||
target: {
|
||||
validator () {
|
||||
return true
|
||||
},
|
||||
default: undefined
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -26,10 +26,15 @@
|
||||
<script>
|
||||
import { nextTick, ref, markRaw } from 'vue'
|
||||
import getScrollParent from '../../_utils/dom/getScrollParent'
|
||||
import withapp from '../../_mixins/withapp'
|
||||
import themeable from '../../_mixins/themeable'
|
||||
import {
|
||||
configurable,
|
||||
themeable,
|
||||
usecssr
|
||||
} from '../../_mixins'
|
||||
import { onFontReady } from '../../_utils/composition/index'
|
||||
import { warn } from '../../_utils/naive/warn'
|
||||
import getTarget from '../../_utils/dom/get-target'
|
||||
import styles from './styles'
|
||||
|
||||
function getOffset (el, container) {
|
||||
const {
|
||||
@ -46,10 +51,12 @@ function getOffset (el, container) {
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'NBaseAnchor',
|
||||
name: 'BaseAnchor',
|
||||
cssrName: 'Anchor',
|
||||
mixins: [
|
||||
withapp,
|
||||
themeable
|
||||
configurable,
|
||||
themeable,
|
||||
usecssr(styles)
|
||||
],
|
||||
provide () {
|
||||
return {
|
||||
@ -57,9 +64,9 @@ export default {
|
||||
}
|
||||
},
|
||||
props: {
|
||||
target: {
|
||||
type: Function,
|
||||
default: null
|
||||
listenTo: {
|
||||
type: [String, Object],
|
||||
default: undefined
|
||||
},
|
||||
bound: {
|
||||
type: Number,
|
||||
@ -68,6 +75,14 @@ export default {
|
||||
ignoreGap: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// deprecated
|
||||
target: {
|
||||
validator () {
|
||||
if (__DEV__) warn('anchor', '`target` is deprecated, please use`listen-to` instead.')
|
||||
return true
|
||||
},
|
||||
default: undefined
|
||||
}
|
||||
},
|
||||
setup () {
|
||||
@ -80,7 +95,13 @@ export default {
|
||||
collectedLinkHrefs: markRaw([]),
|
||||
titleEls: markRaw([]),
|
||||
activeHref: ref(null),
|
||||
container: ref(null)
|
||||
scrollElement: ref(null)
|
||||
}
|
||||
},
|
||||
beforeUnmount () {
|
||||
const { scrollElement } = this
|
||||
if (scrollElement) {
|
||||
scrollElement.removeEventListener('scroll', this.handleScroll)
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@ -162,8 +183,11 @@ export default {
|
||||
const linkEl = document.getElementById(idMatchResult[1])
|
||||
if (linkEl) {
|
||||
this.activeHref = href
|
||||
const top = getOffset(linkEl, this.container).top + (this.container.scrollTop || 0)
|
||||
this.container.scrollTo({
|
||||
const {
|
||||
scrollElement
|
||||
} = this
|
||||
const top = getOffset(linkEl, scrollElement).top + (scrollElement.scrollTop || 0)
|
||||
scrollElement.scrollTo({
|
||||
top: top
|
||||
})
|
||||
if (!transition) {
|
||||
@ -183,7 +207,7 @@ export default {
|
||||
const {
|
||||
top,
|
||||
height
|
||||
} = getOffset(linkEl, this.container)
|
||||
} = getOffset(linkEl, this.scrollElement)
|
||||
links.push({
|
||||
top,
|
||||
height,
|
||||
@ -229,17 +253,26 @@ export default {
|
||||
}
|
||||
},
|
||||
init () {
|
||||
this.container = getScrollParent(this.$el)
|
||||
if (this.target) {
|
||||
const target = this.target()
|
||||
if (target instanceof Element) {
|
||||
this.container = target
|
||||
const {
|
||||
target: getScrollTarget,
|
||||
listenTo
|
||||
} = this
|
||||
let scrollElement
|
||||
if (getScrollTarget) {
|
||||
// deprecated
|
||||
scrollElement = getScrollTarget()
|
||||
} else if (listenTo) {
|
||||
scrollElement = getTarget(listenTo)
|
||||
} else {
|
||||
scrollElement = getScrollParent(this.$el)
|
||||
}
|
||||
if (scrollElement) {
|
||||
this.scrollElement = scrollElement
|
||||
} else if (__DEV__) {
|
||||
warn('anchor', 'target is not a element')
|
||||
warn('anchor', 'Target to be listened to is not valid.')
|
||||
}
|
||||
}
|
||||
if (this.container) {
|
||||
this.container.addEventListener('scroll', this.handleScroll)
|
||||
if (scrollElement) {
|
||||
scrollElement.addEventListener('scroll', this.handleScroll)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user