仿去哪兒網webapp(一)


一,利用FastClick第三方插件來解決移動端click事件300毫秒延遲情況

1,安裝,npm  i  fastclick  -S

在main.js中引入

import FastClick from "fastclick";
FastClick.attach(document.body);

2,安裝stylus

npm i stylus stylus-loader --save-dev

3.關於移動端的尺寸計算,設計圖為750px, 以蘋果6開發(設備寬度375)

在reset.css重置樣式樣式表中可看到font-size大小, 在main.js引入reset.css

1rem = html font-size = 50px

在組件的樣式表中,可用rem來樣式作為尺寸單位

如果一個height為86px, 因為移動端一般用二倍圖來畫,所以height是43px, 再除以50, 也就是0.86rem,

 

4,阿里圖標本地引入

將阿里圖標下載到本地,在vue項目中,assets文件-style文件夾-新建iconfont文件夾,將圖標字體文件放入,在assets-stylus文件中放入iconfont.css,然后在main.js引入iconfont.css

import "./assets/style/iconfont.css";

最后,在iconfont.css中修改圖標字體的路徑(五個都要修改)

 

 

 

 

@font-face {font-family: "iconfont";
  src: url('./iconfont/iconfont.eot?t=1612861657067'); /* IE9 */
  src: url('./iconfont/iconfont.eot?t=1612861657067#iefix') format('embedded-opentype'), /* IE6-IE8 */
  url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAANIAAsAAAAAB1QAAAL6AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDHAqCCIF9ATYCJAMQCwoABCAFhG0HTht1BsgeB+XGM0sZRXL+HcHX2G/f3X0VSJJEI0PFO4npJqERSWKx0SiJ7CXwk13+y02MdiKdupif3OzO7E4Ws/wCOrmT2lz3jUrqkoC///9zTb4SX307m0tUU0Ta0d4Ax60Dimoa2SYyMZ8T8NZlHCfQNKNK1G5n/0SIV1jjAnHNZAHicy5FEaJ1oVqztIhXiFFPd74RAC/h9+MPwhFPUsmsk/ZPOyRo/iz6tAGtGAUz82pYMZ8VwioyVoFCnNfaD6E4tAppar2jrQN1dYm52sKfNozOGNkxz/7LIySZqLIy22CNCWc+i1yS4DNMkvjckCHDDzHUvVFkD7hiiSlZQDNKtu7u3kinVpSTvZsPr8yl+1bmyfsPnRAfPZr8+PGUhw8nPXgQcbMcSCait7Dv8MnjOZP2Hjh2IlfsuP/ZpLSH0yuypT2bqsT51+8rzQtuXpmf+z1nfjBduXHvzLJP8DTpHPr8GZ1H5zjpOXBTLjiIP9+0A925gzzJdp4LHsuBZAdKt9QcqhxzZ2HzYHArvD06dWok/2D65awFBZHJU0cKwAT45/uPVvNdQx5qBiDf+ugXUQjef/btm5NW/yc+qYCPbuspWf9F9zQAfEdBb8EHF7BlRRdZhlJUscs3nMXsZQcSmraJzxxj6NUcyonemYS6iRSSmmnI6maRQqxCRcsaVNVtQNOKrtUtIzYkSgPL1hKEvouQdL1B1hdBCvESKiZ9gap+IGg6iKwtW+aDJbbZRHCJhIcWYiZygzomNzHKHk9kTxPsrCikTSa2w7w45A8Wo13EIPYcM5x5cth1KaY213EnnUY0jWPT5sNEdP2K65q1gQCte5Nf5Dok2mEjBC5Cgg1ZCGNEnIH61V2Jpc+PR8g8GoHdQqmxT0bYHKxzLMQv2APpkhu9KPfyimMeWZjLRWGUjdNhnTSI0Gg4zKwfNIwQufyUEQFTrYBdifaV+9dX6l+4Bpqsq0ukyFGionoqGIrHYh3uOR7PFGybz6+W3H5GNWWaxgwZAAAA') format('woff2'),
  url('./iconfont/iconfont.woff?t=1612861657067') format('woff'),
  url('./iconfont/iconfont.ttf?t=1612861657067') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
  url('./iconfont/iconfont.svg?t=1612861657067#iconfont') format('svg'); /* iOS 4.1- */
}

.iconfont {
  font-family: "iconfont" !important;
  font-size: 16px;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.iconfanhui:before {
  content: "\e624";
}

.iconsousuo:before {
  content: "\e632";
}

.iconarrow-down-filling:before {
  content: "\e688";
}

 

 然后在模板中引入字體圖標類

<div class="header-left  ">h
      <span class="iconfont iconfanhui"></span>
    </div>

 

 5.將主題顏色抽離成變量,以后主題顏色修改更加方便

assets文件夾-style文件夾- 新建varibles.styl文件,寫入主題顏色

$bgColor = #00bcd4

在header組件中,引入該樣式文件,在樣式中寫入該顏色變量

<style lang="stylus"  scoped>
@import '~assets/style/varibles.styl'

.header
    display :flex
    height :0.86rem
    line-height : .86rem
    background : $bgColor
    color : #fff
    .header-left
      flex :0 0 .64rem
      color : #fff
      text-align : center
      font-size: .4rem

 

6.移動端1px像素問題

assets文件夾-style文件夾- 新建mixins.styl文件, 寫入1px的樣式, 然后組件中引入

@import "~assets/style/mixins.styl"
// 偽類+transform
// 原理:把原先元素的border去掉,然后利用:before或者:after重做border,並 transform的scale縮小一半,
// 原先的元素相對定位,新做的border絕對定位。

$color = blue

.border-1px-bottom, .border-1px-top,.border-1px-left,.border-1px-right
  position: relative


// 邊框一像素,利用偽類設置一像素
.border-1px::after
    content: "";
    box-sizing: border-box;
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    border: 1px solid $color

// 下邊框
.border-1px-bottom::after
    position :absolute
    left: 0
    bottom: 0
    width: 100%
    border-bottom: 1px solid $color
    content: ' '
    
// 上邊框
.border-1px-top::before
    position :absolute
    left: 0
    top: 0
    width: 100%
    border-top: 1px solid $color
    content: ' '


// 左邊框
.border-1px-left::before
    position :absolute
    left: 0
    top: 0
    height: 100%
    border-left: 1px solid $color
    content: ' '


// 右邊框
.border-1px-right::after
    position :absolute
    right: 0
    top: 0
    height: 100%
    border-right: 1px solid $color
    content: ' '


/*設備像素比*/
/*顯示屏最小dpr為1.5*/
@media (-webkit-min-device-pixel-ratio: 1.5),(min-device-pixel-ratio: 1.5)
  .border-1px-bottom::after,.border-1px-top::before
    // Y軸壓縮0.7,  1.5*0.7 約等於1
    -webkit-transform: scaleY(0.7)
    transform: scaleY(0.7)
  
  .border-1px-left::before,.border-1px-right::after
  // X軸壓縮0.7,  1.5*0.7 約等於1
    -webkit-transform: scaleX(0.7)
    transform: scalexX(0.7)

  .border-1px::after 
    width: 150%;
    height: 150%;
    transform: scale(0.7);
    transform-origin: 0 0;
    


@media (-webkit-min-device-pixel-ratio: 2),(min-device-pixel-ratio: 2)
  .border-1px-bottom::after,.border-1px-top::before
    // Y軸壓縮0.5,  2*0.5 等於1
    -webkit-transform: scaleY(0.5)
    transform: scaleY(0.5)
  
  .border-1px-left::before,.border-1px-right::after
  // X軸壓縮0.5,  2*0.5 等於1
    -webkit-transform: scaleX(0.5)
    transform: scaleX(0.5)

  .border-1px::after 
    width: 200%;
    height: 200%;
    transform: scale(0.5);
    transform-origin: 0 0;


@media (-webkit-min-device-pixel-ratio: 3),(min-device-pixel-ratio: 3)
  .border-1px-bottom::after,.border-1px-top::before
    -webkit-transform: scaleY(0.333)
    transform: scaleY(0.5)
  
  .border-1px-left::before,.border-1px-right::after
    -webkit-transform: scaleX(0.333)
    transform: scaleX(0.333)

  .border-1px::after 
    width: 300%;
    height: 300%;
    transform: scale(0.333);
    transform-origin: 0 0;

// 去除邊框   // 
border-none()
  &:after
    display: none

 

7.使用vue封裝的vue-awesome-swiper輪播圖插件,不是原生的swiper插件

安裝,npm install vue-awesome-swiper@4.1.1  --save

npm install swiper@5  --save

在main.js全局注冊

import VueAwesomeSwiper from "vue-awesome-swiper";

import "swiper/css/swiper.min.css";

Vue.use(VueAwesomeSwiper);

新建swiper組件

<template>
  <swiper ref="mySwiper" :options="swiperOptions">
    <swiper-slide>Slide 1</swiper-slide>
    <swiper-slide>Slide 2</swiper-slide>
    <swiper-slide>Slide 3</swiper-slide>
    
    <div class="swiper-pagination" slot="pagination"></div>
  </swiper>
</template>

<script>
export default {
  data() {
    return {
      swiperOptions: {
        pagination: {
          el: ".swiper-pagination"
        }
      }
    };
  }
};
</script>

<style scoped lang="stylus"></style>

在home父組件中引入和注冊swiper組件。

<template>
  <div>
    <HomeHeader></HomeHeader>
    <HomeSwiper></HomeSwiper>
  </div>
</template>

<script>
import HomeHeader from "components/HomeHeader/HomeHeader";
import HomeSwiper from "components/Swiper/Swiper";

8, 此時有個小bug,如果在網速條件差的情況,圖片還沒有加載完成的時候,輪播圖結構下方的結構會先占用輪播圖的位置,直到輪播圖加載完成后,才會到他正確的位置(稱為抖動情況)

原因,當圖片沒加載完成,此時圖片高度為0,下面的結構會撐上去,此時只需要計算寬高比,計算padding-bottom即可解決

 

 

解決方法,在swiper組件,新增一個根標簽div ,計算圖片的寬高比例,用樣式來解決

<template>
  <div class="wrapper">
    <swiper ref="mySwiper" :options="swiperOptions">
      <swiper-slide>
        <img class="item" src="@/assets/logo.png" alt="" />
      </swiper-slide>
      <swiper-slide>
        <img class="item" src="@/assets/logo.png" alt="" />
      </swiper-slide>
      <swiper-slide>
        <img class="item" src="@/assets/logo.png" alt="" />
      </swiper-slide>

      <div class="swiper-pagination" slot="pagination"></div>
    </swiper>
  </div>
</template>

<script>
export default {
  data() {
    return {
      swiperOptions: {
        pagination: {
          el: ".swiper-pagination"
        }
      }
    };
  }
};
</script>

<style scoped lang="stylus">
.wrapper
 overflow :hidden width:100% height:0 padding-bottom :31.25%
.item
  width:100%
</style>

 

 9,利用深度選擇器去修改輪播圖 的圓點顏色,默認是藍色,修改成紅色
直接通過.swiper-pagination-bullet-active類修改顏色是無效的,因為scoped只能修改當前組件的樣式,而swiper組件里頭的子組件是不會有效果的
需要通過深度選擇器來改變swiper子組件里頭的樣式
#Scoped CSS
當 <style> 標簽有 scoped 屬性時,它的 CSS 只作用於當前組件中的元素。這類似於 Shadow DOM 中的樣式封裝。
vue-loader官網介紹;https://vue-loader.vuejs.org/zh/guide/scoped-css.html#%E6%B7%B7%E7%94%A8%E6%9C%AC%E5%9C%B0%E5%92%8C%E5%85%A8%E5%B1%80%E6%A0%B7%E5%BC%8F
#子組件的根元素
使用 scoped 后,父組件的樣式將不會滲透到子組件中。不過一個子組件的根節點會同時受其父組件的 scoped CSS 和子組件的 scoped CSS 的影響。
這樣設計是為了讓父組件可以從布局的角度出發,調整其子組件根元素的樣式。 #深度作用選擇器 如果你希望 scoped 樣式中的一個選擇器能夠作用得“更深”,例如影響子組件,你可以使用 >>> 操作符:
<template>
  <div class="wrapper">
    <swiper ref="mySwiper" :options="swiperOptions">
      <swiper-slide>
        <img class="item" src="@/assets/logo.png" alt="" />
      </swiper-slide>
      <swiper-slide>
        <img class="item" src="@/assets/logo.png" alt="" />
      </swiper-slide>
      <swiper-slide>
        <img class="item" src="@/assets/logo.png" alt="" />
      </swiper-slide>

      <div class="swiper-pagination" slot="pagination"></div>
    </swiper>
  </div>
</template>

<script>
export default {
  data() {
    return {
      swiperOptions: {
        pagination: {
          el: ".swiper-pagination",
      loop:true
        }
      }
    };
  }
};
</script>

<style scoped lang="stylus">
.wrapper
  & >>> .swiper-pagination-bullet-active background: red
  overflow :hidden
  width:100%
  height:0
  padding-bottom :100%
  .item
    width:100%

</style>

 

 

 

 

 10.商品圖標區域布局,一個圖標

 

 

  <div class="icons">
        <div class="icon">
          <div class="icon-img">
            <img
              class="icon-img-content"
              src="//s.qunarzz.com/homenode/images/touchheader/hotel.png"
              alt=""
            />
          </div>
          <p class="icon-desc">熱門景點</p>
        </div>

樣式布局,同理,慢速網絡下對於圖片下的結構抖動情況,對用padding-bottom來代替height, 一行八個圖標,一個weidth占25%

<style scoped lang="stylus">

.icons
  margin-top:.1rem
  .icon
    float:left
    width:25% height :0 padding-bottom :25%
    position : relative
    .icon-img
      position: absolute
      top: 0
      left: 0
      right: 0
      bottom: .44rem
      padding :.1rem
      box-sizing:border-box
      .icon-img-content
        display :block
        margin :0 auto
        height :100%
        width:100%
    .icon-desc
      position: absolute
      bottom: 0
      left: 0
      right: 0
      line-height .44rem
      height .44rem
      text-align :center

如果,圖片圖標很多,需要用到swiper輪播圖來處理

  <div class="icons">
    <swiper>
      <swiper-slide>
        <div class="icon">
          <div class="icon-img">
            <img
              class="icon-img-content"
              src="//s.qunarzz.com/homenode/images/touchheader/hotel.png"
              alt=""
            />
          </div>
          <p class="icon-desc">熱門景點</p>
        </div>
      </swiper-slide>
      <swiper-slide>
        <div class="icon">
          <div class="icon-img">
            <img
              class="icon-img-content"
              src="//s.qunarzz.com/homenode/images/touchheader/hotel.png"
              alt=""
            />
          </div>
          <p class="icon-desc">熱門景點</p>
        </div>
      </swiper-slide>
    </swiper>

  </div>

此時一排圖片圖標高度占25%,兩排就占50%,而加入swiper組件后,左右滑動的高度距離只有25%, 我們需要增大他的高度為50%, 此時利用到深度選擇器

 

 樣式

.icons
  margin-top:.1rem
  & >>>.swiper-container padding-bottom : 50% height :0
  .icon
    float:left
    width:25%
    height :0
    padding-bottom :25%
    position : relative

 

11. 對於圖片圖標輪播的頁數邏輯計算以及樣式抽離公共代碼

圖片圖標的數據

 data() {
    return {
      iconList: [
        {
          id: "0001",
          imgUrl:
            "http://img1.qunarzz.com/piao/fusion/1611/54/ace00878a52d9702.png",
          desc: "景點門票"
        },
        {
          id: "0002",
          imgUrl:
            "http://img1.qunarzz.com/piao/fusion/1711/df/86cbcfc533330d02.png",
          desc: "滑雪季"
        },
        {
          id: "0003",
          imgUrl:
            "http://img1.qunarzz.com/piao/fusion/1710/a6/83f636bd75ae6302.png",
          desc: "泡溫泉"
        },
        {
          id: "0004",
          imgUrl:
            "http://img1.qunarzz.com/piao/fusion/1611/35/2640cab202c41b02.png",
          desc: "動植園"
        },
        {
          id: "0005",
          imgUrl:
            "http://img1.qunarzz.com/piao/fusion/1611/d0/e09575e66f4aa402.png",
          desc: "游樂園"
        },
        {
          id: "0006",
          imgUrl:
            "http://img1.qunarzz.com/piao/fusion/1611/59/569d3c096e542502.png",
          desc: "必游榜單"
        },
        {
          id: "0007",
          imgUrl:
            "http://img1.qunarzz.com/piao/fusion/1611/17/4bd370f3eb1acd02.png",
          desc: "演出"
        },
        {
          id: "0008",
          imgUrl:
            "http://img1.qunarzz.com/piao/fusion/1611/7f/b1ea3c8c7fb6db02.png",
          desc: "城市觀光"
        },
        {
          id: "0009",
          imgUrl:
            "http://img1.qunarzz.com/piao/fusion/1611/a9/ffc620dbda9b9c02.png",
          desc: "一日游"
        }
      ]

模板數據填充,每頁輪播圖圖片的數量是8個,第九個圖標需要在第二頁,此時根據iconList數據去計算頁數

 

 

 <div class="icons">
    <swiper>
      <!-- 輪播圖頁數 -->
      <swiper-slide >
        <div class="icon" v-for="(icon, index) in iconList" :key="icon.id">
          <div class="icon-img">
            <img class="icon-img-content" :src="icon.imgUrl" />
          </div>
          <p class="icon-desc">{{icon.desc}}</p>
        </div>
      </swiper-slide>
    </swiper>

計算頁數,用computed

  computed: {
    // 計算輪播圖每行圖片的頁數
    pages() {
      const pages = []; const { iconList } = this;
      iconList.forEach((item, index) => {
        // 計算當前圖標在第幾頁
        const page = Math.floor(index / 8); // 判斷第0個索引沒有數據,內嵌一個數組
        if (!pages[page]) {
          pages[page] = [];
        }
        // 有數據
        pages[page].push(item);
      });

      return pages;
    }
  }

在swiper模板中填充

<div class="icons">
    <swiper>
      <!-- 輪播圖頁數 -->
      <swiper-slide v-for="(page, index) in pages" :key="index">
        <div class="icon" v-for="(icon, index) in page" :key="icon.id">
          <div class="icon-img">
            <img class="icon-img-content" :src="icon.imgUrl" />
          </div>
          <p class="icon-desc">{{icon.desc}}</p>
        </div>
      </swiper-slide>
    </swiper>
  </div>

優化效果,如果圖片下方文字的數量過多,需要有省略情況

在mixins.styl中定義樣式,然后在該組件中引入,

ellipsis()
  overflow: hidden
  white-space: nowrap
  text-overflow: ellipsis    
@import '~assets/style/mixins.styl'
.icon-desc
      position: absolute
      bottom: 0
      left: 0
      right: 0
      line-height .44rem
      height .44rem
      text-align :center
      ellipsis()

 

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM