refactor(anchor): use composition api

This commit is contained in:
07akioni 2020-09-18 17:06:19 +08:00
parent 7108717fcd
commit a8449c9842
4 changed files with 108 additions and 54 deletions

View File

@ -2,7 +2,11 @@ import {
ref,
computed,
watch,
onMounted, inject, toRef
onMounted,
inject,
toRef,
getCurrentInstance,
onBeforeUnmount
} from 'vue'
export function useFalseUntilTruthy (valueRef) {
@ -62,4 +66,59 @@ export function useInjectionRef (injectionName, key, fallback) {
return toRef(injection, key)
}
export function onFontReady (callback) {
onMounted(() => {
const fontsReady = document.fonts.ready
const currentInstance = getCurrentInstance().proxy
fontsReady.then(() => {
callback(currentInstance)
})
})
}
export function useInjectionCollection (injectionName, collectionKey, valueRef) {
const injection = inject(injectionName)
if (!(collectionKey in injection)) {
injection[collectionKey] = []
}
injection[collectionKey].push(valueRef.value)
watch(valueRef, (value, prevValue) => {
const collectionArray = injection[collectionKey]
const index = collectionArray.findIndex(
collectionValue => collectionValue === prevValue
)
if (~index) collectionArray.splice(index, 1)
collectionArray.push(value)
})
onBeforeUnmount(() => {
const collectionArray = injection[collectionKey]
const index = collectionArray.findIndex(
collectionValue => collectionValue === valueRef.value
)
if (~index) collectionArray.splice(index, 1)
})
}
export function useInjectionElementCollection (injectionName, collectionKey, getElement) {
const injection = inject(injectionName)
if (!(collectionKey in injection)) {
injection[collectionKey] = []
}
onMounted(() => {
const currentInstance = getCurrentInstance().proxy
injection[collectionKey].push(
getElement(currentInstance)
)
})
onBeforeUnmount(() => {
const collectionArray = injection[collectionKey]
const currentInstance = getCurrentInstance().proxy
const element = getElement(currentInstance)
const index = collectionArray.findIndex(
collectionElement => collectionElement === element
)
if (~index) collectionArray.splice(index, 1)
})
}
export { default as useLastClickPosition } from './use-last-click-position'

View File

@ -1,6 +1,5 @@
<template>
<div />
<!-- <n-base-anchor
<n-base-anchor
v-if="!affix"
ref="anchor"
:bound="bound"
@ -26,7 +25,7 @@
>
<slot />
</n-base-anchor>
</n-affix> -->
</n-affix>
</template>
<script>

View File

@ -24,10 +24,12 @@
</template>
<script>
import { nextTick, ref, markRaw } from 'vue'
import getScrollParent from '../../_utils/dom/getScrollParent'
import withapp from '../../_mixins/withapp'
import themeable from '../../_mixins/themeable'
import fontawarable from '../../_mixins/fontawarable'
import { onFontReady } from '../../_utils/composition/index'
import { warn } from '../../_utils/naive/warn'
function getOffset (el, container) {
const {
@ -45,7 +47,15 @@ function getOffset (el, container) {
export default {
name: 'NBaseAnchor',
mixins: [withapp, themeable, fontawarable],
mixins: [
withapp,
themeable
],
provide () {
return {
NAnchor: this
}
},
props: {
target: {
type: Function,
@ -60,12 +70,17 @@ export default {
default: false
}
},
data () {
setup () {
onFontReady(vm => {
vm.init()
vm.setActiveHref(window.location)
vm.handleScroll(false)
})
return {
collectedLinkHrefs: [],
titleEls: [],
activeHref: null,
container: null
collectedLinkHrefs: markRaw([]),
titleEls: markRaw([]),
activeHref: ref(null),
container: ref(null)
}
},
watch: {
@ -76,17 +91,7 @@ export default {
}
}
},
provide () {
return {
NAnchor: this
}
},
methods: {
handleFontReady () {
this.init()
this.setActiveHref(window.location)
this.handleScroll(false)
},
disableTransitionOneTick () {
const barEl = this.$refs.bar
const slotEl = this.$refs.slot
@ -100,7 +105,7 @@ export default {
titleEls.forEach(titleEl => {
titleEl.style.transition = 'none'
})
this.$nextTick().then(() => {
nextTick(() => {
const nextBarEl = this.$refs.bar
const nextSlotEl = this.$refs.slot
if (nextBarEl) {
@ -229,8 +234,8 @@ export default {
const target = this.target()
if (target instanceof Element) {
this.container = target
} else {
console.error('[naive-ui/Anchor]: target is not a element')
} else if (__DEV__) {
warn('anchor', 'target is not a element')
}
}
if (this.container) {

View File

@ -18,8 +18,13 @@
</template>
<script>
import collectable from '../../_mixins/collectable'
import simlulatedComputed from '../../_mixins/simulatedComputed'
import { toRef } from 'vue'
import {
useMemo,
useInjectionRef,
useInjectionCollection,
useInjectionElementCollection
} from '../../_utils/composition'
export default {
name: 'AnchorLink',
@ -28,19 +33,6 @@ export default {
default: null
}
},
mixins: [
simlulatedComputed({
active: {
get () {
const href = this.href
return href && (this.activeHref === href)
},
deps: ['activeHref', 'href'],
default: false
}
}),
collectable('NAnchor', 'collectedLinkHrefs', 'href')
],
props: {
title: {
type: String,
@ -51,9 +43,20 @@ export default {
default: null
}
},
computed: {
activeHref () {
return this.NAnchor.activeHref
setup (props) {
const activeHrefRef = useInjectionRef('NAnchor', 'activeHref')
const hrefRef = toRef(props, 'href')
const activeRef = useMemo(() => {
return hrefRef.value && (hrefRef.value === activeHrefRef.value)
}, [
hrefRef,
activeHrefRef
])
useInjectionCollection('NAnchor', 'collectedLinkHrefs', hrefRef)
useInjectionElementCollection('NAnchor', 'titleEls', vm => vm.$refs.title)
return {
activeHref: activeHrefRef,
active: activeRef
}
},
watch: {
@ -61,19 +64,7 @@ export default {
if (value) this.NAnchor.updateBarPosition(this.$refs.title)
}
},
mounted () {
this.NAnchor.titleEls.push(this.$refs.title)
},
beforeDestroy () {
const titleElIndex = this.NAnchor.titleEls.findIndex(el => el === this.$refs.title)
if (~titleElIndex) this.NAnchor.titleEls.splice(titleElIndex, 1)
},
methods: {
handleFontReady () {
if (this.active) {
this.NAnchor.updateBarPosition(this.$refs.title, false)
}
},
handleClick (e) {
this.NAnchor.setActiveHref(this.href)
}