LocalStorage in Vue App with multiple inputs

放肆的年华 提交于 2019-12-25 09:29:20

问题


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.


回答1:


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

  1. adds a mixin to make initialState available in all Vue instances, and
  2. watches for changes and stores them.

Disclaimer: I'm the author of vue-persistent-state.



来源:https://stackoverflow.com/questions/46587976/localstorage-in-vue-app-with-multiple-inputs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!