vue封装一个卡片组件

会用到的知识

  • 父组件向子组件传值
  • slot插槽
我想要做一个这样的组件

vue封装一个卡片组件_第1张图片

  • 头部基本不变,只需要改变图标和标题
  • 下面的内容需要我们改变,可以是视频、资料、新闻等。
1.先定义一个Card.vue的组件

接收父组件动态传过来的图标和标题

<template>
  <div>
    <!-- card -->
    <div class="card p-3 mt-3 bg-white">
      <div class="card-header d-flex pb-3">
        <!-- 图标 -->
        <i class="iconfont" :class="`icon-${icon}`"></i>
        <!-- 标题 -->
        <div class="fs-xl flex-1 ml-2">{{ title }}</div>
        <i class="iconfont icon-menu"></i>
      </div>
      <div class="card-body pt-3">
      <!-- slot用来接收之后的自己定义的内容,就是下面body的内容 -->
        <slot></slot>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  props: {//父组件传来的值
    title: { type: String, required: true },
    icon: { type: String, required: true }
  },
</script>

记得把组件挂载到main.js上,方便全局引用

import Card from "./components/Card";
Vue.component("m-card", Card);
2.再定义一个,CardList.vue组件

接收父组件传过来列表的数据,进行展示。并把图标和标题传给Card.vue。

<template>
  <div>
    <m-card :icon="icon" :title="title">
      <div class="body">
        <!-- 导航栏 -->
        <div class="nav pt-3 jc-between">
          <div
            class="nav-item"
            :class="{active:active===index}"
            v-for="(category,index) in categories"
            :key="index"
            @click="active = index"
          >
            <div class="nav-link">{{category.name}}</div>
          </div>
        </div>
        <!-- 轮播图 -->
        <div class="pt-2">
          <swiper>
            <swiper-slide v-for="(category,index) in categories" :key="index">
            <!-- slot接收显示的列表数据,这里要用具名的solt父组件需要拿到category这个值 -->
              <slot name="items" :category="category"></slot>
            </swiper-slide>
          </swiper>
        </div>
      </div>
    </m-card>
  </div>
</template>
<script>
export default {
  props: {
    title: { type: String, require: true },
    icon: { type: String, require: true },
    categories: { type: Array, require: true }//这是父组件传的列表数据,是个数组
  },
  data() {
    return {
      active: 0
    };
  },
};
</script>

再挂载到main.js上,方便全局引用

import ListCard from './components/ListCard'
Vue.component("m-list-card", ListCard);

注意:这两个组件的slot各自的作用

3.父组件传值
    <!-- 卡片组件 -->
    <m-list-card title="新闻资讯" icon="menu1" :categories="newsCat">
      <template v-slot:items="{ category }">
        <div
          v-for="(item, index) in category.newsList"
          :key="index"
          class="py-2"
        >
          <span>[{{ item.categoryName }}]</span>
          <span>|</span>
          <span>{{ item.title }}</span>
          <span>{{ item.date }}</span>
        </div>
      </template>
    </m-list-card>
    
    //列表数据
      newsCat: [
        {
          name: "热门",
          newsList: new Array(5).fill({}).map(() => ({
            categoryName: "公告",
            title: "这是一条广告",
            date: "06/01"
          }))
        },
        {
          name: "新闻",
          newsList: new Array(5).fill({}).map(() => ({
            categoryName: "新闻",
            title: "这是一条广告",
            date: "06/01"
          }))
        },
        {
          name: "活动",
          newsList: new Array(5).fill({}).map(() => ({
            categoryName: "活动",
            title: "这是一条广告",
            date: "06/01"
          }))
        },
        {
          name: "赛事",
          newsList: new Array(5).fill({}).map(() => ({
            categoryName: "赛事",
            title: "这是一条广告",
            date: "06/01"
          }))
        }
      ]

父组件需要传3个值

  • 父组件传(title=“新闻资讯” icon=“menu1” :categories=“newsCat”)==> CardList.vueprops)接收
  • CardList.vuetitle=“新闻资讯” icon=“menu1”)==> Card.vueprops)接收展示
  • CardList.vue:categories=“newsCat”)v-for循环展示,但是为了复用性,我们需要把里面的数据传给父组件,让父组件展示来。
  • 最后父组件通过