前言
vue3.0以及生态圈内相关的插件的改动还是比较大的,本文主要围绕以下两点做总结:
1.组件的逻辑拆分与封装
2.遇到的坑以及需要注意的细节
正所谓磨刀不废砍柴工,优秀的代码一定是基于优良的设计之上的!
页面该如何进行组件化的拆分?
首先需要先明确自身对于组件的提炼的标准,然后再依据这个标准进行区分设计提炼封装
我个人是主要以两种进行区分
1.业务组件:业务组件是指一个功能板块,内部含有大量的业务逻辑。
2.视图组件:视图组件功能比较纯粹,内部没有业务逻辑,只存在该如何把数据以规定的ui格式展示的逻辑。
不同类型的组件,在开发时关注的重点是不同的
都是组件,有何不同?
1.应用层面
视图组件:一般颗粒度较小,比如封装一个标签组件,足够的简单,完全可以支持跨业务跨项目、页面使用,
业务组件:一般颗粒度较大,因为至少需要能够完成一个完整的业务逻辑点,只能支持跨项目、页面使用
2.开发层面
视图组件:
虽然功能简单纯粹,但是需要足够灵活。在设计之初就要能够预想到多种情况,例如标签组件该怎样满足字符串和数组等不同场景?
一个优秀的视图组件,内部肯定有大量的抽象方法支持。视图组件开发复杂度和灵活度成正比
业务组件:
复杂度基本也只取决于业务的复杂度,不需要应对过多不同场景。
一个业务组件内部可能存在多个逻辑,所以还牵扯到代码节构的问题,若多个逻辑的代码混乱的分布,那么可读性会很差,对后期维护增加压力。
另外可能存在这种情况:在不同页面(或者不同板块)存在相同业务逻辑,但是视图上的展示又各自极具特色,那么我们就需要只把业务逻辑处理部分提炼封装实现复用。
组件节构
一个复杂的业务组件可能由多个业务逻辑点组合而成,那么一个合理的组件节构是很有必要的。就如同一个房子有地基、墙、屋顶组合而成,它们内部互相无直接关联,只有墙需要基于地基之上、屋顶需要基于墙之上,这种逻辑,而像这种逻辑则应该放到同一个父级组件中完成,它们内部只完成各自的构造。
页面原型
页面拆分设计
1.header.vue
(视图组件) 由下拉框和输入框、搜索按钮组合而成。传入下拉框数据,暴漏出搜索事件以及下拉框和输入框的值
2.card.vue
(业务组件) 内容为列表中的方块内容组,完成信息的展示和功能组
3.list.vue
(视图组件) 无关内容 只提供下拉加载等功能
4.projectPage.vue
最外层的组合组件 提供业务逻辑、组件的组合搭建
逻辑点分析
1.请求下拉框数据并且默认选中第一条
2.确定下拉框数据填充完毕后,列表根据当前条件初始化数据(默认每次5条,下拉再加载5条并拼接在下方)
3.点击搜索,则清空之前数据,第一次依然是先加载5条数据
具体的代码细节我就不贴出来了,用伪代码展示关键代码
projectPage.vue
<!-- dropValue:下拉框选中值 secharValue:输入框的值 drops:下拉框数据源 sechar:搜索事件 -->
<header :drops="drops" v-model:dropValue="dropValue" v-model:secharValue="secharValue" @sechar="secharClick" />
<!-- loading:每一次的加载状态 load:加载函数 finished:数据是否全部加载完毕 -->
<list v-model:loading="loading" @load="listLoad" :finished="finished">
<card v-for="item in listData" :key="item.key" :contentData="item" />
</list>
import { ref, computed } from 'vue'
import { getDrops, licenseList } from "@/api/licen"
import useLoadList from "@/compositions/useLoadList"
import header from "@/conponents/header.vue"
import list from "@/conponents/list.vue"
import card from "@/conponents/card.vue"
setup(){
const dropValue = ref('')
const secharValue = ref('')
const drops = ref([])
const params = computed(() => {
return {
drop: dropValue.value,
name: secharValue.value
}
})
// 下拉加载列表的逻辑部分代码 加载状态 加载函数 加载完毕状态
const { loading, listLoad, finished, listData } = useLoadList({ service: licenseList },params)
// 获取下拉框数据后,默认选中第一条
getDrops().then(res=>{
drops.value = res
dropValue.value = drops.value[0]
})
return { dropValue, secharValue, drops }
}
唯一需要注意的地方是 我将其中关于下拉加载列表的逻辑提炼到了另一个模块中。在使用组合式api
时,我会较以往更能关注到不同逻辑之间的拆分。
整体开发下来,与使用vue2开发时的不同及感受大概如下:
1.api的改变 (技术细节的改变可以看我这篇文章vue3学习总结
2.会让开发者更关注业务逻辑的拆分,代码结构的设计。
3.更加的灵活,更贴近js底层。
不得不说的组合式API
2.x时期的选项卡模式
这种模式下,vue
为我们规定好了什么东西应该放在哪里,例如数据
要放在data
声明内,方法
则要放在methods
声明内,在代码节构上看起来会很清晰,但从某一方面来讲,这样的模式又如同一个框架一样,限制着我们的思维。举个例子,比如像对象工厂函数这种技巧,在vue的项目中几乎看不到被使用。我们会在data
,methods
...这种逻辑基准之上去思考。
3.x的组合式API
这种模式可以更解放我们的思维,vue
即提供了能帮我们完成诸多功能的api
,又不会过多的干扰我们写代码自身的思维,我认为这更贴合作为工具
的本质。
混入 mixins
的确,在vue2.x,当我们遇到一个组件的部分逻辑有多个地方都会用的时候,可以采用mixins
来解决,但是个人认为mixins
并不足够灵活,而且存在很多问题,例如当有同名的属性时,会采取浅合并。我们原本只是想拆分逻辑代码,但是这个操作却和vue
这个框架耦合很深
相比较起来,组合式API
就能够更多的运用js
的技巧解决问题。