Cell Vue 3 TypeScript版本
2021-04-13 本文已影响0人
EasyNetCN
![](https://img.haomeiwen.com/i9524925/2201f27c2ceb18e2.png)
使用父级的实例及调用父级实例的方法
const cellGroup = inject<any>('cellGroup')
const handleClickItem = (event: any, newWindow: boolean) => {
cellGroup.ctx.handleClick(name?.value)
handleCheckClick(event, newWindow)
}
cell-item
<template>
<div class="ivu-cell-item">
<div class="ivu-cell-icon">
<slot name="icon"></slot>
</div>
<div class="ivu-cell-main">
<div class="ivu-cell-title"><slot>{{ title }}</slot></div>
<div class="ivu-cell-label"><slot name="label">{{ label }}</slot></div>
</div>
<div class="ivu-cell-footer">
<span class="ivu-cell-extra"><slot name="extra">{{ extra }}</slot></span>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
name: 'CellItem',
props: {
title: {
type: String,
default: ''
},
label: {
type: String,
default: ''
},
extra: {
type: String,
default: ''
}
}
})
</script>
cell
<template>
<div :class="classes">
<a
v-if="to"
:href="linkUrl"
:target="target"
class="ivu-cell-link"
@click.exact="handleClickItem($event, false)"
@click.ctrl="handleClickItem($event, true)"
@click.meta="handleClickItem($event, true)">
<CellItem :title="title" :label="label" :extra="extra">
<template v-slot:icon><slot name="icon"></slot></template>
<template v-slot:default><slot name="default"></slot></template>
<template v-slot:extra><slot name="extra"></slot></template>
<template v-slot:label><slot name="label"></slot></template>
</CellItem>
</a>
<div class="ivu-cell-link" v-else @click="handleClickItem">
<CellItem :title="title" :label="label" :extra="extra">
<slot name="icon"></slot>
<slot name="default"></slot>
<template v-slot:extra><slot></slot></template>
<slot name="label"></slot>
</CellItem>
</div>
<div class="ivu-cell-arrow" v-if="to">
<slot name="arrow">
<Icon :type="arrowType" :custom="customArrowType" :size="arrowSize" />
</slot>
</div>
</div>
</template>
<script lang="ts">
import { computed, defineComponent, getCurrentInstance, inject, PropType, ref, toRefs } from 'vue'
import CellItem from './cell-item.vue'
import Icon from '../icon'
const prefixClass = 'ivu-cell'
export default defineComponent({
name: 'Cell',
inject: ['cellGroup'],
components: { CellItem, Icon },
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
},
name: {
type: [String, Number]
},
title: {
type: String,
default: ''
},
label: {
type: String,
default: ''
},
extra: {
type: String,
default: ''
},
disabled: {
type: Boolean,
default: false
},
selected: {
type: Boolean,
default: false
}
},
setup (props, ctx) {
const { to, replace, target, append } = toRefs(props)
const instance = getCurrentInstance()
const router = instance?.appContext.config.globalProperties.$router
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
})
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)
}
}
}
const cellGroup = inject<any>('cellGroup')
const { name, disabled, selected } = toRefs(props)
const prefixCls = ref(prefixClass)
const classes = computed(() => {
return [
`${prefixCls.value}`,
{
[`${prefixCls.value}-disabled`]: disabled.value,
[`${prefixCls.value}-selected`]: selected.value,
[`${prefixCls.value}-with-link`]: to?.value
}
]
})
const arrowType = computed(() => {
return 'ios-arrow-forward'
})
const customArrowType = computed(() => {
return ''
})
const arrowSize = computed(() => {
return ''
})
const handleClickItem = (event: any, newWindow: boolean) => {
cellGroup.ctx.handleClick(name?.value)
handleCheckClick(event, newWindow)
}
return {
linkUrl,
handleClick,
handleCheckClick,
prefixCls,
classes,
arrowType,
customArrowType,
arrowSize,
handleClickItem
}
}
})
</script>
cell-group
<template>
<div class="ivu-cell-group">
<slot></slot>
</div>
</template>
<script lang="ts">
import { defineComponent, getCurrentInstance, provide } from 'vue'
export default defineComponent({
name: 'CellGroup',
emits: ['on-click'],
setup (props, ctx) {
provide('cellGroup', getCurrentInstance())
const handleClick = (name: string) => {
ctx.emit('on-click', name)
}
return {
handleClick
}
}
})
</script>