1
\$\begingroup\$

I wrote a code like below - It is nuxt.js, which is one of the Vue frameworks. This code will be expected to

  • When change event triggered, update data value. There would be some logic to alter passed data
  • At the same time, it connected with data value to apply input box changing

<template>
  <div>
    <!-- I got question here -->
    <input type="text" ref="receiver" @change="applyData('receiver')" v-model="deliveryInfo.receiver" />
    <button type="button" @click="test">TEST</button>
  </div>
</template>
<script>
  export default {
    data: function () {
      return {
        deliveryInfo: {
          receiver: ''
        }
      }
    },
    methods: {
      applyData: function (refName) {
        let ref = this.$refs[refName];
        if (ref) {
          let temp = {};
          temp[refName] = ref.value;
          this.applyAddress(temp);
        } else {
          console.log("There is no " + refName + " in this.$refs");
        }
      },
      applyAddress: function (options) {
        this.deliveryInfo = Object.assign({}, this.deliveryInfo, options);
        this.$emit('applyChildData', this.deliveryInfo);
      },

      test: function () {
          console.log('set John Doe');
        this.deliveryInfo = Object.assign({}, this.deliveryInfo, {receiver: 'John Doe'});
        console.log('After change ', this.deliveryInfo);
        // It triggers applyData method and change input element value
        // But when I remove v-model in input value, it is not working
      }
    }
  }
</script>

And it works as expected.

However, using v-model and @change at the same tag looks weird to me since both of tag manipulates the connected value(in this case, it would be deliveryInfo.receiver)

Is this code OK to use in production project? Thanks!

FYI, in my real case, it applied to a phone number. I want to show a phone number without dashes in a browser, but data should be saved with dashes.

So when people type in the input, @change alter data to insert dashes.

\$\endgroup\$
1
  • \$\begingroup\$ The point is @change and v-model at the same time is OK or not. I comment this since it seems the point of the post is not clear enough \$\endgroup\$ – Juneyoung Oh Oct 17 '18 at 4:48
1
\$\begingroup\$

Responding to Your question

This is good use of ref and Object.assign() but normally this would be a good place to use a watched Property, or if you need to add dashes, a computed property.

Take a look at the example below, which uses a watcher, instead of the @onchange, which means that the method applyData() can be eliminated:

const form = new Vue({
    el: '#form',
    data: function () {
      return {
        deliveryInfo: {
          receiver: ''
        }
      }
    },
    watch: {
      'deliveryInfo.receiver': function(newValue, oldValue) {
        console.log('receiver changed - deliveryinfo:', this.deliveryInfo);
        this.$emit('applyChildData', this.deliveryInfo);
      }
    },
    methods: {
      test: function () {
          console.log('set John Doe');
        this.deliveryInfo = Object.assign({}, this.deliveryInfo, {receiver: 'John Doe'});
        console.log('After change ', this.deliveryInfo);
        // It triggers applyData method and change input element value
        // But when I remove v-model in input value, it is not working
      }
    }
  });
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

  <div id="form">
    <!-- I got question here -->
    <input type="text" ref="receiver" v-model="deliveryInfo.receiver" /><!--@change="applyData('receiver')"-->
    <button type="button" @click="test">TEST</button>
  </div>

Or the snippet below which uses a computed property to add a dash between the third and fourth characters...

const form = new Vue({
    el: '#form',
    data: function () {
      return {
        deliveryInfo: {
          receiver: ''
        }
      }
    },
    computed: {
      dashedReceiver: function() {
        if (this.deliveryInfo.receiver.length > 3) {
          return this.deliveryInfo.receiver.slice(0,3) + '-' + this.deliveryInfo.receiver.slice(3);
        }
        return this.deliveryInfo.receiver;
      }
    }
  });
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

  <div id="form">
    <!-- I got question here -->
    <input type="text" ref="receiver" v-model="deliveryInfo.receiver" />
    <div>{{dashedReceiver}}</div>
  </div>

Other feedback

One other critique I have is this line:

let ref = this.$refs[refName];

That variable never gets re-assigned so to avoid accidental re-assignment, use const instead of let. There are some who recommend the following:

  • use const by default
  • only use let if rebinding is needed 1

There may not be much of a performance difference here although after reading some SO answers like this one and this one there is a potential but that might only be if a primitive type value (e.g. 42) was used.

1https://mathiasbynens.be/notes/es6-const

\$\endgroup\$
2
  • \$\begingroup\$ Thanks for the advice. However, I got one more question from your reply. You mentioned the keywords, let and const. I agree with yours since the variable will be never assigned after initial assign, but is there any other reasons to use const without semantical reasons? like performance... \$\endgroup\$ – Juneyoung Oh Oct 18 '18 at 2:48
  • 1
    \$\begingroup\$ I have updated my answer to respond to your question \$\endgroup\$ – Sᴀᴍ Onᴇᴌᴀ Oct 18 '18 at 3:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.