如何在运行时将插槽包装在作用域插槽中

Posted

技术标签:

【中文标题】如何在运行时将插槽包装在作用域插槽中【英文标题】:How to wrap the slot in a scoped slot at runtime 【发布时间】:2020-12-16 09:03:45 【问题描述】:

我有一个非常不寻常的场景。

<WrapperComponent>
  <InnerComponent propA="Static"></InnerComponent>
</WrapperComponent>

WrapperComponent 应该管理 InnerComponent 的所有实例。但是我不知道什么会被编译到包装器组件中。

通常我会这样做:

<WrapperComponent>
  <template scoped-slot="data">
    <InnerComponent v-for="(propB) in data" prop-b="Static" :prop-b="propB"></InnerComponent>
  </template>
</WrapperComponent>

但我不能这样做!

我需要能够在运行时创建插槽内容的多个实例。我已经用我目前得到的东西创建了一个代码沙箱。

https://codesandbox.io/s/stupefied-framework-f3z5g?file=/src/App.vue:697-774

<template>
  <div id="app">
    <WrapperComponent>
      <InnerComponent propA="Static"></InnerComponent>
    </WrapperComponent>
  </div>
</template>

<script>
import Vue from "vue";

const WrapperComponent = Vue.extend(
  name: "WrapperComponent",
  data() 
    return 
      valueMap: ["Child 1", "Child 2"]
    
  ,
  render(h) 
    return h("div", , [
      this.valueMap.map(val => 
        console.log(val);
        
        for (const slot of this.$slots.default) 
          // this is a read only slot. I can not change this.
          // However, I want multiple instances of the slot
          // => Inject a scoped-slot
          slot.componentOptions.propsData.propB = val;
        
        return h("div", , [this.$slots.default]);
      )
    ])
  
);
const InnerComponent = Vue.extend(
  name: "InnerComponent",
  props: 
    // This is a static configuration value.
    propA: String,
    // This is a runtime value. The parent component manages this component
    propB: String
  ,
  template: "<div>A: propA B: propB</div>"
);
export default 
  name: "App",
  components: 
    WrapperComponent,
    InnerComponent
  
;
</script>

这仅适用于静态信息,但我也有一些每个插槽实例不同的数据。

因为 VNode 是只读的,我无法修改 this.$slot.default.componentOptions.propsData。如果我忽略警告,结果将只是传递给插槽最后一个实例的内容。

【问题讨论】:

【参考方案1】:
 <WrapperComponent>
  <WrapperSubComponent v-for="(propB) in data" key="probB" :prop-b="prop-b"> 
    <InnerComponent propA="Static"></InnerComponent>
  </WrapperSubComponent>
</WrapperComponent>

将组件包装在另一个组件中并且只执行一次逻辑后工作。

【讨论】:

以上是关于如何在运行时将插槽包装在作用域插槽中的主要内容,如果未能解决你的问题,请参考以下文章

Vue-作用域插槽-列表组件

VueJS - 将插槽和作用域插槽向下传递给子模板中的组件

vue 作用域插槽(插槽赋值)

Vue 作用域插槽

语法糖&具名插槽&作用域插槽&混入

将图像源传递到 Vue.js 中的作用域插槽