Vue3+TypeScript+ElementPlus 组件式开发思路分享

369 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情

项目类型 移动端

写代码 三思而后行

工单模块

image.png

对比其他设计图可以发现重复利用的组件

image.png

image.png

image.png

1、开启设计思路(提取相同参数)

Header.vue

<template>
  <div class="header">
    <div class="title" v-text="props.titleName"></div>
    <slot name="do"></slot>
  </div>
</template>
<script setup lang="ts">
import { withDefaults } from 'vue'

interface Props {
  titleName?: string
}

const props = withDefaults(defineProps<Props>(), {
  titleName: '工单管理'
})
</script>

具名插槽可以让底部实现动态化,需要什么传递什么

Pane.vue

<template>
  <el-tabs v-model="activeName" class="demo-tabs">
    <el-tab-pane
      v-for="(l, i) in props.tabList"
      :key="l.name + i"
      :label="l.name"
      :name="l.name"></el-tab-pane>
  </el-tabs>
</template>

<script setup lang="ts">
import { computed, withDefaults, defineEmits } from 'vue'

interface Props{
  tabList?: any[],
  activeN?: any
}
const emit = defineEmits(['update:activeN'])
const props = withDefaults(defineProps<Props>(), {
  tabList: () => [],
  activeN: ''
})
const activeName = computed({
  get() {
    return props.activeN
  },
  set(val) {
    emit('update:activeN', val)
  }
})

</script>

index.vue

<template>
  <Header>
    <template v-slot:do>
      <Pane
        :tab-list="state.tabList"
        @update:active-n="stateApi.itsmType = $event"></Pane>
    </template>
  </Header>
</template>
<script setup lang="ts">
import Pane from '@/components/Pane.vue'
import Header from '@/components/Header.vue'
import { onMounted, reactive, ref, watch } from 'vue'
import { getAllOrder, getTabPaneList } from '@/api/orderDispatch'
import { OrderDispatchTypeApi, OrderForApi } from '@/types'

onMounted(() => {
  getTabList()
})

const getTabList = async() => {
  const { data } = await getTabPaneList() as any
  state.tabList = data
  stateApi.itsmType = state.tabList?.[0]?.name
  if (data.length > 0) {
    getAllOrderList()
  }
}
const state = reactive<any>({
  tabList: [],
  orderList: []
})
const stateApi = reactive<OrderDispatchTypeApi>({
  itsmType: '',
  status: 1,
  time: '2022-04-07 09',
  currentPageNo: 1,
  pageSize: 10
})
const orderListLoading = ref<boolean>(false)
watch(() => stateApi.itsmType, () => {
  getAllOrderList()
})
const changeStateApi = () => {
  getAllOrderList()
}
const getAllOrderList = async() => {
  orderListLoading.value = true
  const { data } = await getAllOrder(stateApi) as any
  orderListLoading.value = false
  state.orderList = data
}


</script>

2、函数式组件设计思路

index.vue

<template>
  <div class="p-4 h-full">
    <Label
      v-for="(l, i) in state.warningList"
      :key="l.styleT + i"
      :style-t="l.styleT"
      :children="l.childrenList"></Label>
  </div>
</template>

Label.vue

<script lang="ts">
import { h, defineComponent } from 'vue'

export default defineComponent({
  name: 'Label',
  props: {
    styleT: {
      type: String,
      default: () => ''
    },
    children: {
      type: Array,
      default: () => [] as any[]
    }
  },
  render() {
    return h('div', {
      class: this.styleT
    }, [
      h('div', { class: (this.children[0] as any).className }, (this.children[0] as any).children),
      h('div', { class: (this.children[1] as any).className }, (this.children[1] as any).children)
    ])
  }
})

</script>

拆分组件所带来的好处

  1. 提高开发效率

在组件化开发之前,我们每个页面都是单独的,如果在开发一个页面的时候遇到了曾今开发过类似的部分,只能复制粘贴到当前页面,然后进行一些改动,有时参数、变量之类的丢失,页面或许还会报错,还要花费大量的时候去排查问题,组件化之后,类似的部分我们只需要引入组件即可,无需重复开发,一定程度上也减少了代码量,极大提高项目的编译速度

  1. 方便重复使用

多页面重复使用

  1. 方便调试

能够快速确定某一模块报错

  1. 增加可维护性

页面都由组件组成,模块与模块之间的耦合度降低,删除修改某个模块的功能时仅需直接修改组件

  1. 便于团队开发

下发给每一个人的独立模块,互不干扰

如何拆分组件

  1. 保证组件做好份内事,留出接口,把功能给外包出去

  2. 尽量扩展组件而不是修改,单个组件只实现单纯的功能

  3. 尽量让组件小而精悍

  4. 尽量做到入口和出口的参数校验

export interface OrderDispatchTypeApi extends OrderForApi{
  currentPageNo?: number,
  pageSize?: number,
}

export interface OrderForApi{
  itsmType?: string,
  status?: number,
  time?: string
}

export interface OrderListType extends OrderForApi{
  creatorName?: string,
  createTime?: string
}
  1. 合理组件化