美文网首页
Layout Vue 3 TypeScript版本

Layout Vue 3 TypeScript版本

作者: EasyNetCN | 来源:发表于2021-04-23 14:29 被阅读0次

    本示例中,可以了解vue3中ref,watch的使用。


    layout

    layout

    <template>
         <div :class="wrapClasses"><slot></slot></div>
    </template>
    <script lang="ts">
    import { computed, defineComponent, onMounted, ref } from 'vue'
    
    const prefixCls = 'ivu-layout'
    
    export default defineComponent({
      name: 'Layout',
      setup (props, ctx) {
        const hasSider = ref(false)
    
        const wrapClasses = computed(() => {
          return [
                        `${prefixCls}`,
                        {
                          [`${prefixCls}-has-sider`]: hasSider.value
                        }
          ]
        })
    
        onMounted(() => {
          hasSider.value = ctx.slots.default !== undefined && ctx.slots.default().some((child: any) => {
            return child.type.name === 'Sider'
          })
        })
    
        return {
          hasSider,
          wrapClasses
        }
      }
    })
    </script>
    

    content

    <template>
        <div :class="wrapClasses"><slot></slot></div>
    </template>
    <script lang="ts">
    import { computed, defineComponent } from 'vue'
    
    const prefixCls = 'ivu-layout'
    
    export default defineComponent({
      name: 'Content',
      setup () {
        const wrapClasses = computed(() => {
          return `${prefixCls}-content`
        })
    
        return {
          wrapClasses
        }
      }
    })
    </script>
    

    header

    <template>
        <div :class="wrapClasses"><slot></slot></div>
    </template>
    <script lang="ts">
    import { computed, defineComponent } from 'vue'
    
    const prefixCls = 'ivu-layout'
    
    export default defineComponent({
      name: 'Header',
      setup () {
        const wrapClasses = computed(() => {
          return `${prefixCls}-header`
        })
    
        return {
          wrapClasses
        }
      }
    })
    </script>
    

    footer

    <template>
        <div :class="wrapClasses"><slot></slot></div>
    </template>
    <script lang="ts">
    import { computed, defineComponent } from 'vue'
    
    const prefixCls = 'ivu-layout'
    
    export default defineComponent({
      name: 'Footer',
      setup () {
        const wrapClasses = computed(() => {
          return `${prefixCls}-footer`
        })
    
        return {
          wrapClasses
        }
      }
    })
    </script>
    

    sider

    <template>
        <div
            :class="wrapClasses"
            :style="wrapStyles">
            <span v-show="showZeroTrigger" @click="toggleCollapse" :class="zeroWidthTriggerClasses">
                <i class="ivu-icon ivu-icon-ios-menu"></i>
            </span>
            <div :class="childClasses">
                <slot></slot>
            </div>
            <slot name="trigger">
                <div v-show="showBottomTrigger" :class="triggerClasses" @click="toggleCollapse" :style="{width: siderWidth + 'px'}">
                    <i :class="triggerIconClasses"></i>
                </div>
            </slot>
        </div>
    </template>
    <script lang="ts">
    import { computed, defineComponent, onMounted, PropType, ref, toRefs, watch } from 'vue'
    
    import { on, off } from '../../utils/dom'
    import { dimensionMap, setMatchMedia } from '../../utils/assist'
    
    const prefixClass = 'ivu-layout-sider'
    
    setMatchMedia()
    
    export default defineComponent({
      name: 'Sider',
      props: {
        value: { // if it's collpased now
          type: Boolean,
          default: false
        },
        width: {
          type: [Number, String] as PropType<number| string>,
          default: 200
        },
        collapsedWidth: {
          type: [Number, String] as PropType<number| string>,
          default: 64
        },
        hideTrigger: {
          type: Boolean,
          default: false
        },
        breakpoint: {
          type: String as PropType<'xs'| 'sm'| 'md'| 'lg'| 'xl'| 'xxl'>
        },
        collapsible: {
          type: Boolean,
          default: false
        },
        defaultCollapsed: {
          type: Boolean,
          default: false
        },
        reverseArrow: {
          type: Boolean,
          default: false
        }
      },
      emits: ['input', 'on-collapse', 'update:value'],
      setup (props, ctx) {
        const { value, width, collapsedWidth, hideTrigger, breakpoint, collapsible, defaultCollapsed, reverseArrow } = toRefs(props)
    
        const prefixCls = ref(prefixClass)
        const mediaMatched = ref(false)
    
        const siderWidth = computed(() => {
          return collapsible.value ? (value.value ? (mediaMatched.value ? 0 : parseInt(collapsedWidth.value.toString())) : parseInt(width.value.toString())) : width.value
        })
        const wrapClasses = computed(() => {
          return [
                        `${prefixCls.value}`,
                        siderWidth.value ? '' : `${prefixCls.value}-zero-width`,
                        value.value ? `${prefixCls.value}-collapsed` : ''
          ]
        })
        const wrapStyles = computed(() => {
          return {
            width: `${siderWidth.value}px`,
            minWidth: `${siderWidth.value}px`,
            maxWidth: `${siderWidth.value}px`,
            flex: `0 0 ${siderWidth.value}px`
          }
        })
        const triggerClasses = computed(() => {
          return [
                        `${prefixCls.value}-trigger`,
                        value.value ? `${prefixCls.value}-trigger-collapsed` : ''
          ]
        })
        const childClasses = computed(() => {
          return `${prefixCls.value}-children`
        })
        const zeroWidthTriggerClasses = computed(() => {
          return [
                        `${prefixCls.value}-zero-width-trigger`,
                        reverseArrow.value ? `${prefixCls.value}-zero-width-trigger-left` : ''
          ]
        })
        const triggerIconClasses = computed(() => {
          return [
            'ivu-icon',
                        `ivu-icon-ios-arrow-${reverseArrow.value ? 'forward' : 'back'}`,
                        `${prefixCls.value}-trigger-icon`
          ]
        })
        const showZeroTrigger = computed(() => {
          if (collapsible.value) {
            return (mediaMatched.value && !hideTrigger.value) || ((parseInt(collapsedWidth.value.toString()) === 0) && value.value && !hideTrigger.value)
          }
    
          return false
        })
        const showBottomTrigger = computed(() => {
          return collapsible.value ? !mediaMatched.value && !hideTrigger.value : false
        })
    
        const toggleCollapse = () => {
          const val = collapsible.value ? !value.value : false
          ctx.emit('input', val)
          ctx.emit('update:value', val)
        }
        const matchMedia = () => {
          let matchMedia
          if (window.matchMedia) {
            matchMedia = window.matchMedia
          }
          const mediaMatchedVal = mediaMatched.value
    
          mediaMatched.value = breakpoint?.value !== undefined && matchMedia !== undefined && matchMedia(`(max-width: ${dimensionMap[breakpoint?.value]})`).matches
    
          if (mediaMatched.value !== mediaMatchedVal) {
            ctx.emit('input', mediaMatched.value)
          }
        }
        const onWindowResize = () => {
          matchMedia()
        }
    
        watch(value, (stat) => {
          ctx.emit('on-collapse', stat)
        })
    
        onMounted(() => {
          if (defaultCollapsed.value) {
            ctx.emit('input', defaultCollapsed.value)
          }
          if (breakpoint?.value !== undefined) {
            on(window, 'resize', onWindowResize)
            matchMedia()
          }
        })
        onMounted(() => {
          if (breakpoint?.value !== undefined) {
            off(window, 'resize', onWindowResize)
          }
        })
    
        return {
          prefixCls,
          mediaMatched,
          siderWidth,
          wrapClasses,
          wrapStyles,
          triggerClasses,
          childClasses,
          zeroWidthTriggerClasses,
          triggerIconClasses,
          showZeroTrigger,
          showBottomTrigger,
          toggleCollapse,
          matchMedia,
          onWindowResize
        }
      }
    })
    </script>
    

    相关文章

      网友评论

          本文标题:Layout Vue 3 TypeScript版本

          本文链接:https://www.haomeiwen.com/subject/kxmcrltx.html