简体   繁体   中英

Vue.js computed property setInterval

I'm new to Vue js and I have code like that:

Para.vue

<template>
  <t-row>
    <t-col :span="13">
      <t-input
        :id="id+'_tam'"
        ref="tam"
        v-model="ayristirilmisPara.tam"
        reverse
        :label="label"
        :disabled="disabled"
        name="Oran *"
        :labelSpan="15"
        :inputSpan="8"
        :maxlength="tamMaxLength"
        :vNumber="true"
        @input="updateTam"
        v-validate="{ required: this.isRequired }"
        :error="errors.first('Oran *')"
        class="para"
      />
    </t-col>
    <t-col :span="1" style="padding-left: 0px; padding-right: 0px; padding-top: 12.5px;">,</t-col>
    <t-col :span="10">
      <t-input
        ref="kesir"
        :id="id+'_kesir'"
        v-model="ayristirilmisPara.kesir"
        :maxlength="kesirMaxLength"
        :vNumber="true"
        :disabled="disabled"
        :name="'Oran Kesir *'"
        :labelSpan="0"
        :inputSpan="18"
        label
        @input="updateKesir"
        v-validate="{ required: this.isRequired }"
        :error="errors.first('Oran Kesir *')"
        class="para"
      />
    </t-col>
    <t-col :span="1"></t-col>
  </t-row>
</template>

<script>
export default {
  props: {
    tamMaxLength: {
      type: Number,
      default: 3
    },
    kesirMaxLength: {
      type: Number,
      default: 2
    },
    value: {
      type: [String, Number],
      default: "0.00"
    },
    label: {
      type: String,
      default: "",
      required: false
    },
    isRequired: {
      type: Boolean,
      default: false,
      required: false
    },
    disabled: {
      type: Boolean,
      required: false,
      default: false
    }
  },
  data() {
    return {
      tam: "0",
      kesir: "0"
    };
  },
  methods: {
    updateTam(tam) {
      if (!tam) tam = "";
      this.tam = tam;
      this.$emit("input", `${tam}.${this.kesir}`);
    },
    updateKesir(kesir) {
      if (!kesir) kesir = "";
      this.kesir = kesir;
      this.$emit("input", `${this.tam}.${kesir}`);
    }
  },
  computed: {
    ayristirilmisPara() {
        if (this.value === undefined || this.value === null) this.value = "0.0";
        const paraParcali = this.value.toString().split(".");
        let tutar = {
          tam:
            paraParcali[0] == null
              ? 0
              : paraParcali[0] || paraParcali[0] == ""
              ? 0
              : paraParcali[0],
          kesir:
            paraParcali[1] == null
              ? 0
              : paraParcali[1] || paraParcali[1] == ""
              ? 0
              : paraParcali[1]
        };
        this.tam = tutar.tam;
        this.kesir = tutar.kesir;
        this.$emit("input", `${tutar.tam}.${tutar.kesir}`);

        return tutar;
    }
  }
};
</script>
<style>
.el-input {
  min-width: 45px;
}
.para .el-input__inner {
  padding: 0px;
}
</style>

It works fine. It puts automatically 0 when user tries to delete all the input area with id'+_tam' and id+'_kesir'. What I want to do is, I want to wait 3 seconds for user to enter an input, if s/he doesnt enter one, then I will put the 0. I have tried to code below in computed property:

 computed: {
    ayristirilmisPara() {
      setInterval(function() {
        if (this.value === undefined || this.value === null) this.value = "0.0";
        const paraParcali = this.value.toString().split(".");
        let tutar = {
          tam:
            paraParcali[0] == null
              ? 0
              : paraParcali[0] || paraParcali[0] == ""
              ? 0
              : paraParcali[0],
          kesir:
            paraParcali[1] == null
              ? 0
              : paraParcali[1] || paraParcali[1] == ""
              ? 0
              : paraParcali[1]
        };
        this.tam = tutar.tam;
        this.kesir = tutar.kesir;
        this.$emit("input", `${tutar.tam}.${tutar.kesir}`);

        return tutar;
      }, 3000);
    }
  }

But it didn't work. How can I do that? Thank you for your interest.

  1. use the "watch" section indicating "value" watch instead of the "computed" section:
watch: {
  value (newValue) {
    setInterval(...)
  }
}
  1. The function that is passed to setInterval should be binded to 'this' as it was mentioned above

First of all, you have a this issue, since you are having setInterval(function() { , with that this points to your function and not the component. You can solve that by either using fat arrow syntax setInterval(() => ) or then use const self = this; before the function. Also by suggested in comments, add this piece of code to watch instead of computed . But if you are using setInterval , you need to also remember to clear the interval before starting a new, since otherwise you end up creating a new interval each time. So here I use setTimeout , the case is the same, you need to clear the timout before starting a new. Simplified sample:

data: function() {
  return {
    text: "",
    myTimeout: ""
  };
},
watch: {
  text(newValue) {
    clearTimeout(this.myTimeout);
    this.myTimeout = setTimeout(() => {
      console.log(this.text);
    }, 3000);
  }
}

or with using function , modify your watch to:

watch: {
  text(newValue) {
    const self = this;
    clearTimeout(this.myTimeout);
    this.myTimeout = setTimeout(function() {
      console.log(self.text);
    }, 3000);
  }
}

Here's a SANDBOX

That's because your returning of tutar is happening within a callback. ayristirilmisPara() itself is not the one returning tutar.

Remember, It's very important to actual return a value from computed property. Otherwise, Vue won't know what the value should be.

Also keep in mind that, changing or mutating an underline data value in a computed property, is a big source of headaches and bugs.

  • When you need to change data - use methods
  • When you need to change the presentation of existing data - use computed

Take a look at these and you will get the answer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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