美文网首页
Vue组件封装之--选项卡封装

Vue组件封装之--选项卡封装

作者: 晴天守候 | 来源:发表于2020-04-27 17:52 被阅读0次

好记性不如烂笔头,所以觉得有些常用的组件封装记录下,不但加深印象和理解,也方便为以后回头翻阅。并且在前进的路上留下脚印,以后看到也是满满的成就感的。O(∩∩)O哈哈~_

这里把一个组件分成两个来封装,第一个是基础,第二个是在第一个的基础上来继续封装的,根据使用的场景选择

主要以贴代码为主,代码很全,可以直接使用,代码比较简单,只是Vue卡槽的使用如果忘了的话就要先去了解下了

一、基础的封装card组件

1.card图片示例


card.png

card.vue代码如下,后续的引用文件也会贴出来

card.vue --template

<template>
  <div class="card bg-white p-3 mt-3">
    <div class="card-header pb-3">
      <div class="d-flex py-1 ai-center">
        <i class="iconfont fs-lg" :class="`icon-${icon}`"></i>
        <div class="flex-1 ml-2 fs-xl">{{title}}</div>
        <i class="iconfont icon-more"></i>
      </div>
      <img class="w-100 pt-3" :src="image" v-if="image" />
    </div>
    <div class="card-body pt-3">
      <slot></slot>
    </div>
  </div>
</template>

card.vue --js

export default {
  props: {
    title: { type: String, required: true },
    icon: { type: String, required: true },
    image: { type: String }
  },
  data() {
    return {};
  },
  created() {}
};

card.vue --scss

//引用的scss变量文件,然后这里可以直接用定义好的变量   注:用的是用scss写的样式
@import "../assets/scss/_variables.scss";
.card {
  .card-header {
    border-bottom: 1px solid $border-color;
  }
}
</style>

使用card组件

<m-card
      icon="heroku"
      title="英雄列表"
      image="http://ossweb-img.qq.com/upload/webplat/info/yxzj/20200108/20796372351730.jpg"
    ></m-card>

二、listCard组件

1.listCard示例图片


WeChat69bf09823a3980e3300db02a6900f670.png

listCard.vue --template:

<template>
  <div>
    <m-card :icon="icon" :title="title">
      <div class="nav jc-between">
        <div class="nav-item" :class="{active:active === i}" v-for="(category,i) in categories" :key="i">
          <div class="nav-link" @click="$refs.list.swiper.slideTo(i)">{{category.name}}</div>
        </div>
      </div>
      <div class="pt-2">
        <swiper ref="list" :options="{autoHeight:true}"
        @slide-change="()=>active = $refs.list.swiper.realIndex">
          <swiper-slide v-for="(category,i) in categories" :key="i">
            <slot name="items" :category="category"></slot>
          </swiper-slide>
        </swiper>
      </div>
    </m-card>
  </div>
</template>
export default {
  props: {
    title: { type: String, required: true },
    icon: { type: String, required: true },
    categories: { type: Array, required: true },
    image: { type: String }
  },
  data(){
    return{
      active: 0
    }
  }
};

使用listCard组件

<m-list-card icon="Menu" title="新闻资讯" :categories="newsCats">
      <template #items="{category}">
        <!--组件里的solt的name是items,所以这里的也是items -->
        <router-link
        tag="div"
        :to="`/article/${news._id}`"
        class="py-2 d-flex"
        v-for="(news,i) in category.newsList" :key="i">
          <span class="text-info">[{{news.categoryName}}]</span>
          <span class="px-2">|</span>
          <span class="flex-1 text-ellipsis text-dark-1 pr-2">{{news.title}}</span>
          <span class="text-grey-1 fs-sm">{{news.data | date}}</span>
        </router-link>
      </template>
    </m-list-card>

这里还有个造假数据的快捷方法,很方便

newsCats: [  //造假数据
        {
          name: "热门",
          newsList: new Array(5).fill(1).map(v => ({
            categoryName: "热门",
            title: "3月11日全服不停机更新公告3月11日全服不停机更新公告",
            data: "11/03"
          }))
        },
        {
          name: "新闻",
          newsList: new Array(5).fill(1).map(v => ({
            categoryName: "新闻",
            title: "3月11日全服不停机更新公告",
            data: "11/03"
          }))
        },
        {
          name: "公告",
          newsList: new Array(5).fill(1).map(v => ({
            categoryName: "公告",
            title: "3月11日全服不停机更新公告",
            data: "11/03"
          }))
        },
        {
          name: "活动",
          newsList: new Array(5).fill(1).map(v => ({
            categoryName: "活动",
            title: "3月11日全服不停机更新公告",
            data: "11/03"
          }))
        },
        {
          name: "赛事",
          newsList: new Array(5).fill(1).map(v => ({
            categoryName: "赛事",
            title: "3月11日全服不停机更新公告",
            data: "11/03"
          }))
        }
      ]

在main.js中打入组件,就可以全局使用了

import VueAwesomeSwiper from 'vue-awesome-swiper' //轮播图
// require styles
import 'swiper/dist/css/swiper.css'
import '../src/assets/scss/style.scss'
import '../src/assets/iconfont/iconfont.css'   
Vue.use(VueAwesomeSwiper, /* { default global options } */)  
//中全局引用组件,也可以在使用的地方单独引用
import Card from "../src/components/Card.vue"
Vue.component('m-card',Card);
import ListCard from "../src/components/ListCard.vue"
Vue.component('m-list-card',ListCard);

以下就是全部scss代码了。

还是比较喜欢scss来写样式,定义变量,可以轻松实现”变脸“效果。而且使用scss/less开发工具样式,还更加方便快捷。

1、_variables.scss存放样式变量(注意前面是下划线哦)

//colors
$colors:(
    'primary':#db9e3f,
    'info':#4b67af,
    'danger':#791a15,
    'blue-1':#1f3695,
    'blue':#4394e4,
    'white':#fff,
    'light':#f9f9f9,
    'light-1':#d4d9de,
    'grey':#999,
    'grey-1':#666,
    'dark-1':#343440,
    'dark':#222,
    'black':#000,
);
$border-color:map-get($colors,'light-1');
//font-size
$base-font-size:1rem;
$font-size:(
    xxs:0.6154, //8px
    xs:0.7692,  //10px
    sm:0.9231,  //12px
    md:1,       //13px
    lg:1.0769,  //14px
    xl:1.2308   //16px
);
$flex-jc:(
    start:flex-start,
    end:flex-end,
    center:center,
    between:space-between,
    around:space-around,
);
$flex-ai:(
    start:flex-start,
    end:flex-end,
    center:center,
    stretch:stretch,
);
//spacing
$spacing-types:(
    m:margin,
    p:padding);
$spacing-directions:(
    t:top,
    r:right,
    b:bottom,
    l:left);
$spacing-base-size:1rem;
$spacing-sizes:(
    0:0,
    1:0.25,
    2:0.5,
    3:1,
    4:1.5,
    5:3,
);

style.scss

//这里需要注意的,导入_variables.scss的时候不带下划线,像这样导入就好了
@import './variables';
* {
    box-sizing: border-box;
    outline: none;
}
html {
    font-size: 13px;
}
body {
    margin: 0;
    font-family: Arial, Helvetica, sans-serif;
    line-height: 1.2em;
    background: #f1f1f1;
    -webkit-font-smoothing: antialiased;
}
a {
    color: #999;
}
p{
    line-height: 1.5rem;
}
//colors
@each $colorKey,
$color in $colors {
    .text-#{$colorKey} {
        color: $color
    }
    .bg-#{$colorKey} {
        background-color: $color
    }
}
//text overflow
.text-ellipsis{
    display: inline-block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
//text-align
@each $var in (left, center, right) {
    .text-#{$var} {
        text-align: $var !important;
    }
}
//font-size
@each $sizeKey,
$size in $font-size {
    .fs-#{$sizeKey} {
        font-size: $size * $base-font-size
    }
}
//width,height
.w-100 {
    width: 100%;
}
.h-100 {
    height: 100%;
}
// flex (布局)
.d-flex {
    display: flex;
}
.flex-column {
    flex-direction: column;
}
.flex-wrap {
    flex-wrap: wrap;
}
@each $key,
$value in $flex-jc {
    .jc-#{$key} {
        justify-content: $value;
    }
}
@each $key,
$value in $flex-ai {
    .ai-#{$key} {
        align-items: $value;
    }
}
.flex-1 {
    flex: 1
}
.flex-grow-1 {
    //简写是上面的
    flex-grow: 1,
}
//spacing
@each $typeKey,
$type in $spacing-types {
    //m-1形式
    @each $sizeKey,
    $size in $spacing-sizes {
        .#{$typeKey}-#{$sizeKey} {#{$type}: $size * $spacing-base-size;}}
    //mx-1 左右、my-1上下的形式
    @each $sizeKey,
    $size in $spacing-sizes {
        .#{$typeKey}x-#{$sizeKey} {#{$type}-left: $size * $spacing-base-size;#{$type}-right: $size * $spacing-base-size;}}
    @each $sizeKey,
    $size in $spacing-sizes {
        .#{$typeKey}y-#{$sizeKey} {#{$type}-top: $size * $spacing-base-size;#{$type}-bottom: $size * $spacing-base-size;}}
    //mt-1的形式
    @each $directionKey,
    $direction in $spacing-directions {
        @each $sizeKey,
        $size in $spacing-sizes {
            .#{$typeKey}#{$directionKey}-#{$sizeKey} {#{$type}-#{$direction}: $size * $spacing-base-size;}}}
}
//button
.btn {
    border: none;
    border-radius: 0.1538rem;
    font-size: map-get($font-size, 'sm') * $base-font-size;
    padding: 0.2rem 0.6rem;
}
//nav
.nav {
    display: flex;
    .nav-item {
        border-bottom: 3px solid transparent;
        padding-bottom: 0.2rem;
        &.active {
            //在同一层,所以要用 &
            color:map-get($colors,'primary');
            border-bottom-color:map-get($colors,'primary');
        }
    }
    &.nav-inverse{
        .nav-item{
            border-bottom: 3px solid transparent;
            color:map-get($colors,'white');
            &.active{
                border-bottom-color:map-get($colors,'white');
            }
        }
    }
}
// sprite 精灵图
.sprite {
    background: url(../images/index.png) no-repeat 0 0;
    background-size: 28.8462rem;
    display: inline-block;
    &.sprite-news {
        width: 1.7692rem;
        height: 1.5385rem;
        background-position:63.546% 15.517%;
    }
    &.sprite-arrow{
        width:0.7692rem;
        height:0.7692rem;
        background-position: 38.577% 52.076%;
    }
}
//border
@each $dir in (top,right,bottom,left){
    .border-#{$dir}{
      border-#{$dir}:1px solid  $border-color;
    }
}

好了,都这里就结束了,隔了好久没写博客了,我的atom都陌生了😂。

相关文章

网友评论

      本文标题:Vue组件封装之--选项卡封装

      本文链接:https://www.haomeiwen.com/subject/nzaywhtx.html