I'm trying to use a shared vue.js state in a web extension.
The state is stored in the background script's DOM and rendered in a popup page.
First attempt
My first attempt was to use a simple store without vuex:
background.js
var store = {
count: 0
};
popup.js
browser.runtime.getBackgroundPage().then(bg => {
var store = bg.store;
var vue = new Vue({
el: '#app',
data: {
state: store
},
})
})
popup.html
<div id="app">
<p>{{ state.count }}</p>
<p>
<button @click="state.count++">+</button>
</p>
</div>
<script src="vue.js"></script>
<script src="popup.js"></script>
This works the first time the popup is opened (you can increment the counter and the value is updated) but when the popup is opened a second time, rendering fails with [Vue warn]: Error in render: "TypeError: can't access dead object"
. This seems to be caused by the fact that vue.js instance from the first popup modified the store
by setting its own getter/setters, which have now been deleted since the first popup was closed, making the shared state unusable. This seems to be unavoidable, so I decided I'd give vuex a try.
Second attempt
background.js
var store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment: state => state.count++,
}
})
popup.js
browser.runtime.getBackgroundPage().then(bg => {
var store = bg.store;
var vue = new Vue({
el: '#app',
computed: {
count () {
return store.state.count
}
},
methods: {
increment () {
store.commit('increment')
},
}
});
})
popup.html
<div id="app">
<p>{{ count }}</p>
<p>
<button @click="increment">+</button>
</p>
</div>
<script src="vue.js"></script>
<script src="popup.js"></script>
Unfortunately, this doesn't work either. You can open the popup and see the current counter value, but incrementing it doesn't update the view (you need to reopen the popup to see the new value).
When taking the same code but with the store declared in popup.js, the code works as intended so this should work, but for some reason it doesn't
My questions:
- Is vue.js unable to handle this use case at all?
- If so, would other frameworks (angular, react, ...) work here?