本示例主要演示了父组件通过provide传递数据,以及子组件通过inject接收并处理父组件传递过来的数据
Breadcrumb
<template>
<div :class="classes">
<slot></slot>
</div>
</template>
<script lang="ts">
import { defineComponent, computed, provide, toRefs } from 'vue'
const prefixCls = 'ivu-breadcrumb'
export default defineComponent({
name: 'Breadcrumb',
props: {
separator: {
type: String,
default: ''
}
},
setup (props) {
const { separator } = toRefs(props)
provide('separator', separator)
const classes = computed(() => {
return `${prefixCls}`
})
return {
classes
}
}
})
</script>
BreadcrumbItem
<template>
<span>
<a
v-if="to"
:href="linkUrl"
:target="target"
:class="linkClasses"
@click.exact="handleCheckClick($event, false)"
@click.ctrl="handleCheckClick($event, true)"
@click.meta="handleCheckClick($event, true)">
<slot></slot>
</a>
<span v-else :class="linkClasses">
<slot></slot>
</span>
<span :class="separatorClasses" v-html="separator" v-if="!showSeparator"></span>
<span :class="separatorClasses" v-else>
<slot name="separator"></slot>
</span>
</span>
</template>
<script lang="ts">
import { computed, defineComponent, getCurrentInstance, inject, onMounted, PropType, ref, toRefs } from 'vue'
const prefixCls = 'ivu-breadcrumb-item'
export default defineComponent({
name: 'BreadcrumbItem',
props: {
to: {
type: [Object, String]
},
replace: {
type: Boolean,
default: false
},
target: {
type: String as PropType<'_blank' | '_self' | '_parent' | '_top'>,
default: '_self'
},
append: {
type: Boolean,
required: false,
default: false
}
},
setup (props, ctx) {
const { to, replace, target, append } = toRefs(props)
const separator = inject('separator')
const showSeparator = ref(false)
const instance = getCurrentInstance()
const router = instance?.appContext.config.globalProperties.$router
const linkClasses = computed(() => {
return `${prefixCls}-link`
})
const separatorClasses = computed(() => {
return `${prefixCls}-separator`
})
const linkUrl = computed(() => {
const type = typeof to?.value
if (type !== 'string') {
return null
}
if ((to?.value as string).includes('//')) {
/* Absolute URL, we do not need to route this */
return to?.value
}
if (router) {
const current = router.currentRoute
const route = router.resolve(to?.value, current, append.value)
return route ? route.href : to?.value
}
return to?.value
})
onMounted(() => {
showSeparator.value = ctx.slots.separator !== undefined
})
const handleClick = (newWindow = false) => {
if (newWindow) {
let toOpen = to?.value
if (router) {
const current = router.currentRoute
const route = router.resolve(to?.value, current, append.value)
toOpen = route ? route.href : to?.value
}
window.open(toOpen as string)
} else {
if (router) {
if ((typeof to?.value === 'string') && to.value.includes('//')) {
window.location.href = to.value
} else {
replace.value ? router.replace(to?.value) : router.push(to?.value)
}
} else {
window.location.href = to?.value as string
}
}
}
const handleCheckClick = (event: any, newWindow = false) => {
if (to?.value) {
if (target.value === '_blank') {
return false
} else {
event.preventDefault()
handleClick(newWindow)
}
}
}
return {
separator,
showSeparator,
linkClasses,
separatorClasses,
linkUrl,
handleClick,
handleCheckClick
}
}
})
</script>
网友评论