Vue.js前端专刊Vue

Vue.js第6课-项目实战-首页开发(part02)

2019-05-26  本文已影响295人  e20a12f8855d

四、图标区域页面布局与逻辑实现

和上一节首页轮播图一样,我们再创建一个分支 home-icons 并切换到这个分支,将图标区域组件提交到这个分支上去。流程一样,先新建一个 icons.vue,然后在 Home.vue 中引入这个组件,最后编辑这个组件的布局样式就行。

注意,这块也应该是一个轮播效果,当图标超过8个的时候,在第二屏展示,可以根据 swiper.vue 对布局进行一个配置,在去哪网上找一些图标素材,把数据添加到组件的 data 下,通过 v-for 渲染出来。

页面的布局样式我就不多说了,可以参考我写的结构样式:

icons.vue

<template>
  <div class="icon_list">
    <swiper :options="swiperOption">
      <swiper-slide>
        <ul class="ul">
          <li class="li" v-for="item of iconList" :key="item.id">
            <a href class="a">
              <img :src="item.imgSrc" alt class="ico">
              <span class="txt">{{item.txt}}</span>
            </a>
          </li>
        </ul>
      </swiper-slide>
      <div class="swiper-pagination" slot="pagination"></div>
    </swiper>
  </div>
</template>

<script>
export default {
  name: "HomeIcons",
  data() {
    return {
      swiperOption: {
        loop: false,
        pagination: {
          el: ".swiper-pagination"
        }
      },
      iconList: [
        {
          id:'001',
          imgSrc:
            "http://img1.qunarzz.com/piao/fusion/1803/95/f3dd6c383aeb3b02.png",
          txt: "景点门票"
        },
        {
          id:'002',
          imgSrc:
            "http://mp-piao-admincp.qunarzz.com/mp_piao_admin_mp_piao_admin/admin/20193/f0f00d6dfe038c044dbc9a437f58b0eb.png",
          txt: "一日游"
        },
        {
          id:'003',
          imgSrc:
            "http://img1.qunarzz.com/piao/fusion/1804/ff/fdf170ee89594b02.png",
          txt: "北京必游"
        },
        {
          id:'004',
          imgSrc:
            "http://img1.qunarzz.com/piao/fusion/1803/47/c2b659e048b11602.png",
          txt: "溜娃游"
        },
        {
          id:'005',
          imgSrc:
            "http://mp-piao-admincp.qunarzz.com/mp_piao_admin_mp_piao_admin/admin/20191/0334cf5430b9b5505fd79e2b8d7e8670.png",
          txt: "爬长城"
        },
        {
          id:'006',
          imgSrc:
            "http://img1.qunarzz.com/piao/fusion/1803/6c/9e54a8540fee0102.png",
          txt: "故宫"
        },
        {
          id:'007',
          imgSrc:
            "http://img1.qunarzz.com/piao/fusion/1803/76/eb88861d78fb9902.png",
          txt: "动植物园"
        },
        {
          id:'008',
          imgSrc:
            "http://mp-piao-admincp.qunarzz.com/mp_piao_admin_mp_piao_admin/admin/20195/35d83bb968d80d54926f30cfb92cb6ff.png",
          txt: "限时抢购"
        },
        {
          id:'009',
          imgSrc:
            "http://mp-piao-admincp.qunarzz.com/mp_piao_admin_mp_piao_admin/admin/20194/b4511345827006994aa1980a3886f0ac.png",
          txt: "北京世园会"
        }
      ]
    };
  }
};
</script>

<style lang="stylus" scoped>
.icon_list >>> .swiper-container {
  height: 2.8rem;
}
.icon_list {
  margin: 0.24rem 0;
  .ul {
    overflow: hidden;
    margin: 0 -0.1rem;
    .li {
      width: 25%;
      float: left;
      box-sizing: border-box;
      padding: 0.08rem 0.1rem;
      .a {
        color: #333;
        font-size: 0.26rem;
        text-align: center;
        display: block;
        .ico {
          width: 1rem;
          height: 1rem;
        }
        .txt {
          display: block;
          font-size: 0.24rem;
        }
      }
    }
  }
}
</style>

上面代码中我添加了9个图标项,因为设置了轮播区域的高度,所以只显示出8个,如果想在第二屏显示剩下的轮播项该怎么做?我们可以通过 computed 属性来计算,回忆一下 "Vue.js第2课-基础" 中的 computed 计算属性,它自带缓存机制,语法又比较简单。

修改一下 icons.vue 中 js 部分的代码:

icons.vue

export default {
  name: "HomeIcons",
  data() {
    return {
      swiperOption: {
        loop: false,
        pagination: {
          el: ".swiper-pagination"
        }
      },
      iconList: [
        // ...
      ]
    };
  },
  computed: {
    pages() {
      const pages = [];
      this.iconList.forEach((item, index) => {
        const page = Math.floor(index / 8);
        if (!pages[page]) {
          pages[page] = [];
        }
        pages[page].push(item);
      });
      return pages;
    }
  }
};

上面代码中,我们定义了一个 pages 属性,他返回一个内容,这个内容中先定义了一个数组 pages,这个数组就是最外层的一个数组,然后通过 forEach 便历 iconList,forEach 中传一个函数,他接收两个参数,第一个是便历出的每一项,第二个是每一项的下标,然后再定义一个 page,当前下标对应的数据应该展示在轮播图的第几屏,这个页码我们通过 Math.floor(向下取整)来计算,假设第3个数据,index 对应的是2,Math.floor(2/8) 是0,所以应该展示在第0页上,如果是第9个数据,index 对应的就是 8,Math.floor(8/8) 是1,所以第9个数据就会展示到第二页。page 计算完后,就可以做一个判断了,如果 pages 下面的第 page 项不存在,就让他等于一个空数组,然后把 item 添加到 pages 的第 page 项中。最后还需要返回 pages 这个属性。现在 pages 和 page 的关系其实就是这样的一个二维数组,pages 里包含着两个 page:

[[1,2,3,4,5,6,7,8],[9]]

数据便历出来了,接下来就该渲染到页面了,既然 pages 是一个二维数组,那么我们在模板中也要通过两个 v-for 来循环,先在 swiper-slide 中循环 pages,决定它是几页显示,然后在图标列表中循环 page,展示出每页的图标项。

icons.vue

<template>
  <div class="icon_list">
    <swiper :options="swiperOption">
      <swiper-slide v-for="(page,index) of pages" :key="index">
        <ul class="ul">
          <li class="li" v-for="item of page" :key="item.id">
            <a href class="a">
              <img :src="item.imgSrc" alt class="ico">
              <span class="txt">{{item.txt}}</span>
            </a>
          </li>
        </ul>
      </swiper-slide>
      <div class="swiper-pagination" slot="pagination"></div>
    </swiper>
  </div>
</template>

这样就没问题了,第一屏8个图标项展示完后,第9个会显示到第二屏。

再来对模板做一个优化,如果图标下的文字多了,可能会影响页面的布局,这个时候可以通过样式来设置文字超出显示“...”:

overflow: hidden; white-space: nowrap; text-overflow: ellipsis;

其实,不仅这里会用到超出显示“...”,其他地方也会用到,那我们就可以借助 styl 提供的 mixin 对这块的代码进行封装。在 asset 下 style 目录中新建一个文件 mixins.styl,在这里定义一个 ellipsic 方法,他接收的参数就是上边这三行样式代码。

mixins.styl

ellipsic() {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

如何用这个方法呢?首先在样式中通过 import 引入这个 mixins 这个文件,然后在元素样式下直接使用 ellipsic() 就可以了,例:

<style lang="stylus" scoped>
@import "~style/mixins"
.txt {
    display: block;
    font-size: 0.24rem;
    padding:0 .1rem;
    ellipsic();
}

以上就完成了图标区域页面布局与逻辑实现,记得把代码提交到仓库,并切换到 master 分支合并

五、“推荐组件”和“周末去哪组件”开发

这两个组件我们放在一起讲,依然新建一个分支来开发,不过,我们可以试着换一种方式,使用成员协作的方式来开发(如果条件允许的话,可以试一下,两台电脑,两个用户,模拟一下协作开发)。之前两个组件都是在同一个用户账户下,新建分支,开发完成之后再提交并合并,这次,我们试一下在这个项目仓库里添加一个团队成员,在他的账户上开发这个两个组件,再提交。具体操作方法可以参考我的 “如何在GitHub上协作开发项目” 这篇文章。

接下来,在这个新成员的账户环境下我们开始开发“推荐组件”和“周末去哪组件”这部分。首先还是新建并切换到 index-recommend 这个分支上,流程和之前的几个组件一样,先在 home 目录下的 components 目下新建一个 recommend.vue 文件和 weekend.vue,编写布局结构和逻辑代码,然后在 Home.vue 中引用这个两个组件,布局样式我就不多讲解了,可以参考我写好的布局样式,或上去哪网看一下。

recommend.vue

<template>
  <div class="rec_wrap">
    <div class="rw_tit">猜你喜欢</div>
    <div class="rw_list">
      <div class="rl_li border-bottom" v-for="item of recommendList" :key="item.id">
        <a href class="a">
          <div class="pic">
            <img :src="item.imgUrl" alt class="img">
          </div>
          <div class="info">
            <div class="tit">{{item.infoTit}}</div>
            <div class="txt">{{item.infoTxt}}</div>
            <div class="money">
              <b class="b">¥</b>
              <i class="i">{{item.infoMoney}}</i>起
            </div>
          </div>
        </a>
      </div>
    </div>
    <div class="rw_more">
      <a href class="a">查看所有产品</a>
    </div>
  </div>
</template>

<script>
export default {
  name: "HomeRecommend",
  data() {
    return {
      recommendList: [
        {
          id: "001",
          imgUrl:
            "http://img1.qunarzz.com/sight/p0/1902/84/84696f368bbec10da3.img.jpg_200x200_50323152.jpg",
          infoTit: "北京世界园艺博览会",
          infoTxt: "80条评论",
          infoMoney: "108"
        },
        {
          id: "002",
          imgUrl:
            "http://img1.qunarzz.com/sight/p0/1409/19/adca619faaab0898245dc4ec482b5722.jpg_200x200_1bc99086.jpg",
          infoTit: "故宫",
          infoTxt: "659条评论",
          infoMoney: "60"
        }
      ]
    };
  }
};
</script>

<style lang="stylus" scoped>
@import '~style/mixins';
@import '~style/varibles';

.rec_wrap {
  .rw_tit {
    font-size: 0.32rem;
    color: #333;
    padding: 0.2rem;
  }

  .rw_list {
    .rl_li {
      padding: 0.2rem;

      .a {
        color: #333;
        display: flex;

        .pic {
          width: 2rem;
          height: 2rem;

          .img {
            width: 100%;
          }
        }

        .info {
          flex: 1;
          min-width: 0;
          padding: 0.2rem;
          box-sizing: border-box;

          .tit {
            font-size: 0.28rem;
            ellipsic();
          }

          .txt {
            font-size: 0.22rem;
            color: #666;
            margin: 0.2rem 0;
            ellipsic();
          }

          .money {
            font-size: 0.22rem;
            color: #666;

            .b {
              font-size: 0.18rem;
              color: #ff7b00;
            }

            .i {
              font-size: 0.38rem;
              color: #ff7b00;
            }
          }
        }
      }
    }
  }

  .rw_more {
    .a {
      display: block;
      text-align: center;
      font-size: 0.28rem;
      padding: 0.2rem 0;
      color: $ftColor;
    }
  }
}
</style>

补充:在原网站上每一个列表项都有一个下边的,回忆一下在(“Vue.js第5课-Vue项目预热”)[https://www.jianshu.com/p/402e35c9e978] 讲过的1像素边框的问题,那个时候在全局引入了一个 border.css,所以这个下边框就不需要在样式选择器中写了,直接在这个元素标签上加一个 border-bottom 的 class 名就可以了。

weekend.vue

<template>
  <div class="rec_wrap">
    <div class="rw_tit">周末去哪儿</div>
    <div class="rw_list">
      <div class="rl_li" v-for="item of weekendList" :key="item.id">
        <a href class="a">
          <div class="pic">
            <img :src="item.imgUrl" alt class="img">
          </div>
          <div class="info">
            <div class="tit">{{item.infoTit}}</div>
            <div class="txt">{{item.infoTxt}}</div>
          </div>
        </a>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "HomeWeekend",
  data() {
    return {
      weekendList: [
        {
          id: "001",
          imgUrl:
            "http://img1.qunarzz.com/sight/source/1603/6d/2f67ae0659f41f.jpg_r_640x214_bf6cbd0b.jpg",
          infoTit: "北京赏花好地方",
          infoTxt: "乱花渐欲迷人眼,京城赏花大搜索"
        },
        {
          id: "002",
          imgUrl:
            "http://img1.qunarzz.com/sight/source/1811/f3/86173f863bef61.jpg_r_640x214_52b003ac.jpg",
          infoTit: "京城周末撒欢",
          infoTxt: "在帝都过周末,不仅仅是城中游!"
        }
      ]
    };
  }
};
</script>

<style lang="stylus" scoped>
@import '~style/mixins';
@import '~style/varibles';

.rec_wrap {
  background-color: #f4f4f4;

  .rw_tit {
    font-size: 0.32rem;
    color: #333;
    padding: 0.2rem;
  }

  .rw_list {
    .rl_li {
      margin-bottom: 0.1rem;

      .a {
        color: #333;

        .pic {
          width: 100%;

          .img {
            width: 100%;
          }
        }

        .info {
          box-sizing: border-box;
          padding: 0.2rem;
          background-color: #fff;

          .tit {
            font-size: 0.28rem;
            ellipsic();
          }

          .txt {
            font-size: 0.22rem;
            color: #666;
            margin-top: 0.2rem;
            ellipsic();
          }
        }
      }
    }
  }
}
</style>

编写好 recommend.vue 和 weekend.vue 后,效果应该是这样的:

接下来将代码提交到远程仓库:

然后切换到主分支,并将 index-recommend 分支合并到主分支,记得,执行完合并命令后还需要 push 一下,提交到远程仓库。

到此,我们就完成了首页基本的一些内容。


长得好看的都会关注我的 o(≧v≦)o~~

上一篇 下一篇

猜你喜欢

热点阅读