The application has various tools (Pages) with its structure. For example, the hotel search tool (in the left pane of the list, on the right map), or the report tool (full width page), and there are many such tools.
I found an interesting component for working with panels on github. And he began to do something like this:
//MyPanes.vue
<splitpanes class="default-theme" horizontal>
<span>
<div class="left-panel"><slot name="left"></slot></div>
</span>
<span splitpanes-min="20" splitpanes-max="50" :splitpanes-default="horizontal_splitter[1]">
<div class="right-panel"><slot name="right"></slot></div>
</span>
</splitpanes>
//HotelTool.vue
<MyPanes>
<template slot="left">
<v-btn @click.native="add">Add counter</v-btn>
</template>
<template slot="right">
<div>{{ counter }}</div>
<v-map />
</template>
</MyPanes>
..
data: {
counter: 0
},
methods: {
add() { this.counter++; }
}
..
The counter is made for the test. But it does not work. Probably because the contents of the slot does not know about the data of the parent.
Thus the question arises. How to implement this behavior? Need to abandon slots?
Of course, you can do it via event bus or store, but I have a lot of tools, and it’s not very convenient to transfer data in this way. I would like to create the instrument in one file, write logic in it for the left and right parts so that they know about each other. And so do all the tools.
Could you share your thoughts? How to change data between slots in the context of a single parent? And are there any other solutions?
Example tool Example tool On the left and right side there may be different components.
Full code:
<template>
<MyPanes>
<template v-slot:left>
<h1>Мониторинг</h1>
<v-btn @click.native="add">{{ counter }}</v-btn>
</template>
<template v-slot:right>
{{counter}}
</template>
</MyPanes>
</template>
<script>
export default {
data() {
return {
counter: 0,
}
},
methods: {
add: function () {
this.counter++;
}
}
}
</script>
There shouldn't be an issue here with data scope because the reference to the data is all done inside the 'HotelTool' instance.
Don't forget that 'data' is a function that returns an object in Vue:
data() {
return {
counter: 0
}
},
methods: {
add() { this.counter++; }
}
Please also update your @click event to fire passively by replacing the .native with .passive:
<v-btn @click.passive="add">Add counter</v-btn>
Splitpanes documentation claims to disable or block reactivity by default on their website. You can add the watch-slots element to restore reactivity.
<splitpanes watch-slots class="default-theme" horizontal>
....
As a more general answer for future readers asking the same question, sharing data between instances in Vue can be achieved by:
Passing to props and emitting with events (recommended): VueJS.org Props and, VueJS.org Custom Events
A global data 'store': Vuex Guide
I would recommend getting used to the first option, as this is recommended in the Vue documentation and adequate for most scenarios. The Vuex approach starts to become useful for larger applications.
Tip: Vue's console errors are pretty useful and often the first place to look for errors involving scope. They also offer a Chrome extension to help give visibility of your applications state in real time.