如何在Vue.js中在两个不同的条件下绑定两个类



我正在用Vue(v2.x.x(开发一个小型结账步进器。

当前项应该具有类名";活动的";而所有前面的都具有类名";完成";,如下图所示:

* {
margin: 0;
padding: 0;
font-family: "Poppins", sans-serif;
}
.progressbar {
display: flex;
list-style-type: none;
counter-reset: steps;
padding-top: 50px;
justify-content: space-between;
}
.progressbar li {
font-size: 13px;
text-align: center;
position: relative;
flex-grow: 1;
flex-basis: 0;
color: rgba(0, 0, 0, 0.5);
font-weight: 600;
}
.progressbar li.completed {
color: #ccc;
}
.progressbar li.active {
color: #4caf50;
}
.progressbar li::after {
counter-increment: steps;
content: counter(steps, decimal);
display: block;
width: 30px;
height: 30px;
line-height: 30px;
border: 2px solid rgba(0, 0, 0, 0.5);
background: #fff;
border-radius: 50%;
position: absolute;
left: 50%;
margin-left: -15px;
margin-top: -60px;
}
.progressbar li.active::after,
.progressbar li.completed::after {
background: #4caf50;
border-color: rgba(0, 0, 0, 0.15);
color: #fff;
}
.progressbar li.completed::after {
content: '2713';
}
.progressbar li::before {
content: "";
position: absolute;
top: -26px;
left: -50%;
width: 100%;
height: 2px;
background: rgba(0, 0, 0, 0.5);
z-index: -1;
}
.progressbar li.active::before,
.progressbar li.completed::before,
.progressbar li.active+li::before {
background: #4caf50;
}
.progressbar li:first-child::before {
display: none;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container">
<ul class="progressbar">
<li class="completed">Shopping cart</li>
<li class="completed">Shipping</li>
<li class="active">Payment</li>
<li>Confirmation</li>
</ul>
</div>

问题

在Vue中,使用v-bind:class;活动的";班

我可以添加";已完成";类到适当的元素:

<li v-for="(step, index) in steps" v-bind:class="{completed: step.completed === true}">{{step.text}}</li>

但是,因为我还没有找到在两个不同的条件下绑定两个类的方法,所以我不能同时这两件事

var app = new Vue({
el: "#cart",
data: {
stepCounter: 1,
steps: [
{ step: 1, completed: false, text: "Shopping cart" },
{ step: 2, completed: false, text: "Shipping" },
{ step: 3, completed: false, text: "Payment" },
{ step: 4, completed: false, text: "Confirmation" }
]
},
mounted() {},
methods: {
doPrev: function() {
if (this.stepCounter > 1) {
this.stepCounter--;
this.doCompleted();
}
},
doNext: function() {
if (this.stepCounter < this.steps.length) {
this.stepCounter++;
this.doCompleted();
}
},
doCompleted: function() {
this.steps.forEach(item => {
if(item.step < this.stepCounter){
item.completed = true;
}
});
}  
}
});
* {
margin: 0;
padding: 0;
font-family: "Poppins", sans-serif;
}
.progressbar {
display: flex;
list-style-type: none;
counter-reset: steps;
padding-top: 50px;
justify-content: space-between;
}
.progressbar li {
font-size: 13px;
text-align: center;
position: relative;
flex-grow: 1;
flex-basis: 0;
color: rgba(0, 0, 0, 0.5);
font-weight: 600;
}
.progressbar li.completed {
color: #ccc;
}
.progressbar li.active {
color: #4caf50;
}
.progressbar li::after {
counter-increment: steps;
content: counter(steps, decimal);
display: block;
width: 30px;
height: 30px;
line-height: 30px;
border: 2px solid rgba(0, 0, 0, 0.5);
background: #fff;
border-radius: 50%;
position: absolute;
left: 50%;
margin-left: -15px;
margin-top: -60px;
}
.progressbar li.active::after,
.progressbar li.completed::after {
background: #4caf50;
border-color: rgba(0, 0, 0, 0.15);
color: #fff;
}
.progressbar li.completed::after {
content: '2713';
}
.progressbar li::before {
content: "";
position: absolute;
top: -26px;
left: -50%;
width: 100%;
height: 2px;
background: rgba(0, 0, 0, 0.5);
z-index: -1;
}
.progressbar li.active::before,
.progressbar li.completed::before,
.progressbar li.active+li::before {
background: #4caf50;
}
.progressbar li:first-child::before {
display: none;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js"></script>
<div id="cart">
<div class="container">
<ul class="progressbar">
<li v-for="(step, index) in steps" v-bind:class="{active: index + 1 === stepCounter}">{{step.text}}</li>
</ul>
</div>
<div class="container mt-5 text-center">
<div class="btn-group">
<button type="button" class="btn btn-sm btn-success" @click="doPrev()">Previous</button>
<button type="button" class="btn btn-sm btn-success" @click="doNext()">Next</button>
</div>
</div>
</div>

如何解决此问题?

绑定类时,它使用一个javascript对象,在该对象中可以有多个属性。

这意味着您可以分配多个类:

<li v-for="(step, index) in steps" v-bind:class="{ active: index + 1 === stepCounter, completed : index < stepCounter  }">{{step.text}}</li>

类绑定

var app = new Vue({
el: "#cart",
data: {
stepCounter: 1,
steps: [
{ step: 1, completed: false, text: "Shopping cart" },
{ step: 2, completed: false, text: "Shipping" },
{ step: 3, completed: false, text: "Payment" },
{ step: 4, completed: false, text: "Confirmation" }
]
},
mounted() {},
methods: {
doPrev: function() {
if (this.stepCounter > 1) {
this.stepCounter--;
}
},
doNext: function() {
if (this.stepCounter < this.steps.length) {
this.stepCounter++;
this.doCompleted();
}
},
doCompleted: function() {
this.steps.forEach(item => {
if(item.step < this.stepCounter){
item.completed = true;
}
});
}  
}
});
* {
margin: 0;
padding: 0;
font-family: "Poppins", sans-serif;
}
.progressbar {
display: flex;
list-style-type: none;
counter-reset: steps;
padding-top: 50px;
justify-content: space-between;
}
.progressbar li {
font-size: 13px;
text-align: center;
position: relative;
flex-grow: 1;
flex-basis: 0;
color: rgba(0, 0, 0, 0.5);
font-weight: 600;
}
.progressbar li.completed {
color: #ccc;
}
.progressbar li.active {
color: #4caf50;
}
.progressbar li::after {
counter-increment: steps;
content: counter(steps, decimal);
display: block;
width: 30px;
height: 30px;
line-height: 30px;
border: 2px solid rgba(0, 0, 0, 0.5);
background: #fff;
border-radius: 50%;
position: absolute;
left: 50%;
margin-left: -15px;
margin-top: -60px;
}
.progressbar li.active::after,
.progressbar li.completed::after {
background: #4caf50;
border-color: rgba(0, 0, 0, 0.15);
color: #fff;
}
.progressbar li.completed::after {
content: '2713';
}
.progressbar li::before {
content: "";
position: absolute;
top: -26px;
left: -50%;
width: 100%;
height: 2px;
background: rgba(0, 0, 0, 0.5);
z-index: -1;
}
.progressbar li.active::before,
.progressbar li.completed::before,
.progressbar li.active+li::before {
background: #4caf50;
}
.progressbar li:first-child::before {
display: none;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js"></script>
<div id="cart">
<div class="container">
<ul class="progressbar">
<li v-for="(step, index) in steps" v-bind:class="{active: index + 1 === stepCounter, completed : index < stepCounter  }">{{step.text}}</li>
</ul>
</div>
<div class="container mt-5 text-center">
<div class="btn-group">
<button type="button" class="btn btn-sm btn-success" @click="doPrev()">Previous</button>
<button type="button" class="btn btn-sm btn-success" @click="doNext()">Next</button>
</div>
</div>
</div>

您可以通过在绑定上使用数组来向需要的条件添加更多的类,如下所示:

<li v-for="(step, index) in steps" v-bind:class="[{completed: index < stepCounter-1},{active: index + 1 === stepCounter}]">{{step.text}}</li>

请参阅下面修改过的代码,您还可以使用一个基于参数生成类的方法来保持标记的整洁,并使用一个生成正确类的中心方法。

var app = new Vue({
el: "#cart",
data: {
stepCounter: 1,
steps: [
{ step: 1, completed: false, text: "Shopping cart" },
{ step: 2, completed: false, text: "Shipping" },
{ step: 3, completed: false, text: "Payment" },
{ step: 4, completed: false, text: "Confirmation" }
]
},
mounted() {},
methods: {
doPrev: function() {
if (this.stepCounter > 1) {
this.stepCounter--;
}
},
doNext: function() {
if (this.stepCounter < this.steps.length) {
this.stepCounter++;
this.doCompleted();
}
},
doCompleted: function() {
this.steps.forEach(item => {
if(item.step < this.stepCounter){
item.completed = true;
}
});
},
getClass: function(index, step) {
var values = [];
if (index + 1 === this.stepCounter) values.push('active');
if (step.completed) values.push('completed');
return values.join(' ');
}
}
});
* {
margin: 0;
padding: 0;
font-family: "Poppins", sans-serif;
}
.progressbar {
display: flex;
list-style-type: none;
counter-reset: steps;
padding-top: 50px;
justify-content: space-between;
}
.progressbar li {
font-size: 13px;
text-align: center;
position: relative;
flex-grow: 1;
flex-basis: 0;
color: rgba(0, 0, 0, 0.5);
font-weight: 600;
}
.progressbar li.completed {
color: #ccc;
}
.progressbar li.active {
color: #4caf50;
}
.progressbar li::after {
counter-increment: steps;
content: counter(steps, decimal);
display: block;
width: 30px;
height: 30px;
line-height: 30px;
border: 2px solid rgba(0, 0, 0, 0.5);
background: #fff;
border-radius: 50%;
position: absolute;
left: 50%;
margin-left: -15px;
margin-top: -60px;
}
.progressbar li.active::after,
.progressbar li.completed::after {
background: #4caf50;
border-color: rgba(0, 0, 0, 0.15);
color: #fff;
}
.progressbar li.completed::after {
content: '2713';
}
.progressbar li::before {
content: "";
position: absolute;
top: -26px;
left: -50%;
width: 100%;
height: 2px;
background: rgba(0, 0, 0, 0.5);
z-index: -1;
}
.progressbar li.active::before,
.progressbar li.completed::before,
.progressbar li.active+li::before {
background: #4caf50;
}
.progressbar li:first-child::before {
display: none;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js"></script>
<div id="cart">
<div class="container">
<ul class="progressbar">
<li v-for="(step, index) in steps" v-bind:class="getClass(index, step)">{{step.text}}</li>
</ul>
</div>
<div class="container mt-5 text-center">
<div class="btn-group">
<button type="button" class="btn btn-sm btn-success" @click="doPrev()">Previous</button>
<button type="button" class="btn btn-sm btn-success" @click="doNext()">Next</button>
</div>
</div>
</div>

最新更新