[英]Multiple range inputs related on number from parent
我有 4 个范围输入。 他们每个人的最小数字为 0,最大数字为 10。它们的总和不能超过 22。
解决此问题的一种方法是在所有输入达到 22 后禁用所有输入并添加一个重置按钮。 我会发现它更加用户友好,允许在达到最大值而不是整个重置后减小范围。
如果它小于或等于 0,我尝试禁用它,但滚动条仍在控制之下。
如果更容易,请查看沙箱的注释,但父 class 如下:
<template>
<div class="vote">
<div class="vote__title">Left: <span>{{ hmLeft }}</span> votes</div>
<div class="vote__body">
<div v-for="user in activeInnerPoll" :key="user._id">
<userVoteFor :hmLeft="hmLeft" @cntCount="cntCount" :id="user._id"/>
</div>
</div>
</div>
</template>
<script>
import { mapGetters } from "vuex"
import userVoteFor from "@/components/userVoteFor";
export default {
name: "Vote.vue",
components: {
userVoteFor
},
data(){
return {
votes: 22,
objRes: {} // that's where we write what id of a user and how many counts
}
},
computed: {
...mapGetters("polls", ["activeInnerPoll"]), // array of objects {_id : "some_id", cnt: 0}
hmLeft(){ // how much left, counter which tells how many votes left
let sum = 0;
for(let key in this.objRes){
sum += this.objRes[key];
}
return this.votes - sum;
}
},
methods: {
cntCount(id, cnt){ // emit for children, gets id and cnt of input-range and sets to result obj
this.objRes[id] = parseInt(cnt);
}
}
}
</script>
<style scoped lang="scss">
@import "@/assets/vars.scss";
@import "@/assets/base.scss";
.vote{
&__title{
@include center;
margin-top: 15px;
span{
font-size: 20px;
margin: 0 5px;
color: $pink;
}
}
}
</style>
儿童 class 在这里:
<template>
<div class="vote__component">
<label class="vote__component__label" :for="id">{{ playerNameById( id )}}</label>
<input @input="check($event)" // thought maybe something to do with event ?
:disabled="disable"
class="vote__component__input"
:id="id"
type="range"
min="0"
max="10"
step="1"
v-model="cnt">
<div class="vote__component__res">{{ cnt }}</div>
</div>
</template>
<script>
import { mapGetters } from "vuex";
export default {
name: "userVoteFor.vue",
props: {
id: {
type: String,
required: true
},
hmLeft: {
type: Number,
required: true
}
},
emits: ["cntCount"],
data() {
return {
cnt: 0,
disable: false,
lastVal: 0
}
},
computed: {
...mapGetters("user", ["playerNameById"]) // gets map object which stores names for user by id
},
methods: {
check(e){
console.log(e);
if(this.hmLeft <= 0) { //HERE IS APART WHERE I THINK SHOULD BE WRITTEN LOGIC if hmLeft <= 0 then ... , else write cnt in resObj and computed var will calc how many votes left
this.lastVal = this.cnt;
this.cnt = this.lastVal;
}
else this.$emit("cntCount", this.id, this.cnt);
}
}
}
</script>
<style scoped lang="scss">
.vote__component{
width: 80%;
margin: 10px auto;
position: relative;
display: flex;
justify-content: right;
padding: 10px 0;
font-size: 15px;
&__input{
margin-left: auto;
width: 60%;
margin-right: 20px;
}
&__res{
position: absolute;
top: 20%;
right: 0;
}
&__label{
}
}
</style>
我实现这一点的方法是使用watch
和computed
的get
和set
方法。
值数组将通过计算更新。 这使得挂钩到v-model
变得很容易,并允许我们保持与原始数组的反应性。
然后使用手表来计算可用的总数。 然后,对于加分,我们可以使用总来调整输入的宽度,使步长保持一致。
即使这是使用组合 Api,您也可以使用data
、 watch
和computed
经典方式来实现它
const makeRange = (max, vals, index) => { const defaultMax = 10; const num = Vue.computed({ get: () => vals[index], set: value => vals[index] = Number(value) }); const total = Vue.computed(() => vals.reduce((a, b) => a + b, 0), vals); const style = Vue.computed(() => { return `width: ${(numMax.value * 12 + 20)}px` }) const numMax = Vue.computed(() => { return Math.min(defaultMax, (num.value + max - total.value)) }, total); return {num, numMax, style}; }; const app = Vue.createApp({ setup() { const vals = Vue.reactive([5, 5, 5]) const max = 22; const ranges = vals.map((v,i)=>makeRange(max, vals, i)); // helpers for visualising const total = Vue.computed(() => vals.reduce((a, b) => a + b, 0), vals); const totalLeft = Vue.computed(() => max - total.value, total.value); return {ranges, vals, totalLeft, total, max}; } }).mount('#app');
<script src="https://unpkg.com/vue@3.0.2/dist/vue.global.prod.js"></script> <div id="app"> <li v-for="range in ranges"> <input:style="range.style.value" type="range" min="0":max="range.numMax.value" v-model="range.num.value" > value: {{range.num.value}} max: {{range.numMax.value}} </li> <li>{{ vals.join(' + ') }} = {{ total }}</li> <li>max is {{ max }}, minus total {{total }} is {{ totalLeft }}</li> </div>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.