vue使用Swiper做輪播圖時,瀏覽器窗口變化,圖片跟着變化實現


首先輪播圖是這樣的:

 

 很美好,都顯示出來了,但是當我縮小瀏覽器窗口時:

 圖片顯示不全,即使我外面設置了等比例縮小,它里面的圖片尺寸還是根據原來的尺寸不變化。

下面解決方法1:

HTML部分:

 <div ref="home_swiper" class="swiper-container">
      <div class="swiper-wrapper">
        <div class="swiper-slide" v-for="(item,index) in imgList">
          <div class="lb_home1"><img :src="imgList[index]"></div>
        </div>
        <!-- <div class="swiper-slide">
          <div class="lb_home2">2</div>
        </div>
        <div class="swiper-slide">
          <div class="lb_home3">3</div>
        </div> -->
      </div>
      <div class="swiper-scrollbar"></div>
    </div>

js部分,圖片以數組方式傳入

 data() {
        return {
          imgList: ["http://we-teach.humianyuan.cn/home1.png", "http://we-teach.humianyuan.cn/home2.png",
            "http://we-teach.humianyuan.cn/home3.png"
          ],
          Swiper: null,
        }

css部分:

 .lb_home1{
      /* 這里是一個技巧,設置高度為0,再設置padding-bottom百分比,
      此時高度就是父元素高度的百分比,用來設置自適應 */
      height: 0%;
      width: 100%;
      padding-bottom: 50%;
      background-color: black;
    }
    /* 設置圖片大小,100%,讓圖片都顯示出來 */
    .lb_home1 img{
      width: 100%;
      height: 100%;
    }

此時看一下結果:

 

 你以為沒變化嗎,其實已經改變了,只是因為沒刷新,所以我自己上網找了別人說的什么幾把玩意,說調一下update,resize一下,可是這些幾把方法不適合我,沒有用,swiper不會自動刷新,看了官方文檔,用了它推薦的幾把方法也不起效果。

最后一氣之下,自己按了F5,

 達到了我想要的結果,那就自己實現刷新了,vue有個provide方法,可以實現reload注入,實現局部刷新。

在app.vue下

 

 實現該方法注冊,那么在其他組件都可以用這個方法了,用之前必須注入

 然后實時監聽窗口onresize,就可以刷新了,下面是全部代碼:

APP.vue:

<template>
  <div id="app">
    <div v-show='this.$route.name=="Brief"?false:true'><Public_Nav></Public_Nav></div>
    <router-view v-if="isRouterAlive" />
  </div>
</template>
<script>
  import Public_Nav from 'components/content/nav/Public_Nav.vue'
  export default {
    name: 'App',
    //給全局注冊一個reload,需要使用時就注入該方法
    provide(){
      return{
        reload:this.reload
      }
    },
    data() {
      return {isRouterAlive:true}
    },
   methods: {
     reload(){
       this.isRouterAlive = false;
       this.$nextTick(function(){
         this.isRouterAlive = true;
       })
     }
   },
    components:{
      Public_Nav
    }
  }
</script>
<style scoped>
  /* @import 'https://at.alicdn.com/t/font_2391663_8sx9tzlzzhl.css'; */
  /* #app{
    overflow: hidden;
  } */
</style>

自己封裝的Swiper

<template>
    <div ref="home_swiper" class="swiper-container">
      <div class="swiper-wrapper">
        <div class="swiper-slide" v-for="(item,index) in imgList">
          <div class="lb_home1"><img :src="imgList[index]"></div>
        </div>
      </div>
      <div class="swiper-scrollbar"></div>
    </div>
  </template>
  <script>
    import Swiper from 'swiper'; //輪播
    export default {
      name: 'HomeSwiper',
      inject: ['reload'],
      data() {
        return {
          imgList: ["http://we-teach.humianyuan.cn/home1.png", "http://we-teach.humianyuan.cn/home2.png",
            "http://we-teach.humianyuan.cn/home3.png"
          ],
          Swiper: null,
        }
      },
      methods: {
        initMySwiper() {
          let mySwiper = this.Swiper = new Swiper(this.$refs.home_swiper, {
            // direction:'vertical',
            loop: true, // 循環模式選項
            width: window.innerWidth * 0.9 * 0.65,
            //分頁器
            scrollbar: {
              el: '.swiper-scrollbar',
              draggable: true,
            },
            autoplay: {
              delay: 2000,
              disableOnInteraction: false, //用戶觸摸后靜止關閉
            }
          })
        }
      },
      mounted() {
        this.initMySwiper();
        window.onresize = () => {
           this.reload()//窗口變化實時刷新
        }
      },
    }
  </script>
  <style>
    .lb_home1{
      /* 這里是一個技巧,設置高度為0,再設置padding-bottom百分比,
      此時高度就是父元素高度的百分比,用來設置自適應 */
      height: 0%;
      width: 100%;
      padding-bottom: 50%;
      /* background-color: black; */
    }
    /* 設置圖片大小,100%,讓圖片都顯示出來 */
    .lb_home1 img{
      width: 100%;
      height: 100%;
    }
</style>

測試結果:

 

 

 

 大功告成!

第二種方法設置樣式還是要用到reload注入,只不過控制圖片樣式是通過背景圖片方式:

<template>
    <div ref="home_swiper" class="swiper-container">
      <div class="swiper-wrapper">
        <div class="swiper-slide" >
          <div class="lb_home1"></div>
        </div>
        <div class="swiper-slide">
          <div class="lb_home2"></div>
        </div>
        <div class="swiper-slide">
          <div class="lb_home3"></div>
        </div> 
      </div>
      <div class="swiper-scrollbar"></div>
    </div>
  </template>
  <script>
    import Swiper from 'swiper'; //輪播
    export default {
      name: 'HomeSwiper',
      inject: ['reload'],
      data() {
        return {
          imgList: ["http://we-teach.humianyuan.cn/home1.png", "http://we-teach.humianyuan.cn/home2.png",
            "http://we-teach.humianyuan.cn/home3.png"
          ],
          Swiper: null,
        }
      },
      methods: {
        initMySwiper() {
          let mySwiper = this.Swiper = new Swiper(this.$refs.home_swiper, {
            // direction:'vertical',
            loop: true, // 循環模式選項
            width: window.innerWidth * 0.9 * 0.65,
            //分頁器
            scrollbar: {
              el: '.swiper-scrollbar',
              draggable: true,
            },
            autoplay: {
              delay: 2000,
              disableOnInteraction: false, //用戶觸摸后靜止關閉
            }
          })
        }
      },
      mounted() {
        this.initMySwiper();
        window.onresize = () => {
          this.reload()
        }
      },
    }
  </script>
  <style> .lb_home1 {
      height: 0%;
      width: 100%;
      padding-bottom: 50%;
      background: url('http://we-teach.humianyuan.cn/home1.png') no-repeat;
      background-size: 100%;//讓圖片都顯示出來
    }

    .lb_home2 {
      height: 0%;
      width: 100%;
      padding-bottom: 50%;
      background: url('http://we-teach.humianyuan.cn/home2.png') no-repeat;
      background-size: 100%;
    }

    .lb_home3 {
      height: 0%;
      width: 100%;
      padding-bottom: 50%;
      background: url('http://we-teach.humianyuan.cn/home3.png') no-repeat;
      background-size: 100%;
    } 
  </style>

 最后測試結果和上面一樣,用都說好,就不展示了。

 

----------------------------------3月9日第二次更新--------------------------------

上面那種方法是通過mouted加window.resize進行實時監聽刷新的,但是實際應用中我們要做的是局部刷新,所以需要在router-view加keepalive屬性。

<keep-alive>
      <router-view  v-if="isRouterAlive" />
    </keep-alive>

一旦加上keepalive屬性,mouted就不銷毀了。原來的vue會在頁面切換就銷毀,然后重新執行渲染mounted,但是有時候我們需要記錄我們之前在這個頁面做的一些操作,比如點擊了某樣東西,這個東西變色了,加了keepalive之后,跳轉到其它頁面,再切回來,這個東西還是原來變色的那種樣式。

但是keppAlive在帶來方便的同時也帶來了不會重復mounted,需要手動F5按刷新才有效,下面就是頁面加了keepAlive屬性后,輪播圖不會刷新的樣子,因為雖然有檢測到窗口變化,但是由於keppAlive屬性,reload函數不起作用。

 

 所以我們此時reload函數失去作用。

所以接下來我想出了第二個方法,就是在檢測到窗口變化時實時初始化Swiper,例如下面:

 window.onresize=()=>{
          this.initMySwiper()//自己封裝的初始化函數,窗口變化時就初始化
        }

縮小窗口后,得到的是想要的結果:

 但是隨之而來的另一個問題是,監聽窗口變化這個window.resize這個函數會在窗口發生變化時觸發執行,有時候還觸發了不止一次,那么重復初始化Swiper之后,它會創建多個實例對象,且不會銷毀,看起來切換輪播圖的大小雖然沒變,但是速度變得是原來的幾倍,因為實例化了很多個對象,多個對象在不同時間執行,串在一起時就像開高鐵一樣快得驚人。

所以有了問題,我們就得解決問題,解決方案那就是:

(1)在創建新的Swiper實例化對象之前先判斷上一個是否銷毀;

(2)在銷毀對象時,判斷是否為當前的Swiper實例化對象。

翻譯為更加形象一點就是:吃面包的故事。

每天起床第一件事就是吃面包和買面包:

(1)吃面包:判斷今天吃的面包是否是今天買的?

(2)買面包:判斷昨天的面包吃了沒有?

總結起來就是,今天面包今天買,今天吃。每天要吃的面包,每天買,每天吃完。

所以翻譯代碼為:

 data() {
        return {
          Swiper: null,//保存當前的Swiper
          isReload: false,
          oldSwiper:null//要銷毀的Swiper
        }
      },
      methods: {
        initMySwiper() {
          let mySwiper;
            return mySwiper = this.Swiper = new Swiper(this.$refs.home_swiper, {
              // direction:'vertical',
              loop: true, // 循環模式選項
              width: window.innerWidth * 0.9 * 0.65,//可以修改寬度
              //分頁器
              scrollbar: {
                el: '.swiper-scrollbar',
                draggable: true,
              },
              autoplay: {
                delay: 2000,
                disableOnInteraction: false, //用戶觸摸后靜止關閉
              }
            })
        }
      },
    mounted() { this.oldSwiper = this.initMySwiper();//初始化時,把剛剛實例化產生的Swiper保存在oldSwiper中
       console.log("新老swiper:"+(this.oldSwiper==this.Swiper))
        window.onresize = () => {
          console.log("新老swiper:"+(this.oldSwiper==this.Swiper))
          //銷毀的是否為當前對象
          if(this.oldSwiper==this.Swiper){
            this.Swiper.destroy();
            console.log("destroy");
            this.Swiper = null;//摧毀Swiper之后賦值空
          } 
          //判斷上一個對象是否銷毀了,銷毀了才能創建新對象,計時器加不加都可以
          setTimeout(() => {
            if(this.Swiper==null){
              this.oldSwiper=this.initMySwiper(); 
            console.log("初始化swiper")
            }
          }, 10);
           
            console.log("resize")
        }
      console.log("mounted") },
      
    }
  </script>

 ---------------------------3月10日第三次更新------------------------------------

上面那種方案是組件處於keepalive情況下的,但是有一個問題,就是mouted函數只會觸發一次了,因為保持了keepalive屬性;當我們退出頁面重進后,窗口實時監聽就會失效,此時我們應該把監聽窗口變化的函數寫在activated

 


免責聲明!

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



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