外卖APP项目—No.4header组件开发

外卖APP项目—No.4header组件开发

本文重点跟大家介绍外卖APP项目的header组件开发,主要包括三部分:axios应用、外部组件、详情弹层页。废话不多说,正文马上开始!

axios应用

  • header组件涉及很多商家数据,这些数据需要发送请求来获取,本项目使用axios来发送异步请求。
  • axios使用前需要手动安装,安装命令如下:

npm install axios

  • 在main.js中引入axios,具体如下:
    import { createApp } from 'vue'
    import App from './App.vue'
    import router from './router'
    import store from './store'
    import axios from 'axios'
    
    import './common/stylus/index.styl';
    
    axios.defaults.baseURL = 'http://localhost:8080/'
    
    const app = createApp(App)
    app.config.globalProperties.$http = axios
    app.use(store).use(router).mount('#app')
    
  • 在App.vue中发送请求,获取商家数据,并赋值给data中的seller对象,具体如下:
    import Header from './components/header/HeaderVue'
    export default {
    data() {
      return {
        seller: {},
      }
    },
    created() {
      this.getSeller()
    },
    methods: {
      getSeller(){
        this.$http.get('/api/data.json').then((res) => {
          // axios.get('http://localhost:8080/mock/data.json').then((res) => {
          console.log(res)
          if(res.status === 200) {
            this.seller = res.data.seller
          }
        }, err => {
          console.log(err);
        });
      },
      
    },
    components: { 
      Header
    }
    }
    

外部组件

  • 父子组件传值:通过props实现
    • App.vue通过v-bind将seller传给HeaderVue.vue
    • HeaderVue.vue通过以下方式接收seller
    props: {
          seller: {
            type: Object
          }
        }
    
  • 将resource目录中的img子目录的所有图片复制到common目录的stylus子目录下
  • 通用样式实现
    • 清除浮动:使用after伪元素(修改common目录的stylus子目录下的base.stylus文件,具体如下:)
    body,html
        line-height: 1
        font-weight: 200
        font-family: 'PingFang SC', 'STHeitisc-Light', 'Helvetica-Light', arial, sans-serif
    
    .clearfix
        display: inline-block
        &:after
            display: block
            content: "."
            height: 0
            line-height: 0
            clear: both
            visibility: hidden
    
    @media (-webkit-min-device-pixel-ratio:1.5),(min-device-pixel-ratio:1.5)
        .border-1px
            &::after
                -webkit-transform: scaleY(0.7)
                transform: scaleY(0.7)
    
    @media (-webkit-min-device-pixel-ratio:2),(min-device-pixel-ratio:2)
        .border-1px
            &::after
                -webkit-transform: scaleY(0.5)
                transform: scaleY(0.5)
    
    • 根据设备的dpr设置背景图片(修改common目录的stylus子目录下的mixin.stylus文件,具体如下:)
    border-1px($color)
        position:relative
        &:after
            display:block
            position:absolute
            left:0
            bottom:0
            width:100%
            border-top:1px solid $color
            content:''
    
    border-none()
        &:after
            display: none
    
    bg-image($url)
        background-image: url($url + "@2x.png")
        @media (-webkit-min-device-pixel-ratio: 3),(min-device-pixel-ratio: 3)
            background-image: url($url + "@3x.png")
    

渲染效果如下:

在这里插入图片描述

详情弹层页

sticky footers布局实现

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>sticky-footers布局</title>
    <style>
        body {
            width: 100vw;
            height: 100vh;
        }
        .top {
            /* 关键点1:设置内容元素的父容器的min-height: 100%; */
            min-height: 100%;
            width: 100%;
        }
        .footer {
            position: relative;
            width: 100px;
            height: 32px;
            /* 关键点3:设置底部元素的margin-top: -64px;,也就是等于内容元素的padding-bottom属性值,从而把底部元素提到内容元素的padding-bottom里 */
            margin: -64px auto 0 auto;
            clear: both;
            font-size: 32px;
        }
        .main {
            margin-top: 64px;
            /* 关键点2:设置内容元素的padding-bottom: 64px;,为底部元素预留位置 */
            padding-bottom: 64px;
        }
        .clearfix {
            display: inline-block;
        }
        .clearfix:after {
            display: block;
            content: ".";
            height: 0;
            line-height: 0;
            clear: both;
            visibility: hidden;
        }
    </style>
</head>
<body>
    <div class="top clearfix">
        <div class="main">
            This is the main content.This is the main content.This is the main content.
      Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet
      dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit
      lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit
      esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio
      dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla.
      This is the main content.This is the main content.This is the main content.
      Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet
      dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit
      lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit
      esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio
      dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla.
      This is the main content.This is the main content.This is the main content.
      Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet
      dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit
      lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit
      esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio
      dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla.
        </div>
    </div>
    <div class="footer">
        close
    </div>
</body>
</html>

渲染效果如下:
在这里插入图片描述

StarVue.vue组件实现及应用(五星评价组件)

  • 在components目录下新建star子目录,并在该子目录下新建StarVue.vue文件,文件内容具体如下:
    <template>
      <div class="star" :class="starType">
        <span v-for="(itemClass, index) in itemClasses" :key="index" :class="itemClass" class="star-item"></span>
      </div>
    </template>
    
    <script type="text/ecmascript-6">
        const LENGTH = 5
        const CLS_ON = 'on'
        const CLS_HALF = 'half'
        const CLS_OFF = 'off'
    
        export default {
        data () {
            return {}
        },
        props:{
            size:{
                type: Number
            },
            score:{
                type: Number
            }
        },
        computed:{
            starType(){
                return 'star-' + this.size;
            },
            itemClasses(){
                let result = [];
                let score = Math.floor(this.score * 2) / 2;
                let hasDecimal = score % 1 !== 0;
                let integer = Math.floor(score);
                for(let i = 0; i < integer; i++){
                    result.push(CLS_ON);
                }
                if(hasDecimal){
                    result.push(CLS_HALF);
                }
                while(result.length < LENGTH){
                    result.push(CLS_OFF);
                }
                return result;
            }
        },
        methods: {},
        }
    </script>
    
    <style lang="stylus" rel="stylesheet/stylus">
        @import "../../common/stylus/mixin.styl";
    
        .star
            z-index: 200
            font-size: 0px
            .star-item
                display: inline-block
                background-repeat: no-repeat
            &.star-48
                .star-item
                    width: 20px
                    height 20px
                    margin-right: 22px
                    background-size: 20px 20px
                    &:last-child
                        margin-right: 0
                    &.on
                        bg-image('star48_on')
                    &.half
                        bg-image('star48_half')
                    &.off
                        bg-image('star48_off')
            &.star-36
                .star-item
                    width: 15px
                    height 15px
                    margin-right: 16px
                    background-size: 15px 15px
                    &:last-child
                        margin-right: 0
                    &.on
                        bg-image('star36_on')
                    &.half
                        bg-image('star36_half')
                    &.off
                        bg-image('star36_off')
            &.star-24
                .star-item
                    width: 10px
                    height 10px
                    margin-right: 3px
                    background-size: 10px 10px
                    &:last-child
                        margin-right: 0
                    &.on
                        bg-image('star24_on')
                    &.half
                        bg-image('star24_half')
                    &.off
                        bg-image('star24_off')
    </style>
    
  • 在HeaderVue.vue中引入组件,具体如下:
    import Star from '../star/StarVue.vue'
    

flex布局实现

Flex 布局教程:语法篇
Flex 布局教程:实例篇

完整的HeaderVue.vue组件内容如下:

<template>
  <div class="header">
    <div class="content-wrapper"> 
        <div class="avater">
            <img width="64" :src="seller.avater" alt="商家头像">
            <!-- <img width="64" src="../../../static/img/01_seller_avater.png" alt="商家头像"> -->
        </div>
        <div class="content">
            <div class="title">
                <span class="brand"></span>
                <span class="name">{{seller.name}}</span>
            </div>
            <div class="description">
                {{seller.description}}/{{seller.deliveryTime}}分钟送达
            </div>
            <div v-if="seller.supports" class="support">
                <span class="icon" :class="classMap[seller.supports[0].type]"></span>
                <span class="text">{{seller.supports[0].description}}</span>
            </div>
        </div>
        <div v-if="seller.supports" class="support-count" @click="showDetail()">
            <span class="count">{{seller.supports.length}}个</span>
            <i class="icon-circle-right"></i>
        </div>
    </div>    
    <div class="bulletin-wrapper"  @click="showDetail()">
        <span class="bulletin-title"></span><span class="bulletin-text">{{seller.bulletin}}</span>
        <i class="icon-circle-right"></i>
    </div>
    <div class="background">
        <img :src="seller.avater" alt="商家头像" width="375" height="132">
    </div>
    <transition name="fade">
        <div v-show="detailShow" class="detail">
            <div class="detail-wrapper clearfix">
                <div class="detail-main">
                    <h1 class="name">{{seller.name}}</h1>
                    <div class="star-wrapper">
                        <Star :size="48" :score="seller.score"></Star>
                    </div>
                    <div class="title">
                        <div class="line"></div>
                        <div class="text">优惠信息</div>
                        <div class="line"></div>
                    </div>
                    <ul v-if="seller.supports" class="supports">
                        <li class="support-item" v-for="(item, i) in seller.supports" :key="i">
                            <span class="icon" :class="classMap[seller.supports[i].type]"></span>
                            <span class="text">{{seller.supports[i].description}}</span>
                        </li>
                    </ul>
                    <div class="title">
                        <div class="line"></div>
                        <div class="text">商家公告</div>
                        <div class="line"></div>
                    </div>
                    <div class="bulletin">
                        <p class="content">{{seller.bulletin}}</p>
                    </div>
                </div>
            </div>
            <div class="detail-close" @click="hideDetail">
                <i class="icon-cancel-circle"></i>
            </div>
        </div>
    </transition>
  </div>
</template>

<script >
    import Star from '../star/StarVue.vue'
    export default {
        data() {
            return {
                detailShow: false
            }
        },
        props: {
            seller: {
                type: Object
            }
        },
        created(){
            this.classMap = ['decrease', 'discount', 'special', 'invoice', 'guarantee']
        },
        components:{
            Star
        },
        methods: {
            showDetail(){
                this.detailShow = true
            },
            hideDetail(){
                this.detailShow = false
            }
        },
    }
</script>
  
<style lang="stylus" rel="stylesheet/stylus">
  @import "../../common/stylus/mixin.styl";

  .header
      position: relative
      overflow: hidden
      color:#fff
      background: rgba(7, 17, 27, 0.5)
      .content-wrapper
          position relative
          padding: 24px 12px 18px 24px
          font-size: 0
          .avater
              display: inline-block
              vertical-align: top
              img
                  border-radius: 2px
          .content
              display: inline-block
              margin-left: 16px
              .title
                  margin: 2px 0 8px 0
                  .brand
                      display: inline-block
                      vertical-align: top
                      width: 30px
                      height: 18px
                      bg-image('brand')
                      background-size: 30px 18px
                      background-repeat: no-repeat
                  .name
                      margin-left: 6px
                      font-size: 16px
                      line-height: 18px
                      font-weight: bold
              .description
                  margin-bottom: 10px
                  line-height: 12px
                  font-size: 12px
              .support
                  .icon
                      display: inline-block
                      vertical-align: top
                      width: 12px
                      height: 12px
                      margin-right: 4px
                      background-size: 12px 12px
                      background-repeat: no-repeat
                      &.decrease
                          bg-image('decrease_1')
                      &.discount
                          bg-image('discount_1')
                      &.guarantee
                          bg-image('gurantee_1')
                      &.invoice
                          bg-image('invoice_1')
                      &.special
                          bg-image('special_1')
                  .text
                      line-height: 12px
                      font-size: 10px
          .support-count
              position: absolute
              right: 12px
              bottom: 18px
              padding: 0 8px
              height 24px
              line-height: 24px
              border-radius: 14px
              background-color: rgba(0, 0, 0, 0.2)
              text-align: center
              .count
                  vertical-align: top
                  font-size: 10px
              .icon-circle-right
                  display: inline-block
                  margin-left: 6px
                  line-height: 24px
                  font-size: 10px
      .bulletin-wrapper
          position: relative
          height: 28px
          line-height: 28px
          padding: 0 22px 0 12px
          white-space: nowrap
          overflow: hidden
          text-overflow: ellipsis
          background: rgba(7, 17, 27, 0.2)
          .bulletin-title
              display: inline-block
              vertical-align: top
              margin-top: 8px
              width: 22px
              height: 12px
              bg-image('bulletin')
              background-size: 22px 12px
              background-repeat: no-repeat
          .bulletin-text
              vertical-align: top
              margin:0 4px 
              font-size: 10px
          .icon-circle-right
              position: absolute
              font-size: 10px 
              right: 12px
              top: 8px
      .background
          position: absolute
          top: 0
          left: 0
          width: 100%
          height: 100%
          z-index: -1
          filter: blur(10px)
      .detail
          position: fixed
          z-index: 100
          top: 0
          left: 0
          width: 100%
          height: 100%
          overflow: auto
          // transition: all 0.5s
          background: rgba(7, 17, 27, 0.8)
          backdrop-filter: blur(10px)
          &.fade-enter-active, &.fade-leave-active
              transition: all  0.5s
          &.fade-enter, &.fade-leave-to
              opacity: 0
              background: rgba(7, 17, 27, 0.8)
          // &.fade-transition
          //     opacity: 1
          //     background: rgba(7, 17, 27, 0.8)
          // &.fade-enter, &.fade-leave
          //     opacity: 0
          //     background: rgba(7, 17, 27, 0)
          .detail-wrapper
              min-height: 100%
              width: 100%
              .detail-main
                  margin-top: 64px
                  padding-bottom: 64px
                  .name
                      line-height: 16px
                      text-align: center
                      font-size: 16px
                      font-weight: 700
                  .star-wrapper
                      margin-top: 18px
                      padding: 2px 0
                      text-align-last: center
                  .title
                      display: flex
                      width: 80%
                      margin: 28px auto 24px auto
                      .line
                          flex: 1
                          position: relative
                          top:-6px
                          border-bottom: 1px solid rgba(255, 255, 255, 0.2)
                      .text
                          padding: 0 12px
                          font-weight: 700
                          font-size: 14px
                  .supports
                      width: 80%
                      margin: 0 auto
                      .support-item
                          padding: 0 12px
                          margin-bottom: 12px
                          font-size: 0
                          &:last-child
                              margin-bottom: 0
                          .icon
                              display: inline-block
                              width: 16px
                              height: 16px
                              vertical-align: top
                              margin-right: 6px
                              background-size: 16px 16px
                              background-repeat: no-repeat
                              &.decrease
                                  bg-image('decrease_2')
                              &.discount
                                  bg-image('discount_2')
                              &.guarantee
                                  bg-image('gurantee_2')
                              &.invoice
                                  bg-image('invoice_2')
                              &.special
                                  bg-image('special_2')
                          .text
                              line-height: 16px
                              font-size: 12px
                  .bulletin
                      width: 80%
                      margin: 0 auto
                      .content
                          padding: 0 12px
                          line-height: 24px
                          font-size: 12px
          .detail-close
              position: relative
              width: 32px
              height: 32px
              margin: -64px auto 0 auto
              clear: both
              font-size: 32px
</style>

渲染效果如下:

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值