How to correctly bind a component property that is updated by a webservice in vuejs - vue.js

I have a simple page that gets its data from a set of web services and they are called in an interval. I want to update the page every time the web services gets new data.
My current issue is that while I am getting the data but the child component are not updating themselves and are not showing themselves at all. I have also tried this with static data which works correctly so I am guessing that I am not binding the properties correctly.
Below is the html and script pages
<div class="columns" id="app">
<div class="column">
<process-list v-bind:processesInfo="serverProcesses"></process-list>
</div>
<div class="column">
<article class="message is-info">
<div class="message-header">
<p>System info</p>
</div>
<div class="message-body">
<pre> <code> {{ memoryResponse }} </code></pre>
<pre>memory and Storage info </pre>
</div>
</article>
</div>
</div>
script
Vue.config.devtools = true
Vue.component('process-info', {
template:' <article class="message is-info">' +
' <div class="message-header">' +
' <p> {{ process.Process }} id: {{ process.ProcessID }}</p>' +
' </div>' +
' <div class="message-body">' +
' <ul>' +
' <li><strong>I/O Writes (Bytes per sec) : </strong> {{ process.IOWrites }} </li>' +
' <li><strong>Virtual Bytes : </strong> {{ process.VirtualBytes }} </li>'+
' <li><strong>Virtual Bytes Peak : </strong> {{ process.VirtualBytesPeak }}</li>'+
' <li><strong>Working Set : </strong> {{ process.WorkingSet }}</li>'+
' <li><strong>Working Set Peak : </strong> {{ process.WorkingSetPeak }}</li> '+
' <li><strong>% Processor Time : </strong> {{ process.ProcessorTime }}</li>' +
' </ul>' +
' </div>' +
' </article>',
props:['process']
});
Vue.component('process-list', {
template:' <div><div v-for="process in processesInfo"> ' +
' <process-info v-bind:process="process"></process-info>'+
'</div></div>' ,
props:['processesInfo'],
// watch:{
// processesInfo(value) {
// this.myProps = value.Processes
// }
// },
// data() {
// return {
// /* processesInfo: [
// {"Process": "edmserver","ProcessID": "20792","IOWrites": "267","VirtualBytes": "4.294967E+09 MB","VirtualBytesPeak": "4.294967E+09 MB","WorkingSet": "1.387725E+07 MB","WorkingSetPeak": "3.692052E+08 MB","ProcessorTime": "0"},
// {"Process": "edmappserver","ProcessID": "17372","IOWrites": "96","VirtualBytes": "4.294967E+09 MB","VirtualBytesPeak": "4.294967E+09 MB","WorkingSet": "5.326848E+07 MB","WorkingSetPeak": "8.826388E+08 MB","ProcessorTime": "0"}
// ] */
// }
// },
})
var app = new Vue({
el: '#app',
data: {
serverProcesses : [],
serverInfo : null,
backupResponce : 'No data!',
memoryResponse : 'No data!',
edmStatusInterval: null,
edmStatusAttemptNumber : 0,
interval : 5000
},
methods: {
pullingEDMstatus : function() {
this.edmStatusInterval = setInterval(this.checkEDMstatus, this.interval);
},
stopPullings : function() {
clearInterval(this.edmStatusInterval);
},
checkEDMstatus : function() {
this.edmStatusAttemptNumber += 1;
fetch(getEDMstatusUrl(), {
method: "POST",
headers: {
"Content-Type": "text/plain"
}
})
.then(response => response.json())
.then(data => {
this.serverProcesses = JSON.stringify(data.Processes, null, 4)
this.serverInfo = JSON.stringify(data.System, null, 4)
})
.catch(error => {
if(error.message === 'Failed to fetch') {
generateErrorMsg('503','Service Unavailable')
} else {
generateErrorMsg('', error.message)
}
})
}
},
beforeDestroy() {
clearInterval(this,polling)
},
created() {
this.pullingEDMstatus()
}
})
I tried to use the v-bind but this does not work here and I don't know what I'm doing wrong. Also I have read that I need to use a watch when the parent property is updated but again did not work for me.
By the way this is my first attempt with vuejs so links and examples are appreciated.
cheers,
es

To solve this problem I moved the methods from the main to the components themselves
Vue.component('process-list', {
template:' <div><div v-for="process in processesInfo"> ' +
' <process-info v-bind:process="process"></process-info>'+
'</div></div>' ,
data() {
return {
processesInfo : [],
statusInterval: null,
interval : 5000
}
},
methods: {
pullingStatus : function() {
this.statusInterval = setInterval(this.checkStatus, this.interval);
},
checkStatus : function() {
this.statusAttemptNumber += 1;
fetch(getStatusUrl(), {
method: "POST",
headers: {
"Content-Type": "text/plain"
}
})
.then(response => response.json())
.then(data => {
this.processesInfo = data.Processes
})
.catch(error => {
if(error.message === 'Failed to fetch') {
generateErrorMsg('503','Service Unavailable')
} else {
generateErrorMsg('', error.message)
}
})
}
},
beforeDestroy() {
clearInterval(this,polling)
},
created() {
this.pullingStatus()
}
})
var app = new Vue({
el: '#app',
data: {
serverInfo : null,
backupResponce : 'No data!',
memoryResponse : 'No data!',
statusAttemptNumber : 0,
}
})
cheers,
es

Related

Vuejs and vue-qrcode-reader add beep scan

Hello I use the library view-qrcode-reader for QR Code scan. I try to add a BEEP scan but I do not feel that the library does this kind of thing. So I did the thing manually but it does not work either.
<template>
<div class="container" id="app">
<router-link class="waves-effect waves-light btn" to="/livreur"><i class="material-icons">arrow_back</i>
</router-link>
<div class="row center">
<span v-if="errors" class="card-panel white-text red darken-1"><strong>{{ errors }}</strong></span>
</div>
<div class="row infos">
<span v-if="infos" class="card-panel white-text green green-1"><strong>Email & SMS envoyé à {{ infos.firstname }} {{ infos.lastname }}</strong></span>
</div>
<br/>
<div class="row">
<qrcode-stream #decode="onDecode"></qrcode-stream>
</div>
</div>
</template>
<script>
var attributes = {
setting: {
soundSrc: '/sounds/beep.mp3'
}
}
export default {
name: 'prepa',
data () {
return {
infos: '',
errors: '',
success: ''
}
},
methods: {
onDecode (decodedString) {
var audio = new Audio(attributes.setting.soundSrc)
audio.play()
this.$http.get('/orders/delivery/prepa/' + decodedString, {headers: {Authorization: `Bearer ${localStorage.token}`}})
.then(request => this.trackingInfos(request))
.catch((request) => this.trackingFail(request))
},
trackingInfos (req) {
if (req.data.error) {
return this.trackingFail(req)
}
this.errors = ''
this.infos = req.data.datas
this.save()
},
trackingFail (req) {
if (req.data.error) {
this.errors = req.data.error
}
},
save () {
this.$http.post('/order_histories', {
location: this.infos.city,
status: '/api/order_statuses/' + this.$preparation,
User: '/api/users/' + localStorage.userId,
orderId: '/api/orders/' + this.infos.orderId,
headers: {Authorization: `Bearer ${localStorage.token}`}
})
.then(request => this.successPrepa(request))
.catch(() => this.failPrepa())
},
successPrepa (req) {
if (req.data.error) {
return this.failPrepa(req)
}
this.errors = ''
this.success = req.status
},
failPrepa (req) {
if (req.data.error) {
this.errors = req.data.error
}
}
}
}
</script>
No beep and an error that appears in the console.
:8080/sounds/beep.mp3:1 GET http://127.0.0.1:8080/sounds/beep.mp3 net::ERR_ABORTED 404 (Not Found)
:8080/#/prepa:1 Uncaught (in promise) DOMException
Thanks for your help.

Vue 2 Emit selected data back to parent component

Struggling to sort out how to get a selected value from a Typeahead component to pass back to the parent component. I'm allowing the user to search from a variety of data to link a record to a post. Once the user clicks one of the typeahead drop-down records, I pass the item to the sendlink method - I've checked that the data passes ok. When I do the emit using the selected-link event, I'm not getting the data in the parent component.
PostList.vue
<template>
<div>
<div v-if='posts.length === 0' class="header">There are no posts yet!</div>
<form action="#" #submit.prevent="createPost()" class="publisher bt-1 border-fade bg-white" autocomplete="off">
<div class="input-group">
<input v-model="post.content" type="text" name="content" class="form-control publisher-input" placeholder="What's the lastest?" autofocus>
<span class="input-group-btn">
<button type="submit" class="btn btn-primary">Post</button>
</span>
</div>
<span class="publisher-btn file-group">
<i class="fa fa-camera file-browser"></i>
<input type="file">
</span>
</form>
<div #click="doit" v-on:selected-link="onSelectedLink">{{ modellink.name }}</div>
<typeahead
source="/api/typeahead"
placeholder="Link Post to Trip, Business, etc"
filter-key="title"
:start-at="3">
</typeahead>
<post v-for="post in posts"
:key="post.id"
:post="post"
#post-deleted="deletePost($event)">
</post>
</div>
</template>
<script>
var axios = require("axios");
import post from './PostItem.vue';
import typeahead from './Typeahead.vue';
export default {
components: {
post,
typeahead
},
props: ['postableId', 'postableType', 'model'],
data: function() {
return {
modellink: {
"name": "n/a",
"description": "",
"id": null,
"model": "n/a"
},
post: {
id: 1,
content: "",
edited: false,
created_at: new Date().toLocaleString(),
user: {
id: 1,
name: '',
}
},
posts: [
{
id: 1,
content: "",
edited: false,
created_at: new Date().toLocaleString(),
user: {
id: 1,
name: '',
}
}
]
};
},
created() {
this.fetchPostsList();
},
methods: {
onSelectedLink: function (talink) {
alert(JSON.stringify(talink, null, 4));
this.link = talink
},
doit() {
alert(JSON.stringify(this.modellink, null, 4));
},
fetchPostsList() {
if( this.postableId ) {
axios.get('/api/' + this.postableType + '/' + this.postableId + '/posts').then((res) => {
this.posts = res.data;
});
} else {
axios.get('/api/post').then((res) => {
//alert(JSON.stringify(res.data[0], null, 4));
this.posts = res.data;
});
}
},
createPost() {
axios.post('api/post', {content: this.post.content, user_id: Laravel.userId, vessel_id: Laravel.vesselId })
.then((res) => {
this.post.content = '';
// this.post.user_id = Laravel.userId;
// this.task.statuscolor = '#ff0000';
this.edit = false;
this.fetchPostsList();
})
.catch((err) => console.error(err));
},
deletePost(post) {
axios.delete('api/post/' + post.id)
.then((res) => {
this.fetchPostsList()
})
.catch((err) => console.error(err));
},
}
}
</script>
Typeahead.vue
<template>
<div>
<input
v-model="query"
#blur="reset"
type="text"
class="SearchInput"
:placeholder="placeholder">
<transition-group name="fade" tag="ul" class="Results">
<li v-for="item in items" :key="item.id">
<span #click="sendlink(item)">
<strong>{{ item.name }}</strong> - <small>{{ item.model }}</small><br>
<small>{{ item.description }}</small>
</span>
</li>
</transition-group>
<p v-show="isEmpty">Sorry, but we can't find any match for given term :( </p>
</div>
</template>
<script>
var axios = require("axios");
export default {
name: 'Typeahead',
props: {
modellink: {
type: Object,
required: false
},
source: {
type: [String, Array],
required: true
},
filterKey: {
type: String,
required: true
},
startAt: {
type: Number,
default: 3
},
placeholder: {
type: String,
default: ''
}
},
data() {
return {
items: [],
query: '',
taitem: ''
}
},
computed: {
lookup() {
if(this.query.length >= this.startAt) {
axios.get(this.source + '/' + this.query).then((res) => {
this.items = res.data;
return res.data;
});
}
},
isEmpty() {
if( typeof this.lookup === 'undefined' ) {
return false
} else {
return this.lookup.length < 1
}
}
},
methods: {
sendlink: function (taitem) {
this.$emit('selected-link', taitem);
},
reset() {
this.query = ''
}
}
}
</script>
In your PostList.vue, move the v-on:selected-link="onSelectedLink" from the div to typeahead like below. When emitting an event from child to parent, the listener on the parent needs to be on the child component tag for it to work.
<div #click="doit">{{ modellink.name }}</div>
<typeahead
source="/api/typeahead"
placeholder="Link Post to Trip, Business, etc"
filter-key="title"
:start-at="3"
v-on:selected-link="onSelectedLink">
</typeahead>

Vue2 Search in List received via Axios

since filtering is way more complex then in Vue 1, I have a question.
This is my Component, where a list of Sheeps is shown with the option to search/filter on Name or Family.
But I can't figure out how to achieve this.
<input type="search" v-model="search" placeholder="Search for Name OR Family" />
<ul>
<li v-for="sheep in sheeps"> <!-- Tried also: 'sheep in filteredSheeps' -->
{{ sheep.name }} ({{ sheep.type }}/{{ sheep.family }} )
</li>
</ul>
<script>
import axios from 'axios';
export default {
data() {
return {
sheeps: [],
search: '',
};
},
mounted() {
this.getSheeps();
}
methods: {
getSheeps() {
var self = this;
const url = '/api/sheeps';
axios.get(url).then(function(response) {
self.sheeps = response.data;
});
},
},
computed: {
filteredSheeps: function() {
var self = this;
return this.sheeps.filter(function(item) {
return item.family.toLowerCase().indexOf(self.search.toLowerCase()) > -1
})
}
}
}
}
</script>
I thought that it needed the computed method filteredSheeps in the v-for, but that's not it either. Getting an error directly then:
TypeError: null is not an object (evaluating 'item.family.toLowerCase')"
Here is a computed that will protect you from cases where the family and/or name is not populated.
filteredSheeps: function() {
let searchTerm = (this.search || "").toLowerCase()
return this.sheeps.filter(function(item) {
let family = (item.family || "").toLowerCase()
let name = (item.name || "").toLowerCase()
return family.indexOf(searchTerm) > -1 || name.indexOf(searchTerm) > -1
})
}
And a working example.
console.clear()
const sheeps = [
{name: "Lily", type: "Dorper", family: "Family 1"},
{name: "Joe", type: "Merino", family: "Family 2"},
{name: "Bob", type: "Dorper", family: null},
]
new Vue({
el: "#app",
data:{
sheeps:[],
search: null
},
computed: {
filteredSheeps: function() {
let searchTerm = (this.search || "").toLowerCase()
return this.sheeps.filter(function(item) {
let family = (item.family || "").toLowerCase()
let name = (item.name || "").toLowerCase()
return family.indexOf(searchTerm) > -1 || name.indexOf(searchTerm) > -1
})
}
},
created(){
setTimeout(() => this.sheeps = sheeps, 500)
}
})
<script src="https://unpkg.com/vue#2.4.2"></script>
<div id="app">
<input type="search" v-model="search" placeholder="Search for Name OR Family" />
<ul>
<li v-for="sheep in filteredSheeps">
{{ sheep.name }} ({{ sheep.type }}/{{ sheep.family }} )
</li>
</ul>
</div>

Axios response happening after component is rendered

I have a parent component making an Ajax request using Axios, The response is then assigned to a variabled called 'carousel' and is then passed down to the child component.
In the child component on 'created()' I am assigning the passed prop 'carousel' to a new variable called 'slides'
Problem is when I do this is returns undefined and my thinking is the Axios query hasn't returned before this happens.
Is there a way to delay the axios request before the prop is passed and the child component always gets the expected response.
My code is below.
Parent
<template>
<div class='product-container'>
<home-carousel :carousel="carousel"></home-carousel>
<profiler></profiler>
<cta-sections :panels="panels"></cta-sections>
</div>
</template>
<script>
import api from '../api/Home'
import CtaSections from '../components/CtaSections'
import HomeCarousel from '../components/HomeCarousel'
import Profiler from '../components/Profiler'
export default {
components: {
CtaSections,
HomeCarousel,
Profiler,
},
data() {
return {
panels: [],
slides: 'test',
carouselPass: [],
carousel: [],
}
},
created() {
axios.get(window.SETTINGS.API_BASE_PATH + 'pages/5')
.then(response => {
this.panels = response.data.acf.split_panels;
this.carousel = response.data.acf.carousel;
this.carousel.forEach(function (item, index) {
if (index === 0) {
item.active = true;
item.opacity = 1;
} else {
item.active = false;
item.opacity = 0;
}
item.id = index
})
})
},
}
</script>
Child
<template>
<div class='slider'>
<transition-group class='carouse carousel--fullHeight carousel--gradient' tag="div" name="fade">
<div v-for="slide in slides"
class="carousel__slide"
v-bind:class="{ active: slide.active }"
:key="slide.id"
:style="{ 'background-image': 'url(' + slide.image.url + ')' }"
v-show="slide.active"
>
<div class="carousel__caption carousel__caption--centered">
<h2 class="heading heading--white heading--uppercase heading--fixed">{{ slide.tagline }}</h2>
</div>
</div>
</transition-group>
<div class='carousel__controls carousel__controls--numbered carousel__controls--white carousel__controls--bottomRight carousel__controls--flex'>
<div #click="next" class="in">
<img src="/static/img/svg/next-arrow.svg" />
<span v-if="carousel.length < 10">0</span>
<span>{{ slideCount }}</span>
<span>/</span>
<span v-if="carousel.length < 10">0</span>
<span>{{ carousel.length }}</span>
</div>
</div>
</div>
</template>
<script>
import bus from '../bus'
import Booking from './Booking'
export default {
name: 'HomeCarousel',
props: ['carousel'],
data() {
return {
slideCount: 1,
slides: [],
/*
slides: [{
image: this.themepath + 'home-banner.jpg',
active: true,
captionText: 'A PLACE AS UNIQUE AS YOU ARE',
buttonText: 'book now',
buttonUrl: '#',
opacity: 1,
id: 1
},
{
image: this.themepath + 'home-banner2.jpg',
active: false,
captionText: 'A PLACE AS UNIQUE AS YOU ARE',
buttonText: 'book now',
buttonUrl: '#',
opacity: 0,
id: 2
}
]
*/
}
},
methods: {
showBooking: function() {
this.$store.state.showBooking = true;
},
next() {
const first = this.slides.shift();
this.slides = this.slides.concat(first)
first.active = false;
this.slides[0].active = true;
if (this.slideCount === this.slides.length) {
this.slideCount = 1;
} else {
this.slideCount++;
}
},
previous() {
const last = this.slides.pop()
this.slides = [last].concat(this.slides)
// Loop through Array and set all active values to false;
var slideLength = this.slides.length;
for (var slide = 0; slide < slideLength; slide++) {
this.slides[slide].active = false;
}
// Apply active class to first slide
this.slides[0].active = true;
this.slideCount--;
},
loopInterval() {
let self = this;
setInterval(function () {
self.next()
}, 8000);
}
},
created() {
this.slides = this.carousel;
}
}
</script>
You can just watch the prop and set this.slides when it changes, i.e. when the async call has finished:
watch:{
carousel(value) {
this.slides = value
}
}
Here's a JSFiddle: https://jsfiddle.net/nwLh0d4w/

LocalStorage in Vue App with multiple inputs

i dont know if this is possible - but i am working on a Vue app with multiple input fields that posts to the same list - and i need this to be stored somehow, so when you refresh the site, the outputs from the input fields are saved.
This means both the taskList and subTaskList array should be saved ( i know i've only worked on taskList ).
The example i posted here saves the data fine, however if you refresh, it will post all the data in all the components, can this be fixed so it will only be in the right components?
const STORAGE_KEY = 'madplan-storage'
Vue.component('list-component', {
data: function() {
return {
newTask: "",
taskList: [],
newSubTask: "",
subTaskList: [],
};
},
created() {
this.taskList = JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]');
},
template:
'<div>' +
'<section class="prefetch">' +
'<input v-if="showInput" class="input typeahead" type="text" placeholder="Tilføj ret til madplanen" v-model="newTask" v-on:keyup.enter="addTask">' +
'</section>' +
'<details open v-for="task in taskList" v-bind:key="task.text" class="sub-list-item">' +
'<summary>{{ task.text }}<i class="fa fa-times" aria-hidden="true" v-on:click="removeTask(task)"></i>' + '</summary>' +
'<input class="subInput" type="text" placeholder="Tilføj til indøbsseddel" v-model="newSubTask" v-on:keyup.enter="addSubTask">' +
'</details>' +
'</div>',
computed: {
showInput: function() {
return !this.taskList.length
},
},
methods: {
//addTasks
//
addTask: function() {
var task = this.newTask.trim();
if (task) {
this.taskList.push({
text: task
});
this.newTask = "";
localStorage.setItem(STORAGE_KEY, JSON.stringify(this.taskList));
}
},
addSubTask: function() {
var task = this.newSubTask.trim();
if (task) {
this.subTaskList.push({
text: task
});
this.newSubTask = "";
this.$emit('addedtask', task);
localStorage.setItem(STORAGE_KEY, JSON.stringify(this.subTaskList));
}
},
//removeTasks
//
removeTask: function(task) {
var index = this.taskList.indexOf(task);
this.taskList.splice(index, 1);
},
},
});
new Vue({
el: "#madplan",
data: {
newTask: "",
taskList: [],
newSubTask: "",
subTaskList: [],
},
methods: {
acknowledgeAddedTask: function(cls, task) {
this.$data.subTaskList.push({
text: task,
class: "list-item " + cls
})
},
acknowledgeRemovedTask: function(task) {
this.$data.subTaskList = this.$data.subTaskList.filter(it => it.text != task.text)
},
removeSubTask: function(task) {
var index = this.subTaskList.indexOf(task);
this.subTaskList.splice(index, 1);
},
}
});
<section id="madplan" class="section-wrapper">
<section class="check-list">
<div id="mandag" class="dayWrapper">
<h1>Day One</h1>
<list-component
class="mandag"
v-on:addedtask='task => acknowledgeAddedTask("mandag", task)'
></list-component>
</div>
<div id="tirsdag" class="dayWrapper">
<h1>Day Two</h1>
<list-component
class="tirsdag"
v-on:addedtask='task => acknowledgeAddedTask("tirsdag", task)'
></list-component>
</div>
<ul id="indkobsseddel">
<h2>Shopping List</h2>
<li v-for="task in subTaskList" v-bind:key="task.text" :class="task.class">{{ task.text }}<i class="fa fa-times" aria-hidden="true" v-on:click="removeSubTask(task)"></i></li>
</ul>
</section>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://unpkg.com/vue/dist/vue.js" charset="utf-8"></script>
To be clear, i will come with an example:
As it is now, if i post "Foo" and "Bar" to the "Day One" component and refresh the page, it will then post "Foo" and "Bar" to both "Day One" and "Day Two".
Essentially, i would like to be able to post for an example "Foo" to "Day One", "Bar" to "Day Two" and from there post "Hello World" to the Shopping List, and it would all be saved in the right places, instead of posting everything everywhere.
BTW: I'm a scrub at backend work.
To persist global state, you may use the plugin vue-persistent-state like this:
import persistentStorage from 'vue-persistent-storage';
const initialState = {
newTask: "",
taskList: [],
newSubTask: "",
subTaskList: [],
};
Vue.use(persistentStorage, initialState);
Now newTask, taskList, newSubTask and subTaskList is available as data in all components and Vue instances. Any changes will be stored in localStorage, and you can use this.taskList etc. as you would in a vanilla Vue app.
Your list component now becomes:
Vue.component('list-component', {
// data removed
// created removed
template:
'<div>' +
'<section class="prefetch">' +
'<input v-if="showInput" class="input typeahead" type="text" placeholder="Tilføj ret til madplanen" v-model="newTask" v-on:keyup.enter="addTask">' +
'</section>' +
'<details open v-for="task in taskList" v-bind:key="task.text" class="sub-list-item">' +
'<summary>{{ task.text }}<i class="fa fa-times" aria-hidden="true" v-on:click="removeTask(task)"></i>' + '</summary>' +
'<input class="subInput" type="text" placeholder="Tilføj til indøbsseddel" v-model="newSubTask" v-on:keyup.enter="addSubTask">' +
'</details>' +
'</div>',
computed: {
showInput: function() {
return !this.taskList.length
},
},
methods: {
//addTasks
//
addTask: function() {
var task = this.newTask.trim();
if (task) {
this.taskList.push({
text: task
});
this.newTask = "";
// localStorage.setItem not needed
}
},
addSubTask: function() {
var task = this.newSubTask.trim();
if (task) {
this.subTaskList.push({
text: task
});
this.newSubTask = "";
// $emit not needed, state is global and shared
// localStorage.setItem not needed
}
},
//removeTasks
//
removeTask: function(task) {
var index = this.taskList.indexOf(task);
this.taskList.splice(index, 1);
},
},
});
If you want to understand how this works, the code is pretty simple. It basically
adds a mixin to make initialState available in all Vue instances, and
watches for changes and stores them.
Disclaimer: I'm the author of vue-persistent-state.