zoukankan      html  css  js  c++  java
  • 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%;
           100%;
          padding-bottom: 50%;
          background-color: black;
        }
        /* 设置图片大小,100%,让图片都显示出来 */
        .lb_home1 img{
           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, // 循环模式选项
                 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%;
           100%;
          padding-bottom: 50%;
          /* background-color: black; */
        }
        /* 设置图片大小,100%,让图片都显示出来 */
        .lb_home1 img{
           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, // 循环模式选项
                 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%;
           100%;
          padding-bottom: 50%;
          background: url('http://we-teach.humianyuan.cn/home1.png') no-repeat;
          background-size: 100%;//让图片都显示出来
        }
    
        .lb_home2 {
          height: 0%;
           100%;
          padding-bottom: 50%;
          background: url('http://we-teach.humianyuan.cn/home2.png') no-repeat;
          background-size: 100%;
        }
    
        .lb_home3 {
          height: 0%;
           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, // 循环模式选项
                   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

    穷则独善其身,达则兼济天下……
  • 相关阅读:
    机器语言 汇编语言 C C++ Java C# javaScript Go 编译型语言 解释型语言
    计算机历史(二战前)
    可维护性组件的编写原则
    the lasted discuss about h5 optimize
    The last discussion about the inherit
    The last discussion about the prototype
    font-size line-height vertual-align的复杂关系
    vertical-align
    retina屏 适配问题
    XMLHttpRequest2.0的进步之处
  • 原文地址:https://www.cnblogs.com/hmy-666/p/14496859.html
Copyright © 2011-2022 走看看