Vue+TypeScript获取插槽文本遇TS7053错误,求正确实现方案
如何正确访问Vue组件插槽内的文本内容?
问题背景
我编写了一个GoogleTranslate.vue组件,意图将插槽内容翻译为母语,组件代码及使用方式如下:
组件代码:
<template> <div> <slot></slot> <!-- This is a tooltip from bootstrap --> <i class="ms-2 bi bi-globe" data-bs-toggle="tooltip" :title="translateText()"></i> </div> </template> <script lang="ts"> import { defineComponent } from "vue"; export default defineComponent({ name: "VueGoogleTranslate", components: {}, props: {}, mounted() {}, setup() {}, methods: { translateText() { // Get the text content of slot and translate it with the google-translate-api let textToTranslate : string = this.$slots.default[0].text; return textToTranslate; } }, data() { return {}; } }); </script> <style scoped> </style>
组件使用方式:
<GoogleTranslate> Ce test est en français et devrait être traduit en anglais. </GoogleTranslate>
执行npm run build时出现TypeScript错误:
src/components/atoms/GoogleTranslate.vue:35:40 - error TS7053: Element implicitly has an 'any' type because expression of type '0' can't be used to index type 'Slot<any>'. Property '0' does not exist on type 'Slot<any>'. 35 let textToTranslate : string = this.$slots.default[0].text; ~~~~~~~~~~~~~~~~~~~~~~
错误原因
this.$slots.default在Vue的类型定义中是Slot<any>类型,它本质是一个返回VNode数组的函数,而非直接的数组,因此不能通过[0]直接索引访问。
解决方法
要正确提取插槽文本,需先调用this.$slots.default()获取VNode列表,再递归提取所有文本内容(处理嵌套VNode的情况),同时处理空插槽的边界条件:
修改后的translateText方法:
translateText(): string { // 定义递归提取文本的辅助函数 const extractText = (vnodes: any[]): string => { return vnodes.reduce((text, vnode) => { // 如果是文本节点,直接取内容 if (vnode.type === Text) { return text + vnode.children; } // 如果是有子节点的元素,递归提取 if (vnode.children && Array.isArray(vnode.children)) { return text + extractText(vnode.children); } return text; }, '').trim(); }; // 获取插槽VNode数组,处理插槽为空的情况 const slotVNodes = this.$slots.default?.() || []; return extractText(slotVNodes); }
完整修改后的组件代码
<template> <div> <slot></slot> <!-- This is a tooltip from bootstrap --> <i class="ms-2 bi bi-globe" data-bs-toggle="tooltip" :title="translateText()"></i> </div> </template> <script lang="ts"> import { defineComponent, Text } from "vue"; export default defineComponent({ name: "VueGoogleTranslate", components: {}, props: {}, mounted() {}, setup() {}, methods: { translateText(): string { const extractText = (vnodes: any[]): string => { return vnodes.reduce((text, vnode) => { if (vnode.type === Text) { return text + vnode.children; } if (vnode.children && Array.isArray(vnode.children)) { return text + extractText(vnode.children); } return text; }, '').trim(); }; const slotVNodes = this.$slots.default?.() || []; return extractText(slotVNodes); } }, data() { return {}; } }); </script> <style scoped> </style>
说明
- 引入Vue的
Text类型判断文本节点,确保类型安全 - 递归处理嵌套VNode,可正确提取插槽内包含HTML标签或子组件时的文本内容
- 用
?.()和|| []处理空插槽场景,避免空指针错误
内容的提问来源于stack exchange,提问作者flori10
相关产品推荐
相关产品推荐

