# 插槽

# 介绍

由于在日常开发中插槽的必要性,z-element-ui 提供了很多插槽.

# table中的插槽

z-table 中使用插槽非常简单,例如 z-edit-table 就是使用 z-table 实现的.

如果需要对某一列使用插槽,直接在 z-table 标签中添加相对应的插槽,例如:

tableColumn:[
	{
		prop:'name',
		label:'姓名'
	},
	{
		prop:'age',
		label:'年龄'
	}
]

我想对 name 这一列使用 el-tag 进行展示,那么我将直接在 z-table 中加入插槽:

<z-table :tableColumn="tableColumn" :tableData="tableData">
    <template #name="scope" >
    	<el-tag> {{ scope.row.name }}  </el-tag>
    </template>
</z-table>

那如果想对 name 的表头也使用插槽呢?只需要再添加一个名称为 nameheader 的插槽,两者相互独立互不影响, 表头的命名规则就为 那一列的prop + header.

<z-table :tableColumn="tableColumn" :tableData="tableData">
    <template #name="scope" >
    	<el-tag> {{ scope.row.name }}  </el-tag>
    </template>
    <template #nameheader >
    	<el-tag> 只需要 `name` + `header`  </el-tag>
    </template>
</z-table>

注意

当你使用插槽的时候, tableColumn 中必须有该插槽对应的字段

警告

z-table 提供了几个具名插槽,在使用时应该避免与 tableColumn 的prop重复

empty:无数据时插槽

​ ``

# form中的插槽

form 表单中,主要插槽有 append prepend两种插槽, append插槽将会放置在form表单项的最前方, prepend插槽则在表单最后.

例如:

点击查看代码
<!-- @format -->

<template>
  <z-grid-form v-model="form" :rules="rules" :items="formList" label-width="140px" ref="zSlotsForm">
    <template #prepend>
      <div class="m-20">
        <span style="font-size: large; font-weight: 600">标题 </span>
        <el-tag>使用prepend插槽</el-tag>
      </div>
    </template>
    <template #append>
      <el-col :span="24" class="text-right">
        <el-tag>使用append插槽</el-tag>
        <el-button type="danger" plain @click="submit()"> 提交 </el-button>
      </el-col>
    </template>
  </z-grid-form>
</template>
<script>
export default {
  name: 'zSlotsFormDemo',
  data() {
    return {
      form: { age: '23' },
      transformData: [],
      rules: {
        age: [
          { required: true, message: '请输入姓名', trigger: 'blur' },
          { min: 2, max: 5, message: '长度在 2 到 5 个字符', trigger: 'blur' }
        ]
      },
      formList: [
        {
          prop: 'age',
          label: '年龄',
          render: ({ vmodel }) => {
            console.log('🚀 ~ vmodel:', vmodel['age']);
            return <el-input v-model={vmodel['age']} placeholder="请输入年龄" />;
          }
        },

        {
          prop: 'gender',
          label: '性别',
          render: ({ vmodel }) => {
            return (
              <el-radio-group v-model={vmodel['gender']}>
                <el-radio label={'男'}></el-radio>
                <el-radio label={'女'}></el-radio>
              </el-radio-group>
            );
          },
          defaultValue: '男'
        }
      ]
    };
  },
  mounted() {
    console.log(this.getData());
  },
  methods: {
    submit() {
      console.log(this.$refs.zSlotsForm);
      this.$refs.zSlotsForm.validate(
        (valid) => {
          this.$message.success('验证成功', valid);
        },
        (err) => {
          this.$message.error('验证失败', err);
        }
      );
    },
    async getData() {
      const { data } = await new Promise((resolve) => {
        setTimeout(() => {
          const data = [];
          for (let i = 1; i <= 15; i++) {
            data.push({
              key: i,
              label: `备选项 ${i}`,
              disabled: i % 4 === 0
            });
          }
          resolve({ data });
        }, 3000);
      });
      this.$set(this.formList[1], 'option', {
        data,
        filterable: true,
        'left-default-checked': [2, 4],
        'right-default-checked': [1, 3],
        'render-content': (h, option) => {
          return (
            <span>
              {option.key} - {option.label}
            </span>
          );
        }
      });
      console.log(this.formList[1]);
      return data;
    }
  }
};
</script>
<style scoped>
.example {
  margin-bottom: 10px;
  float: right;
}
</style>

注意

在各个表单布局下,使用插槽的方式也略有不同,例如在 z-grid-form 中插槽需要放入el-col中 以此来保持正常的布局.

# 组件中的插槽

items 中的 slots 字段中放置的插槽会放入当前 item 的组件中,例如

点击查看代码
<!-- @format -->

<template>
  <z-grid-form v-model="form" :rules="rules" :items="formList" label-width="140px" ref="zComponentSlotDemo">
    <template #prepend>
      <div class="m-20">
        <span style="font-size: large; font-weight: 600">标题 </span>
        <el-tag>使用prepend插槽</el-tag>
      </div>
    </template>
    <template #append>
      <el-col :span="24" class="text-right">
        <el-tag>使用append插槽</el-tag>
        <el-button type="danger" plain @click="submit()"> 提交 </el-button>
      </el-col>
    </template>
  </z-grid-form>
</template>
<script>
export default {
  name: 'zComponentSlotDemo',
  data() {
    return {
      form: { slots_example: [1, 2, 3], age: '23' },
      transformData: [],
      rules: {
        age: [
          { required: true, message: '请输入姓名', trigger: 'change' },
          { min: 2, max: 5, message: '长度在 2 到 5 个字符', trigger: 'change' }
        ]
      },
      formList: [
        {
          prop: 'age',
          label: '年龄',
          render: ({ vmodel }) => {
            return <el-input v-model={vmodel.age} placeholder="请输入年龄" />;
          }
        },
        {
          prop: 'slots_example',
          label: '插槽示例',
          render: 'el-transfer',
          option: {},
          slots: {
            'left-footer': () => {
              return (
                <el-button type="primary" size="small" style="margin: 5px">
                  自定义左侧底部插槽
                </el-button>
              );
            },
            'right-footer': (
              <el-button type="primary" size="small" style="margin: 5px">
                自定义右侧底部插槽123
              </el-button>
            )
          },
          on: {
            change: (e) => {
              console.log('change', e);
            },
            'left-check-change': (e) => {
              console.log('left-check-change', e);
            },
            'right-check-change': (e) => {
              console.log('right-check-change', e);
            }
          }
        }
      ]
    };
  },
  mounted() {
    console.log(this.getData());
  },
  methods: {
    submit() {
      this.$refs.zSlotsForm.validate(
        (valid) => {
          console.log('🚀 ~ valid:', this.form);

          this.$message.success('验证成功', valid);
        },
        (err) => {
          this.$message.error('验证失败', err);
        }
      );
    },
    async getData() {
      const { data } = await new Promise((resolve) => {
        setTimeout(() => {
          const data = [];
          for (let i = 1; i <= 15; i++) {
            data.push({
              key: i,
              label: `备选项 ${i}`,
              disabled: i % 4 === 0
            });
          }
          resolve({ data });
        }, 3000);
      });
      this.$set(this.formList[1], 'option', {
        data,
        filterable: true,
        'left-default-checked': [2, 4],
        'right-default-checked': [1, 3],
        'render-content': (h, option) => {
          return (
            <span>
              {option.key} - {option.label}
            </span>
          );
        }
      });
      console.log(this.formList[1]);
      return data;
    }
  }
};
</script>
<style scoped>
.example {
  margin-bottom: 10px;
  float: right;
}
</style>

插槽配置的格式就为:

slots:{
	插槽名:()=>{
     	return   自定义组件 | render函数 | vNode | jsx(需要项目内支持)
    },
    插槽名:自定义组件name | render函数 | vNode | jsx(需要项目内支持)   
}