其他分享
首页 > 其他分享> > Vue 中的插槽内容穿透和配置参数过滤

Vue 中的插槽内容穿透和配置参数过滤

作者:互联网

需求描述

(以element ui组件为基础)设计一种嵌套结构,从上到下依次是:

以下实现是通过配置参数的方式动态渲染组件,避免重复书写视图模板。配置参数严格按照组件结构声明。

将“布局组”组件作为插槽内容传入“卡片组”组件,并穿透到“卡片”组件内,“布局组”会获取并绑定“卡片”组件过滤后的布局数组,以确保实际生成的页面严格遵照配置参数的结构。

由于“卡片组”和“卡片”组件是独立的,当只有一个卡片时可以不渲染“卡片组”直接生成“卡片”,更加灵活。

思路分析

Vue 的插槽语法允许将任意符合要求的文本、表达式或组件传入到子组件中。因此,可以通过嵌套插槽的方式,将传入子组件插槽的内容穿透到更深层次的子组件中,并且可以获取到深层次子组件的插槽所绑定的数据。

定义需要穿透的插槽:

<!-- 父组件 -->
···
  <!-- 将父组件的插槽内容传入子组件的插槽 -->
  <template v-slot:childSlotName="{childData}">
    <!-- 定义父组件的插槽,接收外部传入的内容 -->
    <slot name="parentSlotName" :parentData="childData"></slot>
  </template>
···
<!-- 子组件 -->
···
  <slot name="childSlotName" :childData="dataInChild"></slot>
···

代码示例

配置参数 cardList 表示一个卡片组,组内包含两个卡片,每个卡片各自包含两个 el-row 以及若干 el-col

卡片组(dyn-card-group.vue):

<template>
  <div class="dyn-card-group">
    <dyn-card
      :card="card"
      v-for="(card, index) in cardList"
      :key="index"
    >
      <!-- 插槽内容穿透到子组件,并获取子组件过滤后绑定的参数 -->
      <template v-slot:children="{children}">
        <slot
          name="children"
          :children="children"
        >
        </slot>
      </template>
    </dyn-card>
    </el-card>
  </div>
</template>
<script>
import dynCard from "./dyn-card.vue";
export default {
  name: "dyn-card-group",
  props: {
    cardList: Array,
  },
  components: {
    dynCard,
  },
};
</script>

卡片(dyn-card.vue):

<template>
  <div class="dyn-card">
    <el-card>
      <div slot="header">
        <span>{{ card.cardTitle }}</span>
      </div>

      <!-- 父组件插槽的内容会穿透到这里,并获取此处绑定的参数 -->
      <slot
        name="children"
        :children="card.children"
      ></slot>

      </el-form-item>
    </el-card>
  </div>
</template>
<script>
export default {
  name: "dyn-card",
  props: {
    card: {
      cardTitle: String,
      children: Array,
    },
  },
};
</script>

布局组(dyn-layout-group.vue):

<template>
  <div class="dyn-layout-row-group">
    <el-row
      :type="row.type"
      :gutter="row.gutter"
      :class="row.class"
      :justify="row.justify"
      :align="row.align"
      v-for="(row, index) in rowList"
      :key="index"
    >
      <el-col
        :span="col.span"
        :offset="col.offset"
        :push="col.push"
        :pull="col.pull"
        v-for="(col, index) in row.colList"
        :key="index"
      >
      </el-col>
    </el-row>
  </div>
</template>
<script>
export default {
  name: "dyn-layout-row-group",
  data() {
    return {};
  },
  props: {
    rowList: {
      requred: true,
    },
  },
};
</script>

统一导出各组件 index.js:

import dynCardGroup from './dyn-card-group.vue';
import dynCard from './dyn-card.vue';
import dynLayoutGroup from './dyn-layout-group.vue';

export { dynCardGroup, dynCard, dynLayoutGroup};

在主模块中组合三个组件并传入参数:

<template>
  <div class="container">
    <dyn-card-group :cardList="cardList">
      <!-- 布局 -->
      <template v-slot:children="{children}">
        <dyn-layout-group :rowList="children">
          <!-- 字段 -->
          <template v-slot:children>
            <div class="grid-content bg-purple">栅格</div>
          </template>
        </dyn-layout-group>
      </template>

    </dyn-card-group>
  </div>
</template>
<style lang="scss">
.el-row {
  margin-bottom: 20px;
  &:last-child {
    margin-bottom: 0;
  }
}
.grid-content {
  border-radius: 4px;
  min-height: 36px;
}
.bg-purple {
  background: rgb(218, 149, 218);
}
</style>
<script>
import {
  dynCardGroup,
  dynLayoutGroup,
} from "@/components/index";

export default {
  name: "container",
  data() {
    return {
      cardList: [
        {
          cardTitle: "卡片标题",
          // 这里的 children 属性是根据“卡片”组件的 children 属性命名的,
          // 嵌套层级增加时会导致层级辨识困难,
          // 设计时考虑到实际嵌套的组件是动态的,开发时无法确定子组件的名称,因此使用了适用范围更大的抽象命名 children,
          // 优化方法可以考虑将对象拆分,将此处的布局数组在外部定义,然后引用到此处
          children: [
            {
              gutter: 10,
              colList: [{ span: 12 }, { span: 12 }],
            },
            {
              gutter: 10,
              colList: [{ span: 6 }, { span: 6 }, { span: 6 }, { span: 6 }],
            },
          ],
        },
        {
          cardTitle: "卡片标题",
          children: [
            {
              gutter: 20,
              colList: [{ span: 12 }, { span: 12 }],
            },
            {
              type: "flex",
              justify: "space-around",
              gutter: 30,
              colList: [{ span: 6 }, { span: 6 }, { span: 6 }],
            },
          ],
        },
      ],
    };
  },
  components: {
    dynCardGroup,
    dynLayoutGroup,
  },
};
</script>

输出效果:

总结

插槽穿透:

过滤配置参数:

标签:Vue,span,卡片,插槽,穿透,dyn,组件,card
来源: https://www.cnblogs.com/cjc917/p/16214033.html