繁体   English   中英

与来自父级的数字相关的多个范围输入

[英]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>

我实现这一点的方法是使用watchcomputedgetset方法。

值数组将通过计算更新。 这使得挂钩到v-model变得很容易,并允许我们保持与原始数组的反应性。

然后使用手表来计算可用的总数。 然后,对于加分,我们可以使用总来调整输入的宽度,使步长保持一致。

即使这是使用组合 Api,您也可以使用datawatchcomputed经典方式来实现它

 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM