练习

头像
素素
    阅读 11 分钟

    项目实战-首页

    在App.vue中完成首页导航

    <template>
    <div id="app">

    <!--头部区域-->
    <v-header :sellerData="seller"></v-header>
    <!--导航区域-->
    <div class="tabbar border-bottom">
      <router-link tag="div" class="tab-item" to="/goods">商品</router-link>
      <router-link tag="div" class="tab-item" to="/seller">评价</router-link>
      <router-link tag="div" class="tab-item" to="/ratings">商家</router-link>
    </div>
    <!--keep-alive的作用是:在router-view这个容器中所有的router-link的页面的数据都会被存储下来-->
    <keep-alive>
      <!--订单APP是个单页面的项目,所以出了v-header组件不在下面的router-view中展示外,后续其他的都是的路由页面的渲染在这里展示的,
      如果想有其他二级路由页面,只能是它的子路由页面-->
      <router-view/>
    </keep-alive>

    </div>
    </template>

    在router文件中的index.js中的配置

           import Vue from 'vue'
        import Router from 'vue-router'
        import Home from '@/pages/home/Home'
        import Goods from 'components/goods/Goods'
        import Seller from 'components/seller/Seller'
        import Ratings from 'components/ratings/Ratings'
        Vue.use(Router)
        
        export default new Router({
          routes: [
              {
                  path: '/',
                  component: Goods
              },
              {
                  path: '/goods',
                  name: 'goods',
                  component: Goods
              },
              {
                  path: '/ratings',
                  name: 'ratings',
                  component: Ratings
              },
              {
                  path: '/seller',
                  name: 'seller',
                  component: Seller
              }
          ]
        })
    
    **展示效果:**
    
      
    
    
    

    首页中导航点击高亮效果

    <div id="app"><div data-v-0c57a6db="" class="home"><div data-v-5558831a="" data-v-0c57a6db="" class="home-header">
        头部区域
    </div> 
    <div data-v-6ef9686b="" data-v-0c57a6db="" class="home-tabbar">
        <div data-v-6ef9686b="" class="tabbar border-bottom">
            <div data-v-6ef9686b="" class="tab-item router-link-exact-active router-link-active">商品</div>
             <div data-v-6ef9686b="" class="tab-item">评价</div> 
             <div data-v-6ef9686b="" class="tab-item">商家</div>
         </div>
     </div>
     </div> 
     <div data-v-371d4add="" class="goods">
        商品
    </div>
    </div>
    

    从上面的代码中可以看出来,点击哪一个导航选项【类tab-item的div】就会添加一个类名【router-link-exact-active router-link-active】,通过这个类我们就可以在这上面做文章,以实现点击时的高亮效果。

    但是【router-link-active】这个名称太长了,如果能将这个名称用别称取代就好了。通过文档我们发现,还真能取别称:

    export default new Router({

      linkActiveClass:'active',【这句代码的意思是可以给所有‘router-link-active’起个小名‘active’,给‘active’添加样式就等同于给‘router-link-active’添加样式】
      routes: [
          {
              path: '/',
              component: Goods
          },
          {
              path: '/goods',
              name: 'goods',
              component: Goods
          },
          {
              path: '/ratings',
              name: 'ratings',
              component: Ratings
          },
          {
              path: '/seller',
              name: 'seller',
              component: Seller
          }
      ]

    })

    给导航组件添加样式

    <template>
    <div class="home-tabbar">
        <div class="tabbar border-bottom">
            <router-link tag="div" class="tab-item" to="/goods">商品</router-link>
            <router-link tag="div" class="tab-item" to="/seller">评价</router-link>
            <router-link tag="div" class="tab-item" to="/ratings">商家</router-link>
        </div>
    </div>
    </template>
    
    <script>
        export default {
            name: "home-tabbar",
            components:{
            }
        }
    </script>
    
    <style scoped lang="stylus">
    .border-bottom
      &:after
         border-color rgba(7,17,27,.1)
    .tabbar
        width 100%
        display flex
        .tab-item
         flex 1
         text-align center
         height .8rem
         font-size .28rem
         line-height .8rem
         color rgb(77,85,93)
        .active
            color rgb(240,20,20)
    </style>

    呈现效果:

    clipboard.png

    如果初次打开页面我们想展示的是特定页面而不是默认路由‘/’


    export default new Router({

    linkActiveClass:'active',
    routes: [

      {
          path: '/',
          redirect:'/goods' 【这句代码的路由的重定向】
      },
      {
          path: '/goods',
          name: 'goods',
          component: Goods
      },
      {
          path: '/ratings',
          name: 'ratings',
          component: Ratings
      },
      {
          path: '/seller',
          name: 'seller',
          component: Seller
      }

    ]
    })

    css sticky footer

    如果页面内容不足够长时,页脚固定在浏览器窗口的底部;如果内容足够长时,页脚固定在页面的最底部。但如果网页内容不够长,置底的页脚就会保持在浏览器窗口底部

    链接描述

    clipboard.png

    /* 模板结构
    <div class="detail">

    <div class="detail-wrapper">
        <div class="detail-main"></div>
    </div>
    <div class="detail-close">
        <i class="icon-close"></i>
    </div>

    </div>
    */

    / CSS样式 /

    .detail-wrapper {

    width: 100%;
    min-height: 100%;

    }
    .detail-main {

    padding: 64px 0;

    }
    .detail-close {

    width: 32px;
    height: 32px;
    margin: -64px auto 0;
    font-size: 32px;

    }

    <!--遮盖层区域-->

    <div v-show="detailShow" class="detail">
        <div class="detail-wrapper clearfix">
            <div class="detail-main">
                <h1 class="name">{{sellerData.name}}</h1>
                <div class="star-wrapper">
                    星星 星星 星星 星星 星星 星星
                    <!--<star :size="48" :score="sellerData.score"></star>-->
                </div>
                <div class="title">
                    <div class="line"></div>
                    <div class="text">优惠信息</div>
                    <div class="line"></div>
                </div>
                <ul v-if="sellerData.supports" class="supports">
                    <li class="support-item" v-for="(item,index) in sellerData.supports">
                        <span class="icon" :class="classMap[sellerData.supports[index].type]"></span>
                        <span class="text">{{sellerData.supports[index].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">{{sellerData.bulletin}}</p>
                </div>
            </div>
        </div>
        <div class="detail-close" @click="closeDesc">
            <i class="icon-close"></i>
        </div>
    </div>
    

    样式:
    .detail

        position: fixed
        z-index: 100
        top: 0
        left: 0
        width: 100%
        height: 100%
        overflow: auto
        backdrop-filter: blur(10px)
        opacity: 1
        background: rgba(7, 17, 27, 0.8)
        .detail-wrapper
            width: 100%
            min-height: 100%
            .detail-main
                margin-top: 1.28rem
                padding 0 .72rem 1.28rem .72rem
                color rgb(255,255,255)
                .name
                    font-size:.32rem
                    font-weight:700
                    line-height:.32rem
                    width 100%
                    text-align center
                .star-wrapper
                    height .48rem
                    line-height .48rem
                    width 100%
                    text-align center
                    margin .32rem auto .56rem auto
                .title
                    display flex
                    justify-content center
                    align-items center
                    .line
                        flex 1
                        border-bottom: 1px solid rgba(255,255,255,0.2);
                    .text
                        font-size:.30rem
                        line-height:.30rem
                        font-weight:700
                        margin auto .24rem
    
    
                .supports
                    margin .48rem auto .56rem auto
                    .support-item
                            margin  .24rem
                            .icon
                                display: inline-block
                                width: 16px
                                height: 16px
                                vertical-align: top
                                margin-right: 6px
                                background-size: 16px 16px
                                &.decrease
                                    bg-image(('../images/header/decrease_1'))
                                &.discount
                                    bg-image(('../images/header/discount_1'))
                                &.guarantee
                                    bg-image(('../images/header/guarantee_1'))
                                &.invoice
                                    bg-image(('../images/header/invoice_1'))
                                &.special
                                    bg-image(('../images/header/special_1'))
                            .text
                                line-height: 16px
                                font-size: 12px
                .bulletin
                    .content
                        margin .48rem .24rem 0 .24rem
                        font-size:.24rem
                        font-weight:200
                        line-height:.48rem
    
        .detail-close
            position: relative
            width: 1.28rem
            height: 1.28rem
            margin: -1.28rem auto 0 auto
            clear: both
            font-size: .64rem
            color rgba(255,255,255,.5)
            
            
    
    

    星星评价组件

      <template>

    <div class="star">

     <!--动态类starType代表多尺寸的星星图片-->
     <!--下面的循环代码是将所有星星循环出来-->
     <span v-for="(itemClass,index) in itemClasses"
           :class="itemClass"
           class="star-item"
           :key="index"
     ></span>

    </div>
    </template>
    <script>

    const LENGTH = 5; //只有5颗星
    const CLS_ON = 'on'; //星星的类名
    const CLS_HALF = 'half';
    const CLS_OFF = 'off';
    export default {
        name: "Star",
        props: {
            score: {//用来确定星星图片是满星状态,半星状态,还是没有星星状态
                type: Number
            }
        },
        computed: {
            itemClasses() {  //作用是给星星图片添加类【'on','off','half'】
                let result = [];
                let score = Math.floor(this.score * 2) / 2;  //向下取0.5倍数的值
                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);
                }
                if (result.length < LENGTH) {
                    result.push(CLS_OFF);
                }
                console.log(result);
                return result;
            }
        }
    }

    </script>

    <style scoped lang="stylus">

    @import "../../assets/stylus/mixin.styl"
    .star
        font-size: 0
        .star-item
            display: inline-block
            background-repeat: no-repeat
            width: .4rem
            height: .4rem
            margin-right: .44rem
            background-size: .4rem .4rem
            &:last-child
                margin-right: 0
            &.on
                bg-image('../images/star/star48_on')
            &.half
                bg-image('../images/star/star48_half')
            &.off
                bg-image('../images/star/star48_off')
    

    </style>
    效果:

    clipboard.png

    各种icon图片组件

    bg-image($url)
    background-image: url($url + "@2x.png")
    background-repeat no-repeat
    @media (-webkit-min-device-pixel-ratio: 3),(min-device-pixel-ratio: 3)

    background-image: url($url + "@3x.png")
    background-repeat no-repeat
    

    上面代码是封装了一个图片背景函数
    <template>

    <div class="icon" :class="classMap[index]"></div>

    </template>

    <script>

    export default {
        name: "IconType",
        props:['index'],
        created(){
            this.classMap = ['decrease','discount','guarantee','invoice','special']
        }
    }

    </script>

    <style scoped lang="stylus">

    @import "../../assets/stylus/mixin";
    .icon
        display inline-block
        width .24rem
        height:.24rem
        margin-right .08rem
        background-size .24rem .24rem
        &.decrease
            bg-image(('../images/decrease_1'))
        &.discount
            bg-image(('../images/discount_1'))
        &.guarantee
            bg-image(('../images/guarantee_1'))
        &.invoice
            bg-image(('../images/invoice_1'))
        &.special
            bg-image(('../images/special_1'))

    </style>

    总结:这样在组件中每次用到这些图片的时候,就不用每次都要在组件中重新去写样式,只需要将这个组件引入就行了

    vue中使用better-scroll实现滑动效果

    1.在组件中引入import BScroll from 'better-scroll'
    2.在钩子函数created中,获取数据之后,使用$nextTick异步初始化Bscroll【如果没有用到$nextTick,会发现不能滑动,这一步很重要】

    clipboard.png
    mounted(){

            //dataLlist数据是异步加载,直接用new BScroll时,dom可能还没有更新
            this.$nextTick(()=>{ //this.$nextTick()将回调延迟到下次 DOM 更新循环之后执行,使用$nextTick异步初始化Bscroll
                this.meunScroll=new BScroll(this.$refs.left);
                this.foodScroll=new BScroll(this.$refs.right);
            })
        },
    
    

    素素
    37 声望0 粉丝