(二十三)根据对插槽作用域,具名插槽,具名插槽设置默认值的理解模仿ant-design-pro(a-table)或者vxe-table(vxe-grid)封装一个简化版的通用table模板,呢一节是接到(十九),(十九)是初步认识

用到知识点:具名插槽设置默认值,具名插槽,插槽作用域,数组循环,对象循环
实现原理: 如果父组件不传结构子组件就是默认结构,如果父组件传结构,子组件可以提供数据到父组件,父组件根据子组件传的数据传不同的结构进来

设计思路:

(1):mytable.vue作为一个通用模板(子组件)

(2)tablelist.vue调用子组件,传入行数据(data)和页面需要渲染的列数组(headercol)

(3)在子组件里面的逻辑

循环行数据:<tr v-for="(item, index) in data" :key="index">

循环页面需要渲染的列: <template v-for="(item1,index1) in headercol" :key="index1">

在循环每个数据对象里面的每一列:<template v-for="(item2, key2, index2) in item" :key="index2">

如果循环到的当前列名和数据对象的某一个列相等,就取当前数据对象的这一列的值,赋默认值给当前列的具名插槽,通过插槽作用域将值传递到父组件,方便父组件拿到数据做自定义结构的传递:

 <template v-if="item1.field==key2">
<td><slot :name="key2" :[key2]="item2">{{item2}}</slot></td>
 </template>
 </template>
<!--如果列渲染传入了操作,就定义对应的操作栏,并定义对应的插槽,将将当前行的数据提供给父组件-->
<template v-if="item1.field=='操作'">
               <td>
                 <slot name="chaozuo" :rowdata="item">
                 </slot>
                 &nbsp;&nbsp;
                 <!-- 默认插槽,如果父组件没有指定名称就会调用呢个插槽 -->
                   <slot>
                 </slot>
               </td>
            </template>
 </template>
 </tr>
(4)父组件就可以进行在调用组件的时候就可以调用插槽,传入结构
 <mytable :data="list" :headercol="column">
<template #no="{no}">
      <span style="color:red;">{{no}}</span>
    </template>
    <template #sex="{sex}">
        <span v-if="sex==1">男</span>
        <span v-if="sex==0">女</span>
    </template>
 <template #chaozuo="{rowdata}">
           <button type="button" @click="Remove(rowdata.id)">删除</button>
    </template>
   <!-- 此处没有指定插槽名称,就调用默认插槽,调用mytable里面没有指定名称得slot -->
    <button type="button" >详情</button>
  </mytable>
(5):注意:这里的#chaozuo="{rowdata}"就是 v-slot:chaozuo="{rowdata}"的简写,rowdata就是子组件插槽提供的数据,呢里提供的是行数据,操作最好提供行数据,列渲染最好只提供列数据

 以下是完代码实现:

1:父组件代码建一个tablelist.vue

<template>
  <mytable :data="list" :headercol="column">
    <template #no="{no}">
      <span style="color:red;">{{no}}</span>
    </template>
    <template #sex="{sex}">
        <span v-if="sex==1">男</span>
        <span v-if="sex==0">女</span>
    </template>
    <template #chaozuo="{rowdata}">
           <button type="button" @click="Remove(rowdata.id)">删除</button>
    </template>
    <!-- 此处没有指定插槽名称,就调用默认插槽,调用mytable里面没有指定名称得slot -->
    <button type="button" >详情</button>
  </mytable>
</template>
<script>
import mytable from "./mytable.vue";
export default {
  name: "App",
  data() {
    return {
      list: [],
      column: [
        { field: "name", title: "名字", width: 180 },
        { field: "no", title: "编号", width: 180 },
        { field: "sex", title: "性别", width: 180 },
        { field: "操作", title: "操作", width: 180 },
      ],
    };
  },
  components: {
    mytable,
  },
  created() {
    this.getDataGet();
  },
  methods: {
    getDataGet() {
      var api = "/Test/ToJson";
      var param = new URLSearchParams();
      param.append("id1", "111");
      param.append("name1", "666");
      this.$Http
        .get(api, { params: param })
        .then((response) => {
          this.list = response.data;
        })
        .catch((err) => {
          alert(err);
        });
    },
    Remove(id) {
      this.list = this.list.filter((m) => m.id != id);
    },
  },
};
</script>
2:子组件代码新建一个mytable.vue
<template>
  <table style="width: 300px;margin-left:40%;">
    <thead>
      <tr>
        <th v-for="(item, index) in headercol" :key="index">
          {{ item.title }}
        </th>
      </tr>
    </thead>
    <tbody>
      <!-- 循环数据行 -->
      <tr v-for="(item, index) in data" :key="index">

        <!-- 循环页面需要渲染得列 -->
          <template v-for="(item1,index1) in headercol" :key="index1">

           <!-- 循环每个数据行结构 -->
            <template v-for="(item2, key2, index2) in item" :key="index2">
              <!-- 将要渲染得列一个一个拿到数据行结构里面做循环对比,如果相等,就渲染当前数据结构里面得数据-->
              <template v-if="item1.field==key2">
                <!-- 用到知识点(具名插槽赋默认值,具名插槽,插槽作用域)-->
                <!--实现原理: 如果父组件不传结构给子组件就是默认结构,如果父组件传结构,子组件可以提供数据到父组件,父组件根据子组件传的数据传不同的结构进来 -->
                <td>
                    <slot :name="key2" :[key2]="item2">
                       {{item2}}
                    </slot>
                </td>
                 
               
              </template>
            </template>

             <template v-if="item1.field=='操作'">
               <td>
                 <slot name="chaozuo" :rowdata="item">
                   
                 </slot>
                 &nbsp;&nbsp;
                 <!-- 默认插槽,如果父组件没有指定名称就会调用呢个插槽 -->
                   <slot>
                   
                 </slot>
               </td>
            </template>
           

          </template>
      </tr>
    </tbody>
  </table>
</template>
<script>
export default {
  name: "MyTable",
  props: {
    data: {
      type: Array,
      required: true,
      default() {
        return [];
      },
    },
    headercol: {
      type: Array,
      required: true,
      default() {
        return [];
      },
    },
  },
  data() {
    return {};
  },
  components: {},

  methods: {},
};
</script>
3:后端api

[Route("/api/Test")]
[ApiController]
public class TestController : ControllerBase
{

[Route("ToJson")]
[HttpGet]
public string ToJson(string id1, string name1)
{
List<people> peoples = new List<people>() {
new people() { name="zhangsan",no="111",id="1",sex="0"} ,
new people() { name="zhangsan1",no = "222" ,id="2",sex="0"},
new people() { name="zhangsan2",no="333",id="3",sex="1"} ,
new people() { name="zhangsan3",no = "444" ,id="4",sex="1"}
};
string ListJson = JsonConvert.SerializeObject(peoples);
return ListJson;
}

}

public class people
{
public string id { get; set; }
public string name { get; set; }
public string no { get; set; }
public string sex { get; set; }
}

posted @   yingxianqi  阅读(537)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示