四、Vue專案去哪兒網首頁推薦和週末遊元件並使用Axios獲取資料

鐵錘妹妹。發表於2020-10-27

在碼雲建立index-recommended分支

然後在根目錄下cmd,輸入命令列

git pull
git checkout index-recommended
git status
npm run dev

在Home.vue中引用Recommend.vue元件和Weekend.vue元件

在這裡插入圖片描述

Recommend.vue元件

<template>
  <div class="recommend">
    <div class="title">熱銷推薦</div>
    <ul>
      <li
        class="item border-bottom"
        v-for="item in recommendList"
        :key="item.id"
      >
        <img class="item-img" :src="item.imgUrl" />
        <div class="item-info">
          <p class="item-title">{{ item.title }}</p>
          <p class="item-desc">{{ item.desc }}</p>
          <button class="item-button">檢視詳情</button>
        </div>
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'HomeRecommend',
  data () {
    return {
      recommendList: [
        {
          id: '0001',
          imgUrl:
            'http://img1.qunarzz.com/sight/p0/201404/23/04b92c99462687fa1ba45c1b5ba4ad77.jpg_140x140_73fda71d.jpg',
          title: '大連聖亞海洋世界',
          desc: '浪漫大連首站,浪漫的海洋主題樂園'
        },
        {
          id: '0002',
          imgUrl:
            'http://img1.qunarzz.com/sight/p0/201404/23/04b92c99462687fa1ba45c1b5ba4ad77.jpg_140x140_73fda71d.jpg',
          title: '大連聖亞海洋世界',
          desc: '浪漫大連首站,浪漫的海洋主題樂園'
        },
        {
          id: '0003',
          imgUrl:
            'http://img1.qunarzz.com/sight/p0/201404/23/04b92c99462687fa1ba45c1b5ba4ad77.jpg_140x140_73fda71d.jpg',
          title: '大連聖亞海洋世界',
          desc: '浪漫大連首站,浪漫的海洋主題樂園'
        }
      ]
    }
  }
}
</script>

<style lang="scss" scoped>
.title {
  line-height: 0.8rem;
  background: #eee;
  text-indent: 0.2rem;
  margin-top: 0.2rem;
  font-size: 0.32rem;
  font-weight: 500;
}
.item {
  overflow: hidden;
  display: flex;
  height: 1.9rem;
  // background: red;
  .item-img {
    width: 1.7rem;
    height: 1.7rem;
    padding: 0.2rem;
  }
  .item-info {
    flex: 1;
    padding: 0.2rem;
    // 讓省略號顯示出來
    min-width: 0;
    .item-title {
      line-height: 0.54rem;
      font-size: 0.32rem;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
    }
    .item-desc {
      line-height: 0.4rem;
      color: #ccc;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
    }
    .item-button {
      line-height: 0.44rem;
      margin-top: 0.16rem;
      background: #ff9300;
      padding: 0 0.2rem;
      border-radius: 0.06rem;
      color: #fff;
    }
  }
}
</style>

Weekend.vue元件

<template>
  <div class="recommend">
    <div class="title">週末去哪兒</div>
    <ul>
      <li
        class="item border-bottom"
        v-for="item in recommendList"
        :key="item.id"
      >
        <!-- 防止網速慢的情況下抖動 -->
        <div class="item-img-wrapper">
          <img class="item-img" :src="item.imgUrl" />
        </div>
        <div class="item-info">
          <p class="item-title">{{ item.title }}</p>
          <p class="item-desc">{{ item.desc }}</p>
        </div>
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'HomeWeekend',
  data () {
    return {
      recommendList: [
        {
          id: '0001',
          imgUrl:
            'http://img1.qunarzz.com/sight/source/1505/9f/f585152825459.jpg_r_640x214_5d46e4cc.jpg',
          title: '大連聖亞海洋世界',
          desc: '浪漫大連首站,浪漫的海洋主題樂園'
        },
        {
          id: '0002',
          imgUrl:
            'http://img1.qunarzz.com/sight/source/1505/9f/f585152825459.jpg_r_640x214_5d46e4cc.jpg',
          title: '大連聖亞海洋世界',
          desc: '浪漫大連首站,浪漫的海洋主題樂園'
        },
        {
          id: '0003',
          imgUrl:
            'http://img1.qunarzz.com/sight/source/1505/9f/f585152825459.jpg_r_640x214_5d46e4cc.jpg',
          title: '大連聖亞海洋世界',
          desc: '浪漫大連首站,浪漫的海洋主題樂園'
        }
      ]
    }
  }
}
</script>

<style lang="scss" scoped>
.title {
  line-height: 0.8rem;
  background: #eee;
  text-indent: 0.2rem;
  margin-top: 0.2rem;
  font-size: 0.32rem;
  font-weight: 500;
}
.item-img-wrapper {
  overflow: hidden;
  height: 0;
  padding-bottom: 33.9%;
  .item-img {
    width: 100%;
  }
}
.item-info {
    padding: 0.2rem;
    // 讓省略號顯示出來
    min-width: 0;
    .item-title {
      line-height: 0.54rem;
      font-size: 0.32rem;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
    }
    .item-desc {
      line-height: 0.4rem;
      color: #ccc;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
    }
  }
</style>


效果如下:
在這裡插入圖片描述

ajax請求

Vue官方現在推薦我們使用axios請求介面,axios是基於promise的http請求客戶端

使用npm安裝axios

npm install axios
or
npm i axios

然後在要使用的元件Home.vue中引入axios

在static靜態目錄下建立介面的json資料。訪問本地json的話,本地json必須放到static下面
在這裡插入圖片描述

在.gitignore裡新增下static/mock,這樣就不會提交到git倉庫裡在這裡插入圖片描述
不要直接將static路由暴露,需要重定向,在config/index.js配置即可

在這裡插入圖片描述
如果配置檔案發生改變,需要重新啟動應用npm run dev

Home.vue
這裡用到了父元件給子元件傳值

<template>
  <div>
    <home-header :city="city"></home-header>
    <home-swiper :list="swiperList"></home-swiper>
    <home-icons :list="iconList"></home-icons>
    <home-recommend :list="recommendList"></home-recommend>
    <home-weekend :list="weekendList"></home-weekend>
  </div>
</template>

<script>
// 區域性元件需要插入到components中,由於鍵和值都是一樣的,所以寫成HomeHeader
import HomeHeader from './components/Header'
import HomeSwiper from './components/Swiper'
import HomeIcons from './components/Icons'
import HomeRecommend from './components/Recommend'
import HomeWeekend from './components/Weekend'
import axios from 'axios'
export default {
  name: 'home',
  data () {
    return {
      city: '',
      swiperList: [],
      iconList: [],
      recommendList: [],
      weekendList: []
    }
  },
  components: {
    HomeHeader,
    HomeSwiper,
    HomeIcons,
    HomeRecommend,
    HomeWeekend
  },
  methods: {
    getHomeInfo () {
      axios({
        url: '/static/mock/index.json',
        method: 'get'
      }).then(this.getHomeInfoSucc)
    },
    getHomeInfoSucc (res) {
      console.log(res)
      res = res.data
      if (res.ret && res.data) {
        const data = res.data
        this.city = data.city
        this.swiperList = data.swiperList
        this.iconList = data.iconList
        this.recommendList = data.recommendList
        this.weekendList = data.weekendList
      }
    }
  },
  // 鉤子函式mounted
  mounted () {
    this.getHomeInfo()
  }
}
</script>

<style></style>

Header.vue

<template>
  <div class="header">
    <div class="header-left">
      <div class="iconfont back-icon">&#xe685;</div>
    </div>
    <div class="header-input">
      <span class="iconfont">&#xe67d;</span>
      輸入城市/景點/遊玩主題
    </div>
    <div class="header-right">
      {{this.city}}
      <span class="iconfont arrow-icon">&#xe688;</span>
    </div>
  </div>
</template>

<script>
export default {
  name: 'HomeHeader',
  props: {
    city: String
  }
}
</script>

<style lang="scss" scoped>
// styles指的是webpack.base.conf.js中的 src/assets/styles路徑的簡寫
@import '~styles/varibles.scss';
.header {
  display: flex;
  line-height: 0.86rem;
  background-color: $bgColor;
  color: #fff;
  .header-left {
    width: 0.64rem;
    float: left;
    .back-icon {
      font-size: 0.4rem;
      text-align: center;
    }
  }
  .header-input {
    flex: 1;
    background: #fff;
    border-radius: 0.1rem;
    padding-left: 0.2rem;
    margin-top: 0.12rem;
    margin-left: 0.2rem;
    height: 0.64rem;
    line-height: 0.64rem;
    color: #666;
  }
  .header-right {
    width: 1.24rem;
    float: right;
    text-align: center;
    .arrow-icon {
      margin-left: -0.04rem;
      font-size: 0.24rem;
    }
  }
}
</style>

Swiper.vue

<template>
  <!-- 在swiper外面加上一層div,是為了防止在網速慢的情況下抖動的bug,使用者體驗不好 -->
  <div class="warpper">
    <!-- 解決輪播圖預設在第一張 -->
    <swiper :options="swiperOption" v-if="showSwiper">
      <swiper-slide v-for="item in list" :key="item.id">
        <img class="swiper-img" :src="item.imgUrl" />
      </swiper-slide>
      <!-- 用於分頁 -->
      <div class="swiper-pagination" slot="pagination"></div>
    </swiper>
  </div>
</template>

<script>
export default {
  name: 'HomeSwiper',
  // ES6 data後面要有空格
  props: {
    list: Array
  },
  data () {
    return {
      swiperOption: {
        // 引數選項,顯示小點
        pagination: '.swiper-pagination',
        // 迴圈輪播
        loop: true,
        // 每張播放時長1秒,自動播放
        autoplay: 1000,
        // 滑動速度
        speed: 500
      }
    }
  },
  // 用計算屬性,避免模板中有太多內容
  computed: {
    showSwiper () {
      return this.list.length
    }
  }
}
</script>

<style lang="scss" scoped>
// 樣式進行了穿透  只要warpper下出現swiper-pagination-bullet-active類名就變色
// 這樣就不受scoped作用域的限制
.warpper >>> .swiper-pagination-bullet-active {
  background-color: #fff !important;
}
.warpper {
  overflow: hidden;
  width: 100%;
  height: 0;
  padding-bottom: 31.25%;
  background: #eee;

  .swiper-img {
    width: 100%;
  }
}
</style>

Recommend.vue

<template>
  <div class="recommend">
    <div class="title">熱銷推薦</div>
    <ul>
      <li
        class="item border-bottom"
        v-for="item in list"
        :key="item.id"
      >
        <img class="item-img" :src="item.imgUrl" />
        <div class="item-info">
          <p class="item-title">{{ item.title }}</p>
          <p class="item-desc">{{ item.desc }}</p>
          <button class="item-button">檢視詳情</button>
        </div>
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'HomeWeekend',
  props: {
    list: Array
  }
}
</script>

<style lang="scss" scoped>
.title {
  line-height: 0.8rem;
  background: #eee;
  text-indent: 0.2rem;
  margin-top: 0.2rem;
  font-size: 0.32rem;
  font-weight: 500;
}
.item {
  overflow: hidden;
  display: flex;
  height: 1.9rem;
  // background: red;
  .item-img {
    width: 1.7rem;
    height: 1.7rem;
    padding: 0.2rem;
  }
  .item-info {
    flex: 1;
    padding: 0.2rem;
    // 讓省略號顯示出來
    min-width: 0;
    .item-title {
      line-height: 0.54rem;
      font-size: 0.32rem;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
    }
    .item-desc {
      line-height: 0.4rem;
      color: #ccc;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
    }
    .item-button {
      line-height: 0.44rem;
      margin-top: 0.16rem;
      background: #ff9300;
      padding: 0 0.2rem;
      border-radius: 0.06rem;
      color: #fff;
    }
  }
}
</style>

Weekend.vue

<template>
  <div class="recommend">
    <div class="title">週末去哪兒</div>
    <ul>
      <li class="item border-bottom" v-for="item in list" :key="item.id">
        <!-- 防止網速慢的情況下抖動 -->
        <div class="item-img-wrapper">
          <img class="item-img" :src="item.imgUrl" />
        </div>
        <div class="item-info">
          <p class="item-title">{{ item.title }}</p>
          <p class="item-desc">{{ item.desc }}</p>
        </div>
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'HomeWeekend',
  props: {
    list: Array
  }
}
</script>

<style lang="scss" scoped>
.title {
  line-height: 0.8rem;
  background: #eee;
  text-indent: 0.2rem;
  margin-top: 0.2rem;
  font-size: 0.32rem;
  font-weight: 500;
}
.item-img-wrapper {
  overflow: hidden;
  height: 0;
  padding-bottom: 37.09%;
  .item-img {
    width: 100%;
  }
}
.item-info {
  padding: 0.2rem;
  // 讓省略號顯示出來
  min-width: 0;
  .item-title {
    line-height: 0.54rem;
    font-size: 0.32rem;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }
  .item-desc {
    line-height: 0.4rem;
    color: #ccc;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }
}
</style>

通過axios請求介面得到的效果如圖:
在這裡插入圖片描述

相關文章