I have a component that extends another and it needs to read the root components data to update the status in its own component.
For the purposes of my answer I'm going to assume that you have two component definitions, A and B, and B extends A. I assume that when you say root you just mean A.
What I'm finding is that the component that extends the other only seems to take a copy of the root's data when it's rendered but if I update a property in the root component it's not updated in the extended component.
Rendering is not really relevant here. The data properties are set up when a component instance is created. Typically rendering will happen just after creation but merging any data happens much earlier in the component life-cycle. Even if the component isn't rendered the data will still be initialised.
No copying takes place. Let's consider a data function on component A:
data () {
return {
myArray: []
}
}
Every time this function is invoked it is going to return a new object, each containing a new array. This is precisely what happens if you create an instance of A directly. For each instance, Vue will call this function and get a new object defining the data. Generally that's what you'd want, rather that having components sharing data.
Now let's consider B. That might define its own data function. When an instance of B is created Vue will call the data function for both A and B and then merge the objects. No copying takes place, just merging. If you want to know more about how Vue handles merging in general see the documentation but for data the strategy is pretty simple. Properties from both objects will be combined with B taking precedence over A if there's a clash of property names. There is no recursive merging of properties.
So the idea of updating 'a property in the root component' is not particularly well-defined. You might be thinking of it as a bit like a prototype chain, where modifying a superclass would impact the subclass, but that isn't what's going on here. The data functions are invoked when the component is created and that's that. There isn't a lasting link back to the component definition like there is with a prototype chain.
If you really want all your component instances to share the same data value then it can be done, you just need to make sure that the data function is returning the same object/array every time. e.g.
const myArray = []
export default {
name: 'A',
data () {
return {
myArray
}
}
}
Written this way all instances of A will share the same array for myArray. So long as B doesn't define it's own value for myArray it will share it too.
For example I want to check the length of an array on the root component and update another data value. It updates the value on the root but not on the extended component.
I'm struggling a bit to understand what that means. It seems there are lots of assumptions about things being shared, single instances here. It's not entirely clear how you update the 'root' given it's a component definition and not a component instance.
If possible you should use a computed property for this. That would be inherited by B. Each instance of A (or B) would have their own value for this computed property, which might be a little wasteful if they're all going to be the same, but it's probably still the best way to go.
You could in theory use a watch. That should be inherited too but keep in mind it would be manipulating values for that particular instance.
Reading between the lines a little, if you wanted to update something on the 'root' so that it magically appeared in the subcomponents you could use the same shared reference-type trickery that I demonstrated earlier for myArray. You may need to be careful with how you update it though. If, for example, you used a watch you might find the you end up updating the same object many times, once for each instance of the component.
Update:
Based on the code you've posted it could be made to work something like this:
var myArray = [];
var a = Vue.component('a', {
data: function () {
return {
myArray: myArray // Note: using the same, shared array
}
},
methods: {
saveData : function(){
var vm = this;
axios.post('/save', {
})
.then(function (response) {
// Note: Updating the array, not replacing it
var myArray = vm.myArray;
myArray.splice(0, myArray.length);
myArray.push.apply(myArray, response.data);
})
.catch(function (error) {
console.log(error);
});
},
}
});
Vue.component('b', {
extends: a,
});
Your example didn't include any ES6 so I've refrained from using it but it would be a bit simpler if that were available.
The example above works by sharing the same array between all instances of the component and then mutating that instance. Assigning a new array to that property won't work as it would only update that particular component instance.
However, all that said, this is increasingly looking like a case where you should give up on trickery and just use the Vuex store instead.