vue slot插槽使用

215 阅读1分钟

插槽内容与出口

举例来说,这里有一个 <FancyButton> 组件,可以像这样使用:

<FancyButton>
  Click me! <!-- 插槽内容 -->
</FancyButton>

而 <FancyButton> 的模板是这样的:

<button class="fancy-btn"> 
  <slot></slot> <!-- 插槽出口 --> 
</button>

<slot> 元素是一个插槽出口 (slot outlet),标示了父元素提供的插槽内容 (slot content) 将在哪里被渲染。

v-slot 简写

  • v-slot 有对应的简写 #
  • 因此 <template v-slot:objForm> 可以简写为 <template #objForm>
  • 其意思就是“将这部分模板片段传入子组件的 objForm 插槽中”(objForm是插槽名字)。

使用实例:

插槽内容:父页面文件 index.vue
插槽内容:

<template #objForm="{ queryParams, methods }">......</template>

    <!-- 人员弹窗 -->
    <dutyAdd
      v-if="addPeopleDialogVisible"
      :visible.sync="addPeopleDialogVisible"
      @goback="handleAddPeopleConfirm"
      :extraParams="{ taskId, currentDate: parseTime(dateNow) }"
    >
      <template #objForm="{ queryParams, methods }">
        <el-form-item label="姓名:" prop="nickName">
          <el-input
            v-model.trim="queryParams.nickName"
            placeholder="请输入姓名"
            maxlength="50"
            oninput="value=value.replace(/%/g, '').replace(/\\/g, '')"
            show-word-limit
            clearable
          />
        </el-form-item>
      </template>
    </dutyAdd>
子页面文件 dutyAdd.vue
插槽出口:

<slot name="objForm" :queryParams="queryParams" :methods="{ handleQuery }"></slot>

<template>
  <el-dialog
    append-to-body
    :visible="visible"
    title="添加人员"
    width="95%"
    custom-class="add-people-dialog"
    :before-close="cancel"
  >
    <el-form :model="queryParams" ref="form" inline size="small" label-width="100px">
      <slot name="objForm" :queryParams="queryParams" :methods="{ handleQuery }"></slot>
      <el-form-item>
        <el-button type="primary" icon="el-icon-search" @click="handleQuery" size="mini">
          查询
        </el-button>
        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>
    <el-table ref="multipleTable" v-loading="loading" :data="tableData">
      <el-table-column label="序号" type="index" width="50" align="center" />
      <el-table-column label="姓名" prop="userName" show-overflow-tooltip />
      <el-table-column label="联系电话" prop="phonenumber" width="120" />
    </el-table>
    <div slot="footer" class="dialog-footer">
      <el-button type="primary" @click="confirm"> 确 认 </el-button>
      <el-button @click="cancel">取 消</el-button>
    </div>
  </el-dialog>
</template>
<script>
import { getScheduleUser } from "@/api/duty.js";
export default {
  props: {
    visible: {
      type: Boolean,
      default: false,
    },
    // 查询列表的url
    fetchUrl: {
      type: Function,
      default: (v) => getScheduleUser(v),
    },
    // 额外的参数 - 请求必要的参数,又无法通过slots传入
    extraParams: {
      type: Object,
      default: () => {},
    },
  },
  data() {
    return {
      getScheduleUser,
      loading: false,
      // 表单查询项
      queryParams: {
        organizationIds: [], // 单位名称 id 集合
        nickName: "", // 姓名
      },
      // 当前查询到的列表数据
      tableData: [],
    };
  },
  mounted() {
    this.handleQuery();
  },
  methods: {
    // 分页列表
    handleQuery() {
      const params = {
        ...this.queryParams,
        ...this.extraParams,
      };
      this.loading = true;
      this.fetchUrl(params).then((res) => {
          if (res.code == 200) {
            this.pagination.total = res.total;
            this.tableData = res.rows;
          }
        }).finally(() => {
          this.loading = false;
        });
    },
  },
};
</script>