昆明网站seo服务,wordpress 点赞 开启,163企业邮箱官网入口,做问卷的网站有哪些在实际开发中#xff0c;我们通常会将某些常见组件进行二次封装#xff0c;以便更好地实现特定的业务需求。然而#xff0c;在封装 Table 组件时#xff0c;遇到一个问题#xff1a;Table 内部暴露的方法#xff0c;在封装之后的组件获取不到。
代码展示为#xff1a; …在实际开发中我们通常会将某些常见组件进行二次封装以便更好地实现特定的业务需求。然而在封装 Table 组件时遇到一个问题Table 内部暴露的方法在封装之后的组件获取不到。
代码展示为
const MyTable defineComponent({name: MyTable,props: ElTable.props,emits: Object.keys(ElTable.emits || {}),setup(props, { slots, attrs, expose }) {const tableRef refInstanceTypetypeof ElTable();return () (div classtable-containerElTableref{tableRef}{...props}{...attrs}v-slots{slots}{slots.default slots.default()}/ElTable/div);},
});
在 Element Plus 的 ElTable 组件中有很多暴露的方法如下 官方文档Table 表格 | Element Plus
但使用上面封装的 MyTable 打印组件实例时只有 table 本身的方法 下面简单分析一下原因。
1. expose 未正确定义或调用
原因分析
在 Vue 3 中expose 用于暴露子组件的方法和属性使父组件能够访问和操作它们。如果封装了 ElTable 组件但是没有正确定义 expose 或者没有通过 ref 正确引用子组件实例那么 expose 的方法无法生效。
如果在 setup 中使用 expose API 或者 expose 的位置不对那么暴露的方法就无法通过 ref 访问到。
expose({setCurrentRow: tableRef.value?.setCurrentRow, // 错误此时 tableRef.value 还可能为 nullclearSelection: tableRef.value?.clearSelection // 错误
});
解决方法确保在 setup 中正确使用 expose 并且在暴露方法时确保 tableRef 已经指向 ElTable 的实例。
2. ElTable 组件实例未传递给 tableRef
原因分析
在封装代码中ElTable 内部 expose 的方法例如setCurrentRow、clearSelection 等可能会因为 ref 没有正确透传而丢失。Vue3 中ref 的默认行为不能直接传递组件的 expose 方法到父组件中本质。
解决方法手动暴露确保 ElTable 组件通过 ref 绑定到 tableRef。
3. 组件生命周期中的调用顺序问题
原因分析
expose 需要在 setup 函数中定义而 tableRef 需要在组件挂载后才能被正确引用。如果在组件生命周期的某个不合适的时间调用 expose比如在 setup 函数之外或者组件渲染之前可能导致tableRef 无法正确指向组件实例从而无法暴露方法。
解决方法使用 nextTick 来确保组件渲染完成后再执行某些操作。
综上代码如下
import { defineComponent, ref } from vue;
import { ElTable } from element-plus;export default defineComponent({name: MyTable,props: ElTable.props,emits: Object.keys(ElTable.emits || {}),setup(props, { attrs, slots, expose }) {const tableRef refInstanceTypetypeof ElTable();// 确保暴露方法时tableRef 已经引用了正确的实例expose({setCurrentRow: (...args: ParametersInstanceTypetypeof ElTable[setCurrentRow]) tableRef.value?.setCurrentRow(...args),clearSelection: (...args: ParametersInstanceTypetypeof ElTable[clearSelection]) tableRef.value?.clearSelection(...args),});return () (div classtable-containerElTable ref{tableRef} {...props} {...attrs} v-slots{slots}{slots.default slots.default()}/ElTable/div);}
});
现在再看一下 组件实例已经存在了需要的方法。 注意在 table 内部存在很多暴露的方法要想让我们封装的 MyTable 和 ElTable 可以通用那么需要将方法全部暴露出来
export default defineComponent({name: MyTable,props: ElTable.props,emits: Object.keys(ElTable.emits || {}),setup(props, { attrs, slots, expose }) {const tableRef refInstanceTypetypeof ElTable();const ExposedMethods [clearSelection,getSelectionRows,toggleRowSelection,toggleAllSelection,toggleRowExpansion,// ...];// 将方法透传const exposedMethods: Recordstring, Function {};ExposedMethods.forEach(method {exposedMethods[method] (...args: any[]) {return tableRef.value?.[method](...args);};});// 使用 expose 透传所有方法expose(exposedMethods);return () (div classtable-containerElTable ref{tableRef} {...props} {...attrs} v-slots{slots}{slots.default slots.default()}/ElTable/div);}
});
现在所有的方法均存在后续可以直接使用我们封装的 MyTable 组件。 4. 注意
有一个坑不能将 expose 放在 onMounted 内部执行为什么呢
onMounted(() {const exposedMethods: Recordstring, Function {};ExposedMethods.forEach(method {exposedMethods[method] (...args: any[]) {return tableRef.value?.[method](...args);};});// 使用 expose 透传所有方法expose(exposedMethods);
});
1. expose 在 setup 函数内部调用时会立即暴露方法或属性给外部访问。 如果将 expose 放入 onMounted 中setup 函数的执行已经结束因此暴露的方法不会被 Vue 视为暴露的实例方法。
2. onMounted 是一个生命周期钩子函数它会在组件挂载后执行但此时 Vue 的响应式系统和父组件的访问已经设定好了因此暴露的方法不再能正确传递。