Cell Vue 3 TypeScript版本

2021-04-13  本文已影响0人  EasyNetCN
cell.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>
上一篇 下一篇

猜你喜欢

热点阅读