最近接到了一个老项目的翻新工作,结束了总结一下自己的经验方法
使用hooks抽离常用的逻辑,然后使用一套逻辑匹配多种UI版式来提高工作效率
一、以常见的列表展示形式为例子 1.在PC上有列表展示的方式,有卡片展示的方式,有整页轮播的方式等等一系列,通常我们为了适配UI会去实现多个vue,*sx文件,当需求任务样式慢慢的迭代,内容就会慢慢的变得不可控,代码的稳健性会大幅度下降我们可能会写出下面这些代码// 文件1
interface 列表1的文件参数 {
// 数据
data: any[]
//... xxx一系列参数
}
defineOptions({
name: "文件1",
})
defineProps<IListProps>()
这是第二个样式的列表
// 文件2
interface 列表2的文件参数 {
// 数据
data: any[]
//... xxx一系列参数
}
defineOptions({
name: "文件2",
})
defineProps<IListProps>()
这是第三个样式的列表(以此类推,可能慢慢就会有很多参数类似,只是样式大同小异的文件出现)
// 文件3
interface 列表3的文件参数 {
// 数据
data: any[]
//... xxx一系列参数
}
defineOptions({
name: "文件3",
})
defineProps<IListProps>()
聪明的你一定可以想得到抽离逻辑,然后通过type去区分以及写一个大的props涵盖之前所有的参数来保证之前的控件不出问题 最终可能会写成这样
// 大合集文件
interface 大合集文件的文件参数 {
// 数据
data: any[]
// 判断是什么类型的列表
type:"1"|"2"|"3"|"4"|"5"|"6"....
//... xxx一系列参数 包含之前的列表的文件
}
defineOptions({
name: "大合集文件",
})
const props = defineProps<IListProps>()
// 模拟场景 为了保证不影响 还可能会在判断里面加上return 来确保逻辑的正确执行
function test(){
if(props.type==="1"){
// 做什么
}
if(props.type==="2"){
// 做什么
}
if(props.type==="3"){
// 做什么
}
if(["5","6"]){
// ...
}
}
当这么一个大而全的列表经历1到2年的迭代可能会慢慢的面目全非,然后会变得难以维护。这个时候就可以试试把逻辑单独写出来(参考了设计模式
设计思路
- 抽离共有逻辑
- 留出位置可以绑定不同UI实现同时不影响原有功能(单一原则)
- 图片所示
大致就是这样的一个思路 公共逻辑 对外暴露的模块 + 一个符合条件的UI文件 就可以组成一个列表了 下面看看代码
公共逻辑 对外暴露的模块
// 名字你们自己看着起 可能需要props和emits 先定义 但是可以为空
export function use公共部分(props={},emits=null){
function 获取表格数据
function 上一页
function 下一页
// 你需要的一切方法
function ...
}
export function use外暴露的模块(props={},emits=null){
// 需要绑定的组件提供的内容
const Instance = ref(null)
// 绑定的方法
function register(instance) {
if (!instance) return console.error('instance is required')
if (instance) {
popupInstance.value = instance
}
}
function 类型1需要的方法(){
//类型1你需要做的事情 额外判断一下防止在渲染前调用(可以写一个数组去维护 然后在生命周期里面执行
// 当执行完了 就清空数组 这样可以不判断
if (Instance.value && Instance.value.你的方法名
Instance.value.你的方法名()
}
}
function 类型2需要的方法(){
//类型2你需要做的事情 额外判断一下防止在渲染前调用(可以写一个数组去维护 然后在生命周期里面执行
// 当执行完了 就清空数组 这样可以不判断
if (Instance.value && Instance.value.你的方法名
Instance.value.你的方法名()
}
}
function 类型3需要的方法(){
//类型3你需要做的事情 额外判断一下防止在渲染前调用(可以写一个数组去维护 然后在生命周期里面执行
// 当执行完了 就清空数组 这样可以不判断
if (Instance.value && Instance.value.你的方法名
Instance.value.你的方法名()
}
}
//这里导出数组混对象 是为了一个页面有多个名字的时候方便起别名,然后数组的形式更加特殊也方便理解
return [register, { 类型1需要的方法,类型2需要的方法,类型3需要的方法}]
}
需要匹配的的UI文件
// UI样式1
const {方法1} = use公共部分()
// 叫啥名不重要只要有就行
const emit = defineEmits(['register'])
onMounted(() => {
emit('register', {
样式1的方法1,
样式1的方法2,
样式1的方法3,
})
})
// UI样式2
const {方法2} = use公共部分()
// 叫啥名不重要只要有就行
const emit = defineEmits(['register'])
// 如果都在公共里面 可以直接用 不需要这么麻烦 我写这么多主要是为了举例子
onMounted(() => {
emit('register', {
样式2的方法1,
样式2的方法2,
样式2的方法3,
样式2的特殊方法1
})
})
// 调用UI文件的地方
<script setup lang="ts">
const [register,{你需要的方法}] = use外暴露的模块({...一系列参数})
// 在你需要的时候 执行你需要的方法 这样更加的灵活可控
</script>
<template>
<UI样式1 @register="register">
</UI样式1>
</template>
// 不同的ui使用相同的逻辑
<script setup lang="ts">
const [register,{你需要的方法2}]=use外暴露的模块({...一系列参数})
</script>
<template>
<UI样式2 @register="register">
</UI样式2>
</template>
这样通过hooks+设计 把逻辑统一到了一个文件里面,后期维护也是可以维护在一起,这样哪怕是多人协同维护同一个文件,也可以知道有没有可以共有的部分,能够很大程度减少资源的浪费以及复用他人的功能。(因为通过设计模式把所有的资源约束到了一条主线上)
有不懂的小伙伴可以留言,一起探讨。
以上就是经验方法的总结