Vue3+Vite+TS坑
shallowRef和ref
vue2中经常这样写
<component :is="currentComponent" @componentChange="onComponentChange"></component>
如果上了composition-api
,那么很可能会用ref(component)
来实现这个动态更换组件的操作。
const currentComponent = ref(Component1);
currentComponent.value = Component2;
但这样做之后得到一个warning,说是检测到我们把一个Component
弄成了reactive
对象,可能会导致不必要的性能开销。
Vue received a Component which was made a reactive object. This can lead to unnecessary performance overhead, and should be avoided by marking the component with `markRaw` or using `shallowRef` instead of `ref`.
reactive
和ref
这种都是递归监听对象中的所有属性,子属性等,现在我们需要的仅仅是当最外层的currentComponent.value
变化时,也就是我们重新设置一个组件时vue发生响应,而不是当组件中的一个属性变化时都触发响应,所以我们应该使用shallowRef
,这个不会递归监听,只是监听最外层value
的变化。
transition必须只有单根子节点
[Vue warn]: Component inside <Transition> renders non-element root node that cannot be animated.
Vue3中的transition必须只有单根子节点,component
、keep-alive
等标签不会渲染出节点,而在我的组件中又有非单根的组件。所以出现了这个错误。
解决办法就是尽量把组件写成单根。
父组件无法给子组件设置属性
场景:<script setup lang="ts">
<template>
<div class="simple-top-bar">
<!-- 给子组件设置 id -->
<IconTitleBanner id="icon-and-title" />
<LanguageSelector class="language-selector" />
</div>
</template>
<script setup lang="ts">
import LanguageSelector from "@/components/public/LanguageSelector.vue";
import IconTitleBanner from "@/components/public/IconTitleBanner.vue";
</script>
<style scoped>
.simple-top-bar {
display: flex;
flex-direction: row;
}
/* 通过id来找到子组件,设置属性 */
#icon-and-title {
flex: 1;
}
</style>
子组件
<template>
<div class="icon-and-title">
<img src="@assets/imgs/doge-icon-21.png" alt="" />
<h2 class="web-title">DOGE Admin</h2>
</div>
<div></div>
</template>
<script setup lang="ts"></script>
<style scoped>
.icon-and-title img {
display: inline-block;
width: 40px;
height: 40px;
margin-right: 10px;
}
.icon-and-title h2 {
display: inline-block;
color: white;
font-size: 1.4em;
line-height: 40px;
}
</style>
结果发现样式设不上去,id
就没绑定上去,父组件的scope也没绑定到子组件上
手动添加id和scope后样式被应用了
解决
sorry,我是傻逼,我注意到控制台有这样一条消息
不能自动继承非prop属性,因为我们的组件被渲染成Fragment或文本根节点
Vue3中的多根组件就叫Fragment组件,详见:片段
然后原因就是因为我写错了,不小心多写了个div,半小时白费。。。
子组件
<template>
<div class="icon-and-title">
<img src="@assets/imgs/doge-icon-21.png" alt="" />
<h2 class="web-title">DOGE Admin</h2>
</div>
- <div></div>
</template>