全栈开发学习(Node+Vue+Mongodb)(八)——移动端页面搭建(主页部分)

502

前面我们完成了后台管理界面的基本功能,接下来就需要完成移动端页面的搭建与数据的展示。移动端的搭建主要以旧版王者荣耀官网主页样式为模板,本文主要介绍前端搭建的流程与一些基本组件的使用。

1 准备工作

  • 样式

    • 思路:使用SASS规范化我们的所有样式,安装:npm i -D sass sass-loader,并且将所有样式相关的内容放在style.scss中,再在main.js中应用

    • 样式重置

      /*reset*/
      *{
          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;
      }
      a{
          color: #999;
      }
      p{
          line-height: 1.5em;
      }
      
    • 色彩定义:主要分为字体颜色、背景颜色和边框色

      先定义好颜色变量

      $colors:(
          "primary":#db9e3f,
          "white":#fff,
         ...............
      );
      
      $border-color:map-get($colors, 'light-1' );  //边框色
      @each $colorKey,$color in $colors{
          .text-#{$colorKey}{   //字体颜色
              color:$color ;
          }
          .bg-#{$colorKey}{     //背景色
              background-color:$color;
          }
      }
      
    • 字体定义

      • 对齐方式

        //text-align
        @each $var in (left,center,right){
            .text-#{$var}{
                text-align: $var !important;
            }
        }
        
      • 字号

        @each $sizekey, $size in $font-sizes {
            .fs-#{$sizekey} {
             font-size: $size * $base-font-size;
            }
          }
        
      • 文字溢出

        //text-overflow
        .text-ellipsis{
            display: inline-block;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;  //不要换行
        }
        
    • 边框定义

      //borders
      @each $dir in(top,right,bottom,left){
          .border-#{$dir}{
              border-#{$dir}:1px solid $border-color;
          }
      }
      
    • 通用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;
        }
        

      flex布局的具体使用详解参考文章:www.jianshu.com/p/d9373a86b…

    • 按钮定义

    • 边距定义

      • margin

        @each $typeKey,$type in $spacing-types {
            //margin
            @each $directionKey,$direction in $spacing-directions{
                @each $sizeKey,$size in $spacing-sizes {
                     .#{$typeKey}-#{$sizeKey}{
                        #{$type}:$size*$spacing-base-size;
                     }
                    }
                }
             //margin-x,margin-y
                @each $sizeKey,$size in $spacing-sizes {
                     .#{$typeKey}x-#{$sizeKey}{
                        #{$type}-left:$size*$spacing-base-size;
                        #{$type}-right:$size*$spacing-base-size;
                     }
                     .#{$typeKey}y-#{$sizeKey}{
                        #{$type}-top:$size*$spacing-base-size;
                        #{$type}-bottom:$size*$spacing-base-size;
                     }
                    }
        
            //margin-top
            @each $directionKey,$direction in $spacing-directions{
                @each $sizeKey,$size in $spacing-sizes {
                     .#{$typeKey}#{$directionKey}-#{$sizeKey}{
                        #{$type}-#{$direction}:$size*$spacing-base-size;
                     }
                    }
                }
        }
        
      • padding 同上,只不过修改了$spacing-types为p

  • sprite图片

    使用在线图片定位工具:www.spritecow.com/,该工具可以获取一张大…

    根据获得色对图片的定义如下所示:

    &.sprite-news{
            width: 23px;
            height: 20px;
            background-position: 63.546% 15.517% ;
        }
    
  • iconfont字体图标

    在使用iconfont图标库里的图标时,将选用的图标集合下载,解压下载的文件夹并移入web/assets中

    使用图标方式:查看html文件,查看图标类名,直接在需要使用的地方引入该图标的类名

      <div class="iconfont icon-back text-blue-light" @click="$router.push('/')"></div>
    
  • 主页框架

    • 顶部提示条

      <div class="topbar bg-black py-2 px-3 d-flex ai-center" >
          <img src="../assets/images/logo.jpg" height="30">
        <div class="px-2 flex-1">
           <div class="text-white">王者荣耀</div>
           <div class="text-dark-1 fs-xs">团队成就更多</div>
         </div>
         <button type="button" class="btn bg-primary">立即下载</button>
        </div>
      
    • 导航栏

      <div class="bg-primary pt-3 pb-2">
          <div class="nav d-flex text-white jc-around pb-1" >
            <div class="nav-item active">
             <router-link to="/" class="nav-link" tag="div">首页</router-link>
            </div>
            <div class="nav-item">
             <router-link to="/" class="nav-link" tag="div">攻略中心</router-link>
            </div>
            <div class="nav-item">
             <router-link to="/" class="nav-link" tag="div">赛事中心</router-link>
            </div>
          </div>
        </div>
      

2 轮播图组件

  • 安装:github上搜索vue-swiper,执行 npm install vue-awesome-swiper --save

  • 全局引用与使用:

    //swiper组件
    import VueAwesomeSwiper from 'vue-awesome-swiper'
    import 'swiper/dist/css/swiper.css'  //引用样式
    Vue.use(VueAwesomeSwiper, /* { default global options } */)
    
  • 在Home组件中引用:

    <swiper :options="swiperOption">
          <swiper-slide>
            <img class="w-100" src="../assets/images/b9905b35bb0afa9050d9ddbe04d82d29.jpeg">
          </swiper-slide>
          <swiper-slide>
            <img class="w-100" src="../assets/images/210794580bb9303653804bb7b482f2a4.jpeg">
          </swiper-slide>
          <swiper-slide>
            <img class="w-100" src="../assets/images/ddc8c8922cbb694dfb73c86bb03fce22.jpeg">
          </swiper-slide>
        <div class="swiper-pagination pagination-home text-right px-3 pb-2" 
        slot="pagination"></div>
       </swiper>
    
    data(){
            return{
                 swiperOption: {
                   pagination: {
                   el: '.swiper-pagination'
                  }
               }, 
                newsCats:[],
                heroCats:[],
            }
        },
    
  • 小圆点的样式可以在该组件的样式下进行自定义

3 卡片组件

卡片组件在移动端使用得非常频繁,我们可以根据需求自定义组件的封装,给其他卡片组件作为一个公共的组件来复用。

定义全局组件,之后可以用m-card标签对其进行引用:

//card
import Card from './components/Card.vue'
Vue.component('m-card',Card)//定义全局组件

卡片组件的元素组成(可根据不同情况传入不同的参数达到复用的效果):

  • title(组件标题)
  • icon(组件图标)
  • plain(是否有“更多”的图标可供用户点击)
<div class="card bg-white p-3 mt-3 pb-3">
        <div class="card-header d-flex ai-center fs-lg "
         :class="{'border-bottom': !plain, 'pb-3': !plain}">
        <div class="border-bottom" v-if="!plain"></div>
            <i class="iconfont" :class="`icon-${icon}`"></i>
            <div class="fx-xl flex-1 px-2"><strong>{{title}}</strong></div>
            <i class="iconfont icon-menu1" v-if="!plain"></i>
        </div>
        <div class="card-body pt-3">
            <slot></slot>
        </div>
    </div>

4 列表卡片组件

列表卡片组件实际上就是在空白的卡片组件上进行一个扩展,其内部包含了m-card组件。同样也要对其进行全局的定义。

该组件具体的定义结构如下(此结构包含导航栏和列表轮播):

 <m-card :icon="icon" :title="title" >
       <div class="nav1 nav  jc-between">
        <div class="nav-item" :class="{active:active === i}"
        v-for="(category,i) in categories" :key="i"
        @click="$refs.list.swiper.slideTo(i)">
          <div class="nav-link">{{category.name}}</div>
        </div>
      </div>
      <div class="pt-3">
        <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>

在Main.vue中我们这样使用(其中包含可以点击跳转的文章列表链接,文章数据从后台获取):

<m-list-card icon="menu" title="新闻资讯" :categories="newsCats">
    <template #items="{category}">
      <router-link 
        tag="div"
        :to="`/articles/${news._id}`"
         class="py-2 d-flex" 
         v-for="(news,i) in category.newsList" :key="i">
            <span class="text-blue">[{{news.categoryName}}]</span>
            <span class="px-2">|</span>
            <span class="flex-1 text-dark-1 text-ellipsis pr-2">{{news.title}}</span>
            <span class="text-grey ">{{news.createdAt | date}}</span>
      </router-link>
    </template>
  </m-list-card>
  <!--end if 新闻资讯-->

5 其他细节问题

  • px转rem工具

    在扩展程序中搜索px to rem,安装; 安装完成后可以设置的默认字体大小,之后选中具体的数值,alt+z可转换为rem格式