[vue2.0]一步一個坑,仿知乎日報app:banner部分

思路

banner部分首先的框架部分在mint里面的Swipe就可以直接拿過來用了,然后就是獲取到數據源,把圖片一個個循環渲染扔進去展示,那么就按著這樣的思路來做了。

開始

打開

項目名》src》components》banner

<template>
  <div class="banner clearfix swiper-container" ref="banner">
    <mt-swipe :auto="4000">
        <mt-swipe-item>1</mt-swipe-item>
        <mt-swipe-item>2</mt-swipe-item>
        <mt-swipe-item>3</mt-swipe-item>
    </mt-swipe>  
  </div>
</template>

<script>
export default {
  name: 'banner',
  data() {
    return {
     
    }
  },
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.banner {
  width: 100%;
  height: 300px;
}
</style>

直接搬過來(加了點樣式)然后就會是這樣的顯示效果

5.png

如此樣子就長出來了,那就搗鼓里面的內容去了。

首先是數據源,我們看一下api的數據長什么樣子(先找到要用的數據先)

Api:https://zhihu-daily.leanapp.cn/api/v1/last-stories

打開后找到最下面

6.png

用的是chrom瀏覽器,裝上插件JSONView即可格式化json(看得方便,感興趣的可以裝上。)

找到了紅框中需要的數據源了,那么就把它在代碼中獲取過來

打開

項目名》src》components》banner

<script>
// 載入axios
import axios from 'axios'

export default {
  name: 'banner',
  data() {
    return {
     
    }
  },
   mounted() {
    // 調用函數,不然沒調用怎么會有操作
    this.fetchData()
  },

  methods: {
    fetchData() {
      // 獲取數據
      axios.get('https://zhihu-daily.leanapp.cn/api/v1/last-stories')
        // 正確輸出
        .then(response => {
         var items = response.data.STORIES.top_stories;
         console.log(items);
        })
        // 錯誤輸出
        .catch(function (error) {
          console.log(error);
        });
    },
  }
}
</script>

如上圖代碼(我只拿取了script部分展示出來),先載入axios,這里就有個坑不太懂的了我,就是網上有說只要在main.js里面加上

import axios from 'axios';
Vue.prototype.$http = axios;

然后在其他組件用的時候就用 this.$http.get() ...的就可以了。

但是我自己實踐的卻會報錯(不知道是不是我代碼有問題,如果有知道正確用法的請告知一聲,反正我暫時就是搞不來,最后只好在要用axios的組件上直接引用了,就像上面的代碼一樣)。

當中的mounted() {this.fetchData()}我是網上查找的調用vue函數的方法(一開始我就是沒調用,結果愣是看著瀏覽器發呆,為什么沒有數據顯示呢??--你都只有這個函數方法,沒用到,有數據就見鬼了!!!)

如無意外,打開瀏覽器開發者模式里的Console就可以看到獲取到了這樣的數據

7.png

這就說明數據獲取成功了,那么就想辦法把里面關聯的數據放到banner上吧。

先在data里加上原始元素屬性,然后把axios里面得到的數據賦值給data里面的屬性,跟著使用到了vue的v-for來把數據循環輸出到banner上那么就可以實現banner了(主要是用到了數據源當中的image地址,和title標題:分析api上的數據可以得到)

8.png

想法就是上面這樣的,那么就動手實踐一下

繼續打開

項目名》src》components》banner

<script>
import axios from 'axios'

export default {
  name: 'banner',
  data() {
    return {
    //創建數組items,用來裝載axios獲取到的數據
      items: [],
    }
  },

  methods: {
    fetchData() {
      // 獲取數據
      axios.get('https://zhihu-daily.leanapp.cn/api/v1/last-stories')
        // 正確輸出
        .then(response => {
          // 在axios中,這里只有用箭頭函數this才指向vue
          this.items = response.data.STORIES.top_stories;
          console.log(this.items);
        })
        // 錯誤輸出
        .catch(function (error) {
          console.log(error);
        });
    },
  }
}
</script>

這樣寫好的話,在瀏覽器上看到的應該會和之前一樣的效果(上一張Console里面看得的數據內容),這就說明賦值是成功的了。

這里有個坑,就像我注釋里一樣。

//在axios中,這里只有用箭頭函數this才指向vue

這個開始的時候,我是直接在axios的github上復制了一段代碼過來使用的,代碼如下

// Make a request for a user with a given ID
axios.get('/user?ID=12345')
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

結果就是我在里面用this的時候一直報錯,后面查了下資料才知道只有用上箭頭函數時,axios里面的this才是指向vue的。

好了數據獲取到了,那么就該擺放上去banner上了,這里用到了v-for

打開

項目名》src》components》banner

<template>
  <div class="banner clearfix swiper-container" ref="banner">
     <mt-swipe :auto="4000">
        <!-- 以items為數據源,循環 -->
      <mt-swipe-item v-for="item in items" class="banner-img">
        <!-- 圖片地址用v-bind縮寫":" -->
        <img :src=“item.image” alt="banner">
        <span>{{item.title}}</span>
      </mt-swipe-item>
    </mt-swipe>

  </div>
</template>

使用v-for="item in items"把items上的數據循環輸出到item上,然后里面主要是展示圖片,所以加了img標簽獲取圖片,還有一個span標簽用于獲取標題。(上面圖片行代碼<img :src=“item.image” alt="banner">用了中文符號,半角打上去發布就變了,奇怪~)

其中圖片地址用v-bind縮寫":"來綁定,不讓的話你顯示的地址會是直接字符串item.image(此坑我也是掉過進去)

當然為了更好的在瀏覽器上看到效果,我們把一些樣式也加進去先

<style scoped>
.banner {
  width: 100%;
  height: 300px;
  position: relative;
}

.banner-img img {
  display: block;
  width: 100%;
  /*height: 100%; */
  position: absolute;
  left: 50%;
  margin-left: -50%;
}

.banner-img span {
  font-size: 22px;
  display: block;
  position: absolute;
  bottom: 35px;
  color: #fff;
  padding: 0 20px;
}
</style>

當讓加上上面的樣式后你看看瀏覽器會發現

9.png

圖片地址是有了,而且正確了,但是每一張圖片都報錯403!!!

這其實是因為知乎服務器做了圖片防盜鏈的操作,那么我們要用到他的圖片就只能夠處理一下圖片地址了,具體方法就是轉接一下,如運用這個Images.weserv.nl的網站(感興趣的可以去看看,挺簡單的原理),我們要做的就是更改下圖片的前綴,加上images.weserv.nl/?url=p后面接上原圖片地址,就可以從他們的網站作為圖片源了。

所以我們需要多寫一個函數方法來改變一下圖片地址。

  methods: {
    fetchData() {
      // 獲取數據
      axios.get('https://zhihu-daily.leanapp.cn/api/v1/last-stories')
        // 正確輸出
        .then(response => {
          // 在axios中,這里只有用箭頭函數this才指向vue
          this.items = response.data.STORIES.top_stories;
        })
        // 錯誤輸出
        .catch(function (error) {
          console.log(error);
        });
    },
    // 更改圖片地址
    changeImageUrl(srcUrl) {
      if (srcUrl !== undefined) {
        return srcUrl.replace(/http\w{0,1}:\/\/p/g, 'https://images.weserv.nl/?url=p');
      }
    },
  }
}
</script>

然后在使用到圖片地址的地方調用這個方法

<template>
  <div class="banner clearfix swiper-container" ref="banner">
     <mt-swipe :auto="4000">
        <!-- 以items為數據源,循環 -->
      <mt-swipe-item v-for="item in items" class="banner-img">
        <!-- 更改圖片地址,否則知乎圖片防盜鏈無法顯示 -->
        <img :src=“changeImageUrl(item.image)” alt="banner">
        <span>{{item.title}}</span>
      </mt-swipe-item>
    </mt-swipe>

  </div>
</template>

上面<img :src=“changeImageUrl(item.image)” alt="banner">
用了中文符號注意!

很好!大功告成!

10.png

結束

banner部分就此完成了,顯示的效果雖然達成了,但是當中不知道運用的技術是否得當,如有更好的實現方法請留言告訴我,最后把banner組件的完整代碼寫一下。

<template>
  <div class="banner clearfix swiper-container" ref="banner">
     <mt-swipe :auto="4000">
        <!-- 以items為數據源,循環 -->
      <mt-swipe-item v-for="item in items" class="banner-img">
        <!-- 更改圖片地址,否則知乎圖片防盜鏈無法顯示 -->
        <img :src=“changeImageUrl(item.image)” alt="banner">
        <span>{{item.title}}</span>
      </mt-swipe-item>
    </mt-swipe>

  </div>
</template>

<script>
import axios from 'axios'

export default {
  name: 'banner',
  data() {
    return {
      items: [],
    }
  },
  mounted() {
    // 監聽方法
    this.fetchData()
    this.getHeight()
  },
  methods: {
    fetchData() {
      // 獲取數據
      axios.get('https://zhihu-daily.leanapp.cn/api/v1/last-stories')
        // 正確輸出
        .then(response => {
          // 在axios中,這里只有用箭頭函數this才指向vue
          this.items = response.data.STORIES.top_stories;
        })
        // 錯誤輸出
        .catch(function (error) {
          console.log(error);
        });
    },
    // 更改圖片地址
    changeImageUrl(srcUrl) {
      if (srcUrl !== undefined) {
        return srcUrl.replace(/http\w{0,1}:\/\/p/g, 'https://images.weserv.nl/?url=p');
      }
    },
    // 獲取banner塊的高度
    getHeight() {
      // 獲取屏幕高度
      let h = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
      //  更改樣式,用到了vue中$refs方法
      this.$refs.banner.style.height = h / 2 - 80 + 'px';
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.banner {
  width: 100%;
  position: relative;
}

.banner-img {
  width: 100%;
  height: 100%;
  overflow: hidden;
  margin: 0 auto;
  position: relative;
}

.banner-img img {
  display: block;
  width: 100%;
  /*height: 100%; */
  position: absolute;
  left: 50%;
  margin-left: -50%;
}

.banner-img span {
  font-size: 22px;
  display: block;
  position: absolute;
  bottom: 35px;
  color: #fff;
  padding: 0 20px;
}
</style>

和上面文章唯一不同的是,我把banner的高度改了一下,其他完全一樣。(上面<img :src=“changeImageUrl(item.image)” alt="banner">
用了中文符號注意!)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容