You can watch the props by using a watcher function in your parent (Form.vue) component inside the mounted hook.

You have to just attach a ref to your top most child component. For ex :

<order-form-info :name="name" :phone="phone" ref="orderFormComponent"></order-form-info>

Live Demo :

Vue.component('orderFormInfo', {
  props: ['name', 'phone'],
  template: `<div>
    <input-field
      placeholder="phone number"
      type="text"
      v-model="phone"/>
    <input-field
      placeholder="recipient name"
      type="text"
      v-model="name"/>
  </div>`
});

Vue.component('inputField', {
  props: ['value', 'placeholder'],
  template: `<input
:value="value"
@input="$emit('input', $event.target.value)"
:placeholder="placeholder"
/>`
});

var app = new Vue({
  el: '#form',
  data: {
    name: 'Alpha',
    phone: '1111111111'
  },
  mounted() {
    this.$watch(
      "$refs.orderFormComponent.phone", (newVal, oldVal) => {
         console.log(newVal, oldVal)
      }
    );
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="form">
  <order-form-info :name="name" :phone="phone" ref="orderFormComponent"></order-form-info>
</div>

Answer from Rohìt Jíndal on Stack Overflow
🌐
Vue.js
v2.vuejs.org › v2 › api
API - Vue 2
The special case to note here is the data option - it must be a function when used with Vue.extend(). ... Defer the callback to be executed after the next DOM update cycle. Use it immediately after you’ve changed some data to wait for the DOM update. New in 2.1.0+: returns a Promise if no ...
Introduction
Vue 2 has reached EOL and is no longer actively maintained.
Computed Properties and Watchers
Vue 2 has reached EOL and is no longer actively maintained.
Top answer
1 of 3
2

You can watch the props by using a watcher function in your parent (Form.vue) component inside the mounted hook.

You have to just attach a ref to your top most child component. For ex :

<order-form-info :name="name" :phone="phone" ref="orderFormComponent"></order-form-info>

Live Demo :

Vue.component('orderFormInfo', {
  props: ['name', 'phone'],
  template: `<div>
    <input-field
      placeholder="phone number"
      type="text"
      v-model="phone"/>
    <input-field
      placeholder="recipient name"
      type="text"
      v-model="name"/>
  </div>`
});

Vue.component('inputField', {
  props: ['value', 'placeholder'],
  template: `<input
:value="value"
@input="$emit('input', $event.target.value)"
:placeholder="placeholder"
/>`
});

var app = new Vue({
  el: '#form',
  data: {
    name: 'Alpha',
    phone: '1111111111'
  },
  mounted() {
    this.$watch(
      "$refs.orderFormComponent.phone", (newVal, oldVal) => {
         console.log(newVal, oldVal)
      }
    );
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="form">
  <order-form-info :name="name" :phone="phone" ref="orderFormComponent"></order-form-info>
</div>

2 of 3
0

I was able to solve it this way, I found an article on the Internet. Here are the changes:

OrderFormInfo.vue

     <Input
          placeholder="Phone number"
          type="text"
          :error-status="false"
          :errors="[]"
          :value="phone"
          @input="$emit('input-phone', $event)"
     />

OrderForm.vue

  <OrderFormInfo.
      v-if="step === 'info'"
      :name="name"
      @input-name="name = $event"
      :phone="phone"
      @input-phone="phone = $event"
      @next-step="handleNext"
  />
Top answer
1 of 2
76

No difference in your specific example, but there is a very important difference between those two notations, specially when it comes to Vue.js: the this won't reflect the vue instance in arrow functions.

So if you ever have something like:

export default {
    props: ['stuffProp'],
    data: () => ({
      myData: 'someData',
      myStuff: this.stuffProp
    })
}

It won't work as you expect. The this.stuffProp won't get the stuffProp prop's value (see below for more on the reason why).

Fix

Change the arrow function to, either (ES6/EcmaScript 2015 notation):

export default {
    props: ['stuffProp'],
    data() {                                   // <== changed this line
      return {
        myData: 'someData',
        myStuff: this.stuffProp
      }
    }
}

Or to (regular, ES5 and before, notation):

export default {
    props: ['stuffProp'],
    data: function() {                           // <== changed this line
     return {
        myData: 'someData',
        myStuff: this.stuffProp
      }
    }
}

Reason

Don't use arrow functions (() => {}) when declaring Vue methods. They pick up the this from the current scope (possibly window), and will not reflect the Vue instance.

From the API Docs:

Note that you should not use an arrow function with the data property (e.g. data: () => { return { a: this.myProp }}). The reason is arrow functions bind the parent context, so this will not be the Vue instance as you expect and this.myProp will be undefined.

2 of 2
0

It has something to do with ES5 or ES6 syntax, If you have used arrow functions ()=> in your previous scripts it is safe to use the following codes.

// tested and this.myData can be accessed in the component
data: () => { return {
    myData: 'someData',
    myStuff: this.stuffProp
} }

// this also works
data: () => ({
    myData: 'someData',
    myStuff: this.stuffProp
})

🌐
Vue.js
vuejs.org › guide › essentials › component-basics.html
Components Basics | Vue.js
export default { // ... data() { return { posts: [ { id: 1, title: 'My journey with Vue' }, { id: 2, title: 'Blogging with Vue' }, { id: 3, title: 'Why Vue is so fun' } ] } } } js ·
🌐
Handsontable
handsontable.com › docs › javascript-data-grid › vue-installation
Installation - Vue 2 Data Grid | Handsontable
October 2, 2025 - Install Handsontable's Vue 2 wrapper via npm, import the stylesheets, and get your application up and running. ... This component needs the Handsontable library to work. Use npm to install the packages. ... <template> <hot-table theme="ht-theme-main" :data="data" :rowHeaders="true" :colHeaders="true" > </hot-table> </template> <script> import { HotTable } from '@handsontable/vue'; import { registerAllModules } from 'handsontable/registry'; import 'handsontable/styles/handsontable.min.css'; import 'handsontable/styles/ht-theme-main.min.css'; // register Handsontable's modules registerAllModules(); export default { data: function() { return { data: [ ["", "Ford", "Volvo", "Toyota", "Honda"], ["2016", 10, 11, 12, 13], ["2017", 20, 11, 14, 13], ["2018", 30, 15, 12, 13] ], }; }, components: { HotTable } } </script>
🌐
Vue.js
v2.vuejs.org › v2 › guide › instance
The Vue Instance — Vue.js
Each Vue instance goes through a series of initialization steps when it’s created - for example, it needs to set up data observation, compile the template, mount the instance to the DOM, and update the DOM when data changes.
🌐
Vue.js
vuejs.org › api › options-state.html
Options: State | Vue.js
interface ComponentOptions { data?( this: ComponentPublicInstance, vm: ComponentPublicInstance ): object } ... The function is expected to return a plain JavaScript object, which will be made reactive by Vue. After the instance is created, the reactive data object can be accessed as this.$data.
Find elsewhere
🌐
Vue.js
v2.vuejs.org › v2 › guide › components.html
Components Basics - Vue 2
February 17, 2022 - Upgrade to Vue 3 or learn more about | Vue 2 EOL. ... Join the Vue.js Community! ... Components are reusable Vue instances with a name: in this case, <button-counter>. We can use this component as a custom element inside a root Vue instance created with new Vue: Since components are reusable Vue instances, they accept the same options as new Vue, such as data, computed, watch, methods, and lifecycle hooks.
🌐
EDUCBA
educba.com › home › software development › software development tutorials › javascript technology tutorial › vue.js data()
Vue.js data() | How data() Works in vue.js with Examples
April 13, 2023 - <template> <div> <h1>Programming Language: {{name1}}</h1> <h1>Scripting language: {{name2}}</h1> <h1>{{Msg()}}</h1> </div> </template> <script> export default { data: function() { return { name1: "Node.js ", name2: "Java Script" }; }, methods:{ Msg:function(){ return 'Coding done by' +this.name1 +''+ this.name2 } } } </script> <style> #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style> Explanation: This is another simple example of data function with methods. Illustrate the end result of the above declaration by using the use of the following snapshot. Emit data in vue.js with event ·
Address   Unit no. 202, Jay Antariksh Bldg, Makwana Road, Marol, Andheri (East),, 400059, Mumbai
🌐
Rv-grid
rv-grid.com › guide › vue2
Vue 2 Data Grid | RevoGrid
Use Vue 2 Data Grid to build fast, scalable data applications with support for virtual rows and columns.
🌐
Handsontable
handsontable.com › docs › javascript-data-grid › vue-basic-example
Basic example - Vue 2 Data Grid | Handsontable
October 23, 2025 - import { HotTable } from '@handsontable/vue'; import { registerAllModules } from 'handsontable/registry'; import 'handsontable/styles/handsontable.css'; import 'handsontable/styles/ht-theme-main.css'; // register Handsontable's modules registerAllModules(); const ExampleComponent = { data() { return { hotSettings: { themeName: 'ht-theme-main', data: [ ['', 'Ford', 'Volvo', 'Toyota', 'Honda'], ['2016', 10, 11, 12, 13], ['2017', 20, 11, 14, 13], ['2018', 30, 15, 12, 13] ], colHeaders: true, height: 'auto', autoWrapRow: true, autoWrapCol: true, licenseKey: 'non-commercial-and-evaluation' } }; }, components: { HotTable } }; export default ExampleComponent;
Top answer
1 of 2
51

It seems as though the comments on your question missed a key point when considering your specific code example.

In a root Vue instance i.e. constructed via new Vue({ ... }), you can simply use data: { ... } without any problems. The issue is when you have reusable components that are defined via Vue.component(...). In these instances, you need to either use data() {return { ... };} or data: function() {return { ... };}.

The reason for this is to ensure that for each individual instance of the reusable child component, there is a unique object containing all of the data being operated on. If, in a child component, you instead use data: { ... }, that same data object will be shared between the child components which can cause some nasty bugs.

Please review the corresponding section of the Vue.js documentation for more information regarding this problem.

2 of 2
0

[Vue warn]: The "data" option should be a function that returns a per-instance value in component definitions.

so initiating a new vue instance dose not matter between data:{} as a object or data(){return{}} or data:function(){return{}}.

It matters when it comes to component lets try an example:

<body>
    <div id="app">
        <counter></counter>
        <counter></counter>
    </div>
    <script>
         Vue.component('counter', {
             template: '<button v-on:click="counter += 1">{{ counter }}</button>',
             data: {
                 counter:0
             }
         });
    </script>

Output:

[Vue warn]: The "data" option should be a function that returns a per-instance value in component definitions.

Now lets watch in vue object:

<body>
    <div id="app">
        <button v-on:click="counter += 1">{{ counter }}</button>
        <button v-on:click="counter += 1">{{ counter }}</button>
    </div>
    <script>

        new Vue({
            el: '#app',
            /*data() {
                return {
                    counter:0
                }
            },*/
            //or (output same)
            /*data: function () {
                return {
                    counter: 0
                }
            }*/
            //or (output same)
            data:{
                counter:0
            }

        });
    </script>

</body>

//Now let's try data as a function in the component to reuse same component over and over again.

<body>
    <div id="app">
        <counter></counter>
        <counter></counter>
        <counter></counter>
    </div>
    <script>

        Vue.component('counter', {
            template: '<button v-on:click="counter += 1">{{ counter }}</button>',
            data: function () {
                return {
                    counter: 0
                }
            }
        })

        new Vue({
            el: '#app'
        });
    </script>

</body>
🌐
Vue.js
v2.vuejs.org › v2 › guide
Introduction — Vue.js
Here, it is basically saying “keep this element’s title attribute up-to-date with the message property on the Vue instance.” · If you open up your JavaScript console again and enter app2.message = 'some new message', you’ll once again see that the bound HTML - in this case the title attribute - has been updated. ... Go ahead and enter app3.seen = false in the console. You should see the message disappear. This example demonstrates that we can bind data to not only text and attributes, but also the structure of the DOM.
🌐
Stack Overflow
stackoverflow.com › questions › 77678599 › vue-2-how-to-do-static-data-declaration-inside-component
vuejs2 - Vue 2, How to do Static Data Declaration inside component - Stack Overflow
data() { return { tableHeaders: [{name: "uma"}] }; }, let assume tableHeaders im using in template to display something. But is it necessary to decalre tableHeaders insid...
🌐
Smashing Magazine
smashingmagazine.com › 2020 › 01 › data-components-vue-js
How To Pass Data Between Components In Vue.js — Smashing Magazine
Then, in our template, we can give those attributes values and — BAM — we’re passing data from a parent to a child component! For example, let’s say we’re working on a user profile page and want to have a child component accept a username prop. We’ll need two components. The child component accepting the prop, let’s call this AccountInfo.vue.