surmon-china / vue-awesome-swiper

🏆 Swiper component for @vuejs
https://github.surmon.me/vue-awesome-swiper
MIT License
12.81k stars 1.96k forks source link

You may have an infinite update loop in a component render function #394

Open jasonz1987 opened 6 years ago

jasonz1987 commented 6 years ago

原谅我英文水平差,如果机器翻译的话,肯定更看不懂。

具体问题:

更新数据的时候,报错

You may have an infinite update loop in a component render function

具体代码

<template>
  <div class="swiper-container">

    <swiper :options="swiperOption" class="swiper-box">
      <swiper-slide class="slide-item slide-item-1" :style="images[0]">
        <div class="">
          <div class="text-1">
            <p>已有{{result.pv_count || '--'}}位玩家查看</p>
          </div>

          <div class="left-ball">
            <img :src="leftBallIcon">
          </div>

          <div class="right-ball">
            <img :src="rightBallIcon">
          </div>

          <div class="pull-text">
            <!--<i class="el-icon-arrow-up"></i>-->
            <img :src="pullIcon" class="pull-icon">
            <p>上拉加载更多</p>
          </div>
        </div>
      </swiper-slide>
      <swiper-slide class="slide-item slide-item-2" :style="images[1]" v-if="!result.is_new">
          <div class="avatar">
            <img :src="result.avatar_url">
          </div>
          <div class="text-2">
            <p>你</p>
            <h2>{{result.reg_date}}</h2>
            <p>来到多多临海麻将</p>
            <br>
            <p>已度过</p>
            <h2>{{result.reg_days}}天</h2>
            <p>的欢乐游戏时光</p>
          </div>

          <div class="pull-text">
            <!--<i class="el-icon-arrow-up"></i>-->
            <img :src="pullIcon" class="pull-icon">
            <p>上拉加载更多</p>
          </div>
      </swiper-slide>
      <swiper-slide class="slide-item slide-item-3" :style="images[1]" v-if="!result.is_new">
        <div class="">
          <div class="text-3">
            <p>你</p>
            <p>登录过</p>
            <h2>{{result.login_count}}次</h2>
            <br>
            <p>最常玩</p>
            <h2>临海麻将</h2>
            <br>
            <p>总共玩过</p>
            <h2>{{result.play_total_count}}局</h2>
            <br>
            <p>胜利</p>
            <h2>{{result.play_win_count}}局</h2>
            <br>
            <p>胜率</p>
            <h2>{{result.play_win_rate}}%</h2>
            <p style="color:yellow;">超过了{{result.over_win_rate}}%的玩家</p>
          </div>

          <div class="pull-text">
            <!--<i class="el-icon-arrow-up"></i>-->
            <img :src="pullIcon" class="pull-icon">
            <p>上拉加载更多</p>
          </div>
        </div>
      </swiper-slide>
      <swiper-slide class="slide-item slide-item-4" :style="images[1]" v-if="!result.is_new">
        <div class="text-4" v-if="!result.is_lost">
          <p>你最近一次登录在</p>
          <h2>{{result.last_login_text}}</h2>
          <p>真是对多多临海麻将</p>
          <p>爱得深沉呢~</p>

          <br>
          <p>有<span class="num">7</span>位与你同桌过朋友</p>
          <p>已经超过7天</p>
          <p>没有登录游戏了</p>
          <p>想念他们吗</p>
          <br>
          <p>现在邀请他们回归游戏</p>
          <p>每成功邀请1位</p>
          <p>即可获得<span class="num" style="color:yellow;">5</span>张房卡奖励</p>
          <p>快去邀请吧!</p>
        </div>

        <div class="text-4" v-if="result.is_lost" style="margin-bottom: 200px;">
          <p>你最近一次登录在</p>
          <h2>{{result.last_login_text}}</h2>
          <p>已经过去<span class="num">{{result.last_login_days}}</span>天了</p>

          <br>
          <p>现在重新登录</p>
          <p>即可免费获得</p>
          <h2 style="color:yellow;">45张房卡</h2>
          <h2 style="color:yellow;">20元红包</h2>
          <br>
          <p><span class="num">{{result.friend_count}}</span>位朋友在游戏里</p>
          <p>等你哦!</p>
        </div>

        <div id="invite-btn" v-if="!result.is_lost" @click="doInvite">
          <img :src="inviteBtnImg">
        </div>

        <div class="down-btn" v-if="result.is_lost">
          <img :src="logoImg" width="64" height="64" style="display: block;
    margin: 10px auto;">
          <a :href="result.down_url">
            <img :src="downBtnImg" style="width:200px;">
          </a>
        </div>

        <div class="pull-text">
          <!--<i class="el-icon-arrow-up"></i>-->
          <img :src="pullIcon" class="pull-icon">
          <p>上拉加载更多</p>
        </div>

      </swiper-slide>
      <swiper-slide class="slide-item" :style="images[2]">
        <div>
          <div class="down-btn" v-if="result.is_new">
            <img :src="logoImg" width="64" height="64" style="display: block;
    margin: 10px auto;">
            <a :href="result.down_url">
              <img :src="downBtnImg" style="width:200px;">
            </a>
          </div>
          <div class="pull-text">
            <!--<i class="el-icon-arrow-up"></i>-->
            <img :src="pullIcon" class="pull-icon">
            <p>上拉加载更多</p>
          </div>
        </div>
      </swiper-slide>
      <swiper-slide class="slide-item" :style="images[3]">
        <div>
          <div class="down-btn" v-if="result.is_new">
            <a :href="result.down_url">
              <img :src="downBtnImg" style="width:200px;">
            </a>
          </div>
          <div class="pull-text">
            <!--<i class="el-icon-arrow-up"></i>-->
            <img :src="pullIcon" class="pull-icon">
            <p>上拉加载更多</p>
          </div>
        </div>
      </swiper-slide>
      <swiper-slide class="slide-item" :style="images[4]">
        <div>
          <div class="down-btn" v-if="result.is_new">
            <img :src="downBtnImg" style="width:200px;">
          </div>
          <div class="pull-text">
            <!--<i class="el-icon-arrow-up"></i>-->
            <img :src="pullIcon" class="pull-icon">
            <p>上拉加载更多</p>
          </div>
        </div>
      </swiper-slide>
      <swiper-slide class="slide-item" :style="images[5]">
        <div>
          <div class="down-btn" v-if="result.is_new">
            <a :href="result.down_url">
              <img :src="downBtnImg" style="width:200px;">
            </a>
          </div>
          <div class="pull-text">
            <!--<i class="el-icon-arrow-up"></i>-->
            <img :src="pullIcon" class="pull-icon">
            <p>上拉加载更多</p>
          </div>
        </div>
      </swiper-slide>
      <swiper-slide class="slide-item" :style="images[6]"></swiper-slide>

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

    <div class="share-tip" v-if="is_share" @click="cancelShare()">
      <img :src="shareTipBg" style="width: 100%;height: 100%;">
    </div>
  </div>
  <!--<div class="share-tip" v-show="is_share" @click="cancelShare()">-->
    <!--<img :src="shareTipBg" style="width: 100%;height: 100%;">-->
  <!--</div>-->
</template>

<script>
  import 'swiper/dist/css/swiper.css'

  import { swiper, swiperSlide } from 'vue-awesome-swiper'
  import { MessageBox } from 'element-ui';
  import { Message } from 'element-ui';

  export default {
    created() {

      const vm = this;

      var result = JSON.parse(sessionStorage.getItem("data"));

      var channel_id = sessionStorage.getItem('channel_id');
      var role_id = sessionStorage.getItem('role_id');

      var url = vm.urlHost+'/invite?channel_id='+channel_id+'&role_id'+role_id;

      if(!result) {
        window.open(url,'_self');
      }

      vm.result = result;

      var shareTitle = "临海周年庆";
      var shareImg = "https://file.tuo3.com.cn/linhai200.png";

      wx.ready(function () {
        alert(shareTitle);
        alert(shareImg);
        alert(result.invite_url);

        wx.onMenuShareTimeline({
          title: shareTitle, // 分享标题
          link: result.invite_url, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
          imgUrl: shareImg, // 分享图标
          success: function () {
            // 用户确认分享后执行的回调函数
            Message.success('分享成功');
          },
          error: function (err) {
            console.log(err);
            Message.error('分享失败');
          },
          cancel: function () {
          }
        });
        wx.onMenuShareAppMessage({
          title: shareTitle, // 分享标题
          desc: shareTitle, // 分享描述
          link: result.invite_url, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
          imgUrl: shareImg, // 分享图标
          success: function () {
            // 用户确认分享后执行的回调函数
            Message.success('分享成功');
          },
          error: function (err) {
            console.log(err);
            Message.error('分享失败');
          },
          cancel: function () {
          }
        });
      });
    },
    data() {
//      var data = sessionStorage.getItem("data");
//      console.log(data);
      return {
        result:{
          pv_count:'--'
        },
        swiperOption: {
          direction: 'vertical',
          slidesPerView: 1,
          spaceBetween: 30,
          mousewheel: true,
          pagination: {
            el: '.swiper-pagination',
            clickable: true
          },
          observer: true,//修改swiper自己或子元素时,自动初始化swiper
          observeParents: true,//修改swiper的父元素时,自动初始化swiper
        },
        images:[
          {
            backgroundImage: "url(" + require("../assets/invite/001.jpg") + ")",
            backgroundRepeat: "no-repeat",
            backgroundPosition: "center center",
            backgroundSize: "cover",
          },
          {
            backgroundImage: "url(" + require("../assets/invite/002.jpg") + ")",
            backgroundRepeat: "no-repeat",
            backgroundPosition: "center center",
            backgroundSize: "cover",
          },
          {
            backgroundImage: "url(" + require("../assets/invite/003.jpg") + ")",
            backgroundRepeat: "no-repeat",
            backgroundPosition: "center center",
            backgroundSize: "cover",
          },
          {
            backgroundImage: "url(" + require("../assets/invite/004.jpg") + ")",
            backgroundRepeat: "no-repeat",
            backgroundPosition: "center center",
            backgroundSize: "cover",
          },
          {
            backgroundImage: "url(" + require("../assets/invite/005.jpg") + ")",
            backgroundRepeat: "no-repeat",
            backgroundPosition: "center center",
            backgroundSize: "cover",
          },
          {
            backgroundImage: "url(" + require("../assets/invite/006.jpg") + ")",
            backgroundRepeat: "no-repeat",
            backgroundPosition: "center center",
            backgroundSize: "cover",
          },
          {
            backgroundImage: "url(" + require("../assets/invite/007.jpg") + ")",
            backgroundRepeat: "no-repeat",
            backgroundPosition: "center center",
            backgroundSize: "cover",
          }
        ],
        inviteBtnImg:require('../assets/invite/invite_btn.png'),
        downBtnImg:require('../assets/invite/down_btn.png'),
        logoImg:require('../assets/invite/icon.png'),
        pullIcon:require('../assets/invite/pull.png'),
        leftBallIcon:require('../assets/invite/ball_left.png'),
        rightBallIcon:require('../assets/invite/ball_right.png'),
        shareTipBg:require("../assets/invite/share_tip.png"),
        is_share: false
      }
    },
    components: {
      swiper,
      swiperSlide
    },
    name: 'invite2',
    methods: {
      doInvite:function () {

  //        var vm = this;
        this.is_share = true;
      },
      cancelShare:function() {
        var vm = this;
        vm.is_share = false;
      }
    }
  }
</script>

<style>

  html,body,#app,.swiper-container{
    position: relative;
    height: 100%;
    color:#fff;
  }
  body {
    background: #eee;
  }
  .swiper-container,.swiper-box {
    width: 100%;
    height: 100%;
    margin: 0 auto;
  }

  .slide-item {
    /*height: 100%;*/
    text-align: center;
    font-size: 14px ;
    background: #fff;
    /* Center slide text vertically */
    display: -webkit-box;
    display: -ms-flexbox;
    display: -webkit-flex;
    display: flex;
    -webkit-box-pack: center;
    -ms-flex-pack: center;
    -webkit-justify-content: center;
    justify-content: center;
    -webkit-box-align: center;
    -ms-flex-align: center;
    -webkit-align-items: center;
    align-items: center;
    flex-direction:column;
  }

  .pull-text {
    position: absolute;
    bottom:1%;
    left:0;
    right:0;
    z-index:10000;
    height:50px;
  }

  .pull-text > p {
    font-size:12px;
    margin :5px 0;
  }

  .slide-item-1 .text-1 {
    position: absolute;
    bottom: 14%;
    left: 0;
    right: 0;
    margin:0 auto;
    background-color: #ffd632;
    width:80%;
    line-height: 0.8;
    border-radius: 25px;
    /*border-radius:20%;*/
  }

  .slide-item-1 .left-ball img{
    position: absolute;
    left : 5px;
    top: 28%;
    animation:move-left 3s ease-in-out infinite;
    width: 130px;
  }

  .slide-item-1 .right-ball img{
    position: absolute;
    right : 5px;
    top: 30%;
    width: 130px;
    animation:move-right 3s ease-in-out infinite;
  }

  .slide-item-2 .avatar {
    padding-top: 100px;
    flex:0;
    padding-bottom: 30px;
  }

  .slide-item-2 .avatar img {
    width:120px;
    height:120px;
    border: 5px solid #fff;
  }

  .slide-item-2 .text-2 {
    flex: 1;
    -webkit-flex: 1;
    text-align: left;
    line-height: 0.6;
  }

  .slide-item-2 .text-2 br {
    line-height: 5px;
  }

  .slide-item-3 .text-3 {
    flex: 1;
    text-align: left;
    line-height: 0.5;
    margin-bottom: 50px;
  }

  .slide-item-3 .text-3 br {
    display: inline;
    line-height: 1px;
  }

  .slide-item-4 .text-4 {
    padding-top:100px;
    flex: 1 0 auto;
    text-align: left;
    line-height: 0.5;
  }

  .slide-item-4 .text-4 br {
    display: inline;
    line-height: 0.1;
  }

  .slide-item-4 .num {
    font-size:2.0rem;
    padding:0 5px;
  }

  .share-tip {
    position: fixed;
    left: 0;
    top: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.8);
    filter: alpha(opacity=80);
    height: 100%;
    width: 100%;
    z-index: 100;
  }

  #invite-btn {
    flex:0 0 auto;
    padding-bottom: 20%;
  }

  #invite-btn img{
    /*position:absolute;*/
    /*bottom:15%;*/
    /*left:0;*/
    /*right:0;*/
    /*margin: 0 auto;*/
    width: 200px;
  }

  .down-btn {
    flex:0 0 auto;
    padding-bottom: 20%;
    /*position:absolute;*/
    /*bottom:15%;*/
    /*left:0;*/
    /*right:0;*/
    /*margin: 0 auto;*/
    /*width: 280px;*/
  }

  .pull-icon {
    width: 36px;
    animation: jump 1s infinite;
  }

  @keyframes jump {
    0% {
      transform: translate(0px, 0px);
    }
    50% {
      transform: translate(0px, -10px); /*往Y轴方向跳动*/
    }
    100% {
      transform: translate(0px, 0px);
    }
  }

  @keyframes move-left {
    0%, 100% {
      transform: translateY(0) rotate(-6deg);
    }
    50% {
      transform: translateY(-10px) rotate(8deg);
    }
  }

  @keyframes move-right {
    0%, 100% {
      transform: translateY(0) rotate(6deg);
    }
    50% {
      transform: translateY(-30px) rotate(-8deg);
    }
  }

</style>

当我使用调用doInvite方法,更改is_share的时候就会报错,而且这个页面也会卡死。

@surmon-china

jasonz1987 commented 6 years ago

这个问题 我暂时的处理方法是 给

<swiper :options="swiperOption" class="swiper-box">

加上一个v-if

<swiper :options="swiperOption" class="swiper-box" v-if="!is_share">

这样就可以避免数据变化的时候 刷新swiper组件。

但是 总感觉只是一个投机取巧的方法,具体还是等一个更好的解释吧~

wyh909 commented 5 years ago

遇到同样一个问题,引入的swiper用到render里,由于数据获取导致多次渲染,应该是这个问题引起的,但不知如何解决

return (
        h('div', {class: this.$style.app}, [
          h(swiper, {}, [
            h(swiperSlide, {class: this.$style.view}, [h(Intra, { class: this.$style.section, props: { user: this.store.user }})]),
            ...views
          ])
        ])
      )
VolodymyrTesliuk commented 5 years ago

Hello @jasonz1987 is it resolved?

giuliano-macedo commented 3 years ago

@VolodymyrTesliuk I solved by:

  1. Isolating my swiper component creating another .vue template or
  2. Never initializing mySwiper object to null even in the created().