Home > Mobile >  Why do I need the v-bind when I have the v-on?
Why do I need the v-bind when I have the v-on?

Time:03-09

In the tutorial of vue.js, we have this code

<script>
export default {
  data() {
    return {
      text: ''
    }
  },
  methods: {
    onInput(e) {
      this.text = e.target.value
    }
  }
}
</script>

<template>
  <input :value="text" @input="onInput" placeholder="Type here">
  <p>{{ text }}</p>
</template>

And I don't understand why when I delete the bind on value, the two way binding is still working ?
In the tuto, it says that using the v-on & v-bind allow to do two way binding
Am I missing something ?

CodePudding user response:

The Vue example is sort of a bad use case, a little simple for what it's trying to convey:

v-on is for assigning event listeners, so v-on:click="doSomething(value)"

v-bind is binding the actual value of vue data/state. So example:

<button v-on:click="setUserDetails(value)" v-bind:value="user.id">Click</button>

CodePudding user response:

Imagine this component:

<template>
  <input :value="value"/>
</template>
<script>
export default {
 name: 'MyComp',
 props:{
  value: String
 }
}
</script>

And now a simple usage of it:

<template>
  <MyComp v-model="passwd" type="password" minlength="3" @focus="onFocus"/>
</template>
<script>
export default {
 name: 'MyOtherComp',
 data(){
  return {
   passwd: ''
  }
 },
 methods:{
   onFocus(){}
 }
}
</script>

As you can see, value, type, and minlength properties and focus event are bidden to MyComp.

Now question: How can I handle extra props in MyComp? they are not defined in MyComp props. Vue gathers them in a special variable called $attrs, which is a normal JS object. Vue also gathers all events into $listeners variable. Now inside MyComp these special variables are:

$atrrs:{
  type: 'password',
  minlength: '3'
}

$listerners:{
 focus: /* function onFocus from parent */
}

To redirect these values:

<template>
 <input :value="value" v-bind="$attrs" v-on="$listeners"/>
</template>

<script>
export default {
 name: 'MyComp',
 props:{
   value: String
 }
}
</script>

As you can see, we use v-bind to bind extra props, and we use v-on to bind (redirect) events. The result is:

 <input :value="value" :type="$attrs.type" :minlength="$attrs.minlength" @focus="$listeners.focus"/>

Of course you can use these directions to bind you objects too:

<template>
  <input :value="value" v-bind="$attrs" v-bind="accumulated" v-on="$listeners"/>
</template>
<script>
export default {
 name: 'MyComp',
 props:{
  value: String
 },
 data(){
   return {
    accumulated:{
     maxlenght: ( this.$attrs.minlength || 2)   30, // It's just for a practice to use extra props inside JS code :-) 
     rows: 5,
    }
   }
 }
}
</script>

Keep in mind that duplicate props will replace and the last one wins.

  • Related