# vue3封装组件思想+方式
主要记录我对组件封装的个人理解,与封装组件中常用的函数与vue接口# 封装思想
封装方式并非死规则,应根据通信方式灵活处理,寻找组件最适合的封装方式## 1、常规封装思路
在components内新建Lee-compt组件目录补充.vue组件,补充readme.md文档对文档进行描述补充type.ts文件对组件使用到的自定义类型进行补充
- 当前封装方法要学会对项目内可公用部分的业务提取,并内部高耦合外部低耦合,提高组件的复用率## 2、模块封装思路
- 当前封装方法,仅适用于独立于项目本身的组件,如对第三方插件进行自定义封装、或在项目内的组件内部复杂,但对外简单的大组件
在components内新建Lee-compt组件目录补充index.vue组件,作为组件的唯一入口补充组件内部的逻辑文件目录:utils\types\assets\componentsutils存储大组件的公用方法types存储大组件的ts自定义类型assets存储大组件的静态文件components文件用来存储,大组件拆分的小组件
- 当前封装方法要学会善于运用hooks形式的封装,如项目内的 src/components/Lee-Logic-Flow/utils/lifecycle-hooks.ts 文件- 大组件封装,要考虑的是不同项目的移植问题,内部逻辑自洽,对外通信减少类似第三方插件在项目内的使用,提高多个项目的复用率## 3、插槽封装思路
- 通过has与v-if配合,slot与prop的参数用来区分slot的使用条件
// 检查插槽是否被使用,使用则以插槽内容为准,否则以 props.title 为准 const hasTitleSlot = computed(() => { return !!slots.title && slots.title().length > 0; });
# 生命周期钩子
## 1、onActivated
- 组件被激活时触发,用于被keep-live缓存的组件重新显示时## 2、onDeactivated
setup() { onActivated(() => { console.log('组件被激活') // 执行数据更新、状态重置等操作 }) onDeactivated(() => { console.log('组件被停用') // 清理定时器、取消订阅等 }) }
## 3、onBeforeMount
## 4、onMounted
## 5、onBeforeUpdate
## 6、onUpdated
## 7、onBeforeUnmount
## 8、onUnmounted
## 9、onErrorCaptured
setup() { onBeforeMount(() => { // 执行需要访问DOM的操作 console.log('组件挂载前执行') }) onMounted(() => { // 执行需要访问DOM的操作 console.log('组件挂载后执行') }) onBeforeUpdate(() => { // 执行需要访问DOM的操作 console.log('组件dom更新前执行') }) onUpdated(() => { // 组件更新后执行 console.log('组件dom更新后执行') }) onBeforeUnmount(() => { // 执行需要访问DOM的操作 console.log('组件卸载前执行') }) onUnmounted(() => { // 执行需要访问DOM的操作 console.log('组件卸载后执行') }) onErrorCaptured(() => { // 执行需要访问DOM的操作 console.log('组件异常捕获') })}
# 通信方式(共六种)
## 1、props\emits
* 使用场景,多用于普通组件的封装,功能简单的组件,仅涉及传参和事件响应至父级- 2、v-model进行组件封装,保持父子组件的数据响应* 通过 defineEmits 声明事件,然后使用计算属性来实现父子组件数据的双向绑定<actionModal v-model="actionModalShow" :type="normalMenuInfo.type" :appId="normalMenuInfo.id"></actionModal>const emit = defineEmits(["update:modelValue"]);const props = defineProps({ modelValue: { type: Boolean, default: false, },});const close = () => { console.log("guanbi"); emit("update:modelValue", false);};
## 2、inject\provide
Vue3 中的 provide 和 inject 是一对用于实现依赖注入的 API,主要用于解决组件深层嵌套时的 prop 逐级传递问题。- 此属性为数据注入,目的是,将父组件数据同时注入多个子孙级组件进行使用+ 1、provide('theme', 'dark') // 提供静态值+ 2、const count = ref(0);provide('count', count) // 提供响应式数据+ 3、const user = reactive({ name: '小李', age: 16 });provide('user', user) // 提供响应式对象+ 4、function updateUser(){};provide('updateUser', updateUser) // 提供方法+ 1、const theme = inject('theme') // 注入基本值+ 2、const count = inject('count') // 注入响应式数据+ 3、const user = inject('user') // 注入对象+ 4、const updateUser = inject('updateUser') // 注入方法+ 5、const nonExistent = inject('nonExistent', '默认值') // 提供默认值+ 6、const complexDefault = inject('complex', () => new Map()) // 工厂函数默认值- 注入函数时要注意先写函数,后写provide提供,稳妥方式为,将注入时机放在js文件最后面,注意先后!!!<!-- 祖先组件 --><scriptsetup>import { provide, ref } from 'vue'const globalData = ref('共享数据')provide('globalData', globalData)</script><!-- 后代组件 --><scriptsetup>import { inject } from 'vue'const globalData = inject('globalData')</script>
## 3、eventBus事件总线
- vue3中已经抛弃了事件总线,如项目特殊需使用的话,可使用第三方依赖`mitt`,如需查看集成方式可参考当前目录下【1-2 依赖集成步骤.md】文件- 详细可参考项目内文件【src/utils/eventBus.ts】## 4、pinia/local storage/cookie
- 此项通信,唯一原理,是通过pinia进行全局状态的存储与管理,在pinia存储同时,进行缓存的存储- 详细可参考项目目录【src/store/index.ts】## 5、ref/$parent
- ref:此属性多用于封闭式组件,在固定的prop传参形式外,可以使用户在不影响原父子通信结构的情况下,自定义扩展- ref:使用此属性进行封装组件,需详细书写组件的使用文档,若不则易出现,组件无法使用或错用情况- $parent:此属性用于获取父组件实例,与ref为配对属性,但不建议使用,会导致父子组件高耦合,降低组件化中心思想### ref使用方式
<!-- 上传组件 --><LeeUpload ref="uploadRef" title="上传文件" :limit="1" :multiple="true" :upload-params="uploadParams" @success="handleUploadSuccess"/>
// 上传组件引用const uploadRef = ref<InstanceType<typeof LeeUpload> | null>(null);uploadRef.value.open();uploadRef.value.close();
### parent使用方式
<!-- 子组件 --><template> <div> <button @click="getParentData">获取父组件数据</button> <p>父组件的消息:{{ $parent.parentMessage }}</p> </div></template><scriptsetup>const getParentData = () => { console.log('父组件数据:', $parent.parentMessage) // 调用父组件方法 $parent.parentMethod()}</script>
<scriptsetup>import { getCurrentInstance } from 'vue'const instance = getCurrentInstance()const parent = instance.parent// 访问父组件数据console.log('父组件数据:', parent.props.someProp)console.log('父组件暴露的方法:', parent.exposed?.someMethod)</script>
## 6、v-model
- 使用vue的双向绑定,实现父子组件传参,达到v-model的数据变化及时响应效果- 此属性多用于弹出层表单的子组件,便于弹出层的开启关闭管理const emit = defineEmits(["update:modelValue"]);const props = defineProps({ modelValue: { type: Boolean, default: false, },});// 在需要更新v-model值时,使用emit向父组件响应emit("update:modelValue", false);
git 仓库地址:https://gitee.com/xiaoli-account/vue3_ts.git