【问题标题】:vue.js v class binding is overriding other bindings and not removing classes properlyvue.js v 类绑定覆盖其他绑定并且没有正确删除类
【发布时间】:2018-05-04 18:06:07
【问题描述】:

我有一个出气筒“游戏”,我想在每个点击事件中添加一个动画类。而当生命值降至零时,我将用爆裂袋的图像替换袋子图片。

只要我不尝试添加动画类就可以了。当我尝试添加动画时,两个功能都不起作用。

链接在这里:https://codepen.io/damianocel/pen/mqXady

这是 HTML:

<div id="vue-app-one">
<!-- the bag images -->
<div id="bag" v-bind:class="[animationToggle ? activeClass : 'swingLeft', 
'noSwing']" v-bind:class="{ burst: ended }"></div>

<!-- health meter -->
<div id="bag-health">
  <div v-bind:class="[danger ? activeClass : 'dangerous', 'safe']" v-
bind:style="{ width: health + '%'}"></div>
</div>


 <!-- the game buttons -->

 <div id="controls">
    <button v-on:click="punch" v-show="!ended">Punch it!</button>
      <button v-on:click="restart">Restart game</button>
 </div>

 </div>

有问题的部分是这样的:

<div id="bag" v-bind:class="[animationToggle ? activeClass : 'swingLeft', 
'noSwing']" v-bind:class="{ burst: ended }"></div>

// 上面我尝试将 noSwing CSS 类绑定为默认值,如果 animationToggle 属性发生变化,将其更改为 swingLeft。但是,当我检查开发工具时,这会添加两个类,并且没有动画发生。我可以像这样在 1 个元素上绑定 2 个类吗?

// 此外,我将 end 属性绑定到突发 CSS 类,这仅在我删除 animationToggle 绑定和所有相关 CSS 时才有效。

实例如下所示:

var one = new Vue({
el: '#vue-app-one',
data: {
health: 100, //init health bar, this works
ended: false, // init ended state, works partially
punched: false, //init punched, don't need for now
danger: false, // this works
animationToggle: false, // there is a problem with this
activeClass: "" // have to init or I get the errors in the console
 },
methods: {

  punch: function(){
      this.health -=10; //works
      this.animationToggle= true; // is set on click
      if(this.health <= 0){
        this.ended = true; // works partially, the background img change is not working ,though
      }
      if(this.health <= 20){
        this.danger = true; // works
      }
      else{
        this.danger = false;
      }
      setTimeout(function () {
          this.animationToggle = false // I am not sure this ever works, give no error, but I am still not sure
          }.bind(this),500);

  },
  restart: function(){
    this.health =100;
    this.ended = false; // works partially, no img change when health is 0, though
  }
}

});

相关的 CSS:

#bag.noSwing {
width: 300px;
height: 500px;
margin: -80px auto;
background: url("https://3.imimg.com/data3/VM/TI/MY-18093/classical-heavy-
bag-250x250.png") center no-repeat;
background-size: 70%;
-webkit-animation-name: swingRight;
-webkit-animation-duration:1s;
-webkit-animation-iteration-count: 1;
-webkit-transition-timing-function: cubic-bezier(.11,.91,.91,.39);
-webkit-animation-fill-mode: forwards;
-webkit-transform-origin: center;
      transform-origin: center;
 }

#bag.swingLeft {
width: 300px;
height: 500px;
margin: -80px auto;
background: url("https://3.imimg.com/data3/VM/TI/MY-18093/classical-heavy-
bag-250x250.png") center no-repeat;
background-size: 70%;
-webkit-animation-name: swingLeft;
-webkit-animation-duration:1s;
-webkit-animation-iteration-count: 1;
-webkit-transform-origin: right;
      transform-origin: right;
-webkit-transition-timing-function: cubic-bezier(.91,.11,.31,.69);

 }


@keyframes swingLeft {
0% { -webkit-transform: rotate (0deg); transform: rotate (0deg); }
20% { -webkit-transform: rotate (-20deg); transform: rotate (-20deg); }
50% { -webkit-transform: rotate (20deg); transform: rotate (20deg); }
70% { -webkit-transform: rotate (-10deg); transform: rotate (-10deg); }
100% { -webkit-transform: rotate (0deg); transform: rotate (0deg); }
}

@keyframes swingRight {
0% { -webkit-transform: rotate (0deg); transform: rotate (0deg); }
 20% { -webkit-transform: rotate (20deg); transform: rotate (20deg); }
50% { -webkit-transform: rotate (-20deg); transform: rotate (-20deg); }
70% { -webkit-transform: rotate (10deg); transform: rotate (10deg); }
100% { -webkit-transform: rotate (0deg); transform: rotate (0deg); }
}

 #bag.burst {

 background: url("http://i.imgur.com/oRUzTNx.jpg") center no-repeat;
 background-size: 70%;

 }

 #bag-health {
 width: 200px;
 border: 2px solid #004;
 margin: -80px auto 20px auto;
 }

#bag-health div.safe {
height: 20px;
background: #44c466;
}

#bag-health div.dangerous {

背景:#00ffff; }

那么为什么当点击“punch it”按钮时没有应用动画,为什么它同时添加了 noSwing 和 swingLeft 类?并且它会覆盖在健康计量器达到零值时将背景图像更改为突发坏的功能。

【问题讨论】:

  • 为什么一个 div 上有 2 个 :class 道具?从来没有这样做过,所以不确定它是否会导致问题。
  • @webnoob,这是我使用 vue.js 的第二天,我在文档中找不到任何内容,我不确定它是否允许,也不确定它的语法是否正确,但它没有给我任何错误消息,并应用这些类,问题是,它不会删除其中一个。也许是实例方法中的 setTimeout。一个类绑定肯定可以正常工作,数组语法直接来自文档,这也很好,我知道有一个对象语法可以使用 v bind。
  • 您意识到noSwing 类将在您将其添加到数组末尾时始终被应用?这应该是有条件的吗?

标签: javascript css vue.js


【解决方案1】:

首先,你不能在同一个元素上拥有 2 个类绑定,你也不应该需要它们。

你有很多关于添加/删除类的逻辑,所以我建议将它提取到计算:

computed: {
  className () {
      let classes= [];
          if (this.animationToggle){
             classes.push(this.activeClass)
          }
          else{
             classes.push('swingLeft')
          }
      return classes;

      }
  }
}


<div id="bag" :class="className"></div>

【讨论】:

  • 这和我的代码一样工作,但它覆盖了“{ burst:ended }”绑定,感谢您澄清只有一个类绑定是可能的。是否有第二个绑定的解决方案,因为它从未应用过。?方法中类的删除也会导致问题,如果我删除它,则没有任何效果,如果我将它留在那里,动画将不会按应有的方式开始。如果您可以检查,现在笔上的代码就是我上面描述的。也许 v-on:click="!animationToggle" (在 punch it 按钮上)可以解决问题吗?
  • 这只是一个例子,你可以将任何你想要的类添加到这个数组中!只需将“burst”推送到数组中,它就会被添加
  • 嗯,如果我在数组中同时应用两者,它会立即添加突发类。要仅在最后添加突发类,我需要另一个 if 子句,对吗?另一件事是为什么每次点击都会重新渲染整个图像?
  • 你需要根据你需要的逻辑添加/删除突发类,所以显然它需要if/else。我不知道为什么会渲染整个图像。
猜你喜欢
  • 2013-08-17
  • 2015-06-26
  • 1970-01-01
  • 2017-10-26
  • 1970-01-01
  • 1970-01-01
  • 2017-12-10
  • 1970-01-01
  • 2013-01-28
相关资源
最近更新 更多