Vue3+TSX开发模式下内置组件的替代方案
问题:
开发模式为 Vue3+TSX, 无法通过Vue的内置组件<component />
实现动态组件,代码为:
import { defineComponent } from 'vue'
import Comp1 from './components/xxx'
export default defineComponent({
name: 'App',
components: {
xxx
},
setup (){
return {}
},
render() {
return (
<component is={ 'Comp' }></component>
)
}
})
可是却未能生效,且有以下提示,大概意思就是组件没有注册,但是不知道在哪里引入vue的内置组件:
原因:
以下内容摘自文档
<component>
和 is
在底层实现里,模板使用 resolveDynamicComponent
来实现 is
attribute。如果我们在 render
函数中需要 is
提供的所有灵活性,我们可以使用同样的函数:
const { h, resolveDynamicComponent } = Vue
// ...
// `<component :is="name"></component>`
render() {
const Component = resolveDynamicComponent(this.name)
return h(Component)
}
就像 is
, resolveDynamicComponent
支持传递一个组件名称、一个 HTML 元素名称或一个组件选项对象。
通常这种程度的灵活性是不需要的。通常resolveDynamicComponent
可以被换做一个更直接的替代方案。
例如,如果我们只需要支持组件名称,那么可以使用resolveComponent
来代替。
如果 VNode 始终是一个 HTML 元素,那么我们可以直接把它的名字传递给 h:
// `<component :is="bold ? 'strong' : 'em'"></component>`
render() {
return h(this.bold ? 'strong' : 'em')
}
同样,如果传递给 is
的值是一个组件选项对象,那么不需要解析什么,可以直接作为 h
的第一个参数传递。
与 <template>
标签一样,<component>
标签仅在模板中作为语法占位符需要,当迁移到 render
函数时,应被丢弃。
内置组件
诸如 <keep-alive>
、<transition>
、<transition-group>
和<teleport>
等内置组件默认并没有被全局注册。这使得打包工具可以 tree-shake,因此这些组件只会在被用到的时候被引入构建。不过这也意味着我们无法通过 resolveComponent
或 resolveDynamicComponent
访问它们。
在模板中这些组件会被特殊处理,即在它们被用到的时候自动导入。当我们编写自己的 render
函数时,需要自行导入它们:
诸如 <KeepAlive>
、<Transition>
、<TransitionGroup>
、<Teleport>
和 <Suspense>
等内置组件在渲染函数中必须导入才能使用:
import { h, KeepAlive, Teleport, Transition, TransitionGroup } from 'vue'
export default {
setup () {
return () => h(Transition, { mode: 'out-in' }, /* ... */)
}
}
如果不用h函数 用jsx语法怎么写呢?
像tsx 和 jsx 的方式写组件 ,本来就会缺少一些.vue
组件的一些东西 ,像这种情况 ,想使用 teleport 那就从vue 中 import , 名字是 大写字母开头<Teleport>
,然后,components:{} 中注册一下
以上内容来自:https://segmentfault.com/q/1010000040821752?utm_source=sf-similar-question
解决:
动态组件的实现方式:
import { defineComponent, h, resolveComponent, defineAsyncComponent,ref } from 'vue';
export default defineComponent({
components:{
coma: defineAsyncComponent(() => import('./components/coma')),
comb: defineAsyncComponent(() => import('./components/comb'))
},
setup(){
let Component = ref('coma');
return ()=>(
<>
<h1>动态组件示例</h1>
<button onClick={ () => Component.value = 'coma'}>coma</button>
<button onClick={ () => Component.value = 'comb'}>comb</button>
{ h(resolveComponent(Component.value)) }
</>
);
}
})
关键步骤:
1.用defineAsyncComponent声明需要动态载入的组件
2.用resolveComponent请求组件
3.用渲染函数h加载组件
参考资料:
Vue3官方渲染函数/JSX改写案例
vue使用jsx写法如何实现动态组件功能?
vue3+tsx 内置组件不生效