uni-app 子组件的具名插槽如果延迟渲染的话,样式会丢失

uni-app 子组件的具名插槽如果延迟渲染的话,样式会丢失

开发环境 版本号 项目创建方式
Mac macOS Ventura版本13.6.3 CLI 2.0.2-3090920231225001
产品分类:uniapp/H5

### 示例代码:
```javascript
// 子组件  
<template>  
  <view class="card">  
    <view>我是子组件</view>  
    <view class="title" v-if="$slots.title">  
        <slot name="title"></slot>  
    </view>  
    <slot/>  
    <view class="footer" v-if="$slots.footer">  
        <slot name="footer"></slot>  
    </view>  
  </view>  
</template>  

<script>  
export default {  

}  
</script>  

<style lang="scss" scoped>  
.card {  
    border: 2upx solid #000;  
    margin-bottom: 20upx;  
    .title {  
        color: red;  
    }  
    .footer {  
        color: blue;  
    }  
}  
</style>
// 父组件  
<template>  
  <view>  

    <childComponent>  
        <template v-if="step === 1">  
            <view>我是步骤1的内容</view>  
        </template>  
        <template v-if="step === 2">  
            <view slot="title">我是步骤2的标题,我是红色的</view>  
            <view>我是步骤2的内容</view>  
            <view slot="footer">我是步骤2的FOOTER</view>  
        </template>  
    </childComponent>  
  </view>  
</template>  

<script>  
import childComponent from './_components/childComponent.vue'  
export default {  
    components: {  
        childComponent  
    },  
    data() {  
        return {  
            step: 1  
        }  
    },  
    mounted() {  
        setTimeout(() => {  
            this.step = 2;  
        }, 3000);  
    }  
}  
</script>  

<style>  

</style>

操作步骤:

代码复制粘贴至项目中,页面自动运行

预期结果:

title是红色字体,内容是黑色字体,Footer是蓝色字体

实际结果:

title是黑色字体,内容是黑色字体,Footer是蓝色字体

bug描述:

子组件的具名插槽title如果延迟渲染的话,title的样式会丢失,但是footer没问题


更多关于uni-app 子组件的具名插槽如果延迟渲染的话,样式会丢失的实战教程也可以访问 https://www.itying.com/category-93-b0.html

3 回复

子组件去掉 v-if 判断 <template>
<view class="card">
<view>我是子组件</view>
<view class="title">
<slot name="title"></slot>
</view>
<slot />
<view class="footer">
<slot name="footer"></slot>
</view>
</view>
</template>

更多关于uni-app 子组件的具名插槽如果延迟渲染的话,样式会丢失的实战教程也可以访问 https://www.itying.com/category-93-b0.html


实际业务场景中,会出现如果需要判断是否存在插槽的情况,想到了另外一个方法是用v-show

uni-app 中,如果你在子组件中使用具名插槽(Named Slot),并且延迟渲染(例如通过 v-ifv-show 控制),可能会出现样式丢失的问题。这通常是由于以下原因导致的:

1. 样式作用域问题

  • 如果你在子组件中使用了 scoped 样式,样式可能会被限制在子组件的范围内。当插槽内容延迟渲染时,这些样式可能无法正确应用到插槽内容上。
  • 解决方案:可以使用 ::v-deep/deep/ 来穿透作用域样式,确保样式能够应用到插槽内容。
/* 子组件样式 */
.child-component ::v-deep .slot-content {
  color: red;
}

2. 样式未正确加载

  • 如果插槽内容是通过异步加载的(例如通过 v-ifv-show),样式可能没有在正确的时间被加载。
  • 解决方案:确保样式在插槽内容渲染时已经加载。你可以使用 v-if 而不是 v-show,或者在插槽内容渲染后手动触发样式更新。

3. 样式优先级问题

  • 延迟渲染的内容可能会导致样式优先级问题,特别是当父组件和子组件都有相同类名的样式时。
  • 解决方案:确保样式的优先级正确,或者使用更具体的类名来避免冲突。

4. 重新渲染问题

  • 如果插槽内容在延迟渲染后重新渲染,可能会导致样式丢失。
  • 解决方案:确保插槽内容在重新渲染时样式能够正确应用,或者使用 key 属性强制重新渲染。

5. 使用 v-show 的问题

  • v-show 只是通过 display: none 来隐藏元素,而不会重新渲染。这可能会导致样式在元素显示时未正确应用。
  • 解决方案:使用 v-if 而不是 v-show,这样可以确保元素在显示时重新渲染并应用样式。

示例代码

<!-- 子组件 -->
<template>
  <div class="child-component">
    <slot name="content"></slot>
  </div>
</template>

<style scoped>
.child-component ::v-deep .slot-content {
  color: red;
}
</style>

<!-- 父组件 -->
<template>
  <child-component>
    <template v-slot:content>
      <div v-if="showContent" class="slot-content">
        这是插槽内容
      </div>
    </template>
  </child-component>
</template>

<script>
export default {
  data() {
    return {
      showContent: false
    };
  },
  mounted() {
    setTimeout(() => {
      this.showContent = true;
    }, 1000);
  }
};
</script>
回到顶部