vue que cli javascript module store vuex on-the-fly

javascript - que - vue.js download



Separando almacenes vuex para componentes creados dinĂ¡micamente (2)

Hola y gracias por publicar tu pregunta y tu solución.

Comencé a aprender Vuex hace un par de días y encontré un problema similar. He comprobado su solución y encontré la mía que no requiere el registro de nuevos módulos. Me parece que es una exageración y, para ser honesto, no entiendo por qué lo haces. Siempre hay una posibilidad de que haya entendido mal el problema.

He creado una copia de su marca con algunas diferencias por motivos de claridad y demostración.

Tengo:

  1. JobList.vue - componente principal personalizado
  2. Job.vue - componente personalizado hijo de lista de trabajos
  3. jobs.js - archivo de módulo de tienda vuex

JobList.vue (que es responsable de envolver los elementos de la lista de trabajos)

<template> <div> <job v-for="(job, index) in jobs" :data="job" :key="job.id"></job> <h3>Create New Job</h3> <form @submit.prevent="addJob"> <input type="text" v-model="newJobName" required> <button type="submit">Add Job</button> </form> </div> </template> <script> import store from ''../store/index'' import job from ''./job''; export default { components: { job }, data() { return { newJobName: '''' }; }, computed: { jobs() { return store.state.jobs.jobs; } }, methods: { addJob() { store.dispatch(''newJob'', this.newJobName); } } } </script>

El trabajo

<template> <div> <h5>Id: {{ data.id }}</h5> <h4>{{ data.name }}</h4> <p>{{ data.active}}</p> <button type="button" @click="toggleJobState">Toggle</button> <hr> </div> </template> <script> import store from ''../store/index'' export default { props: [''data''], methods: { toggleJobState() { store.dispatch(''toggleJobState'', this.data.id); } } } </script>

Y finalmente el archivo del módulo jobs.js Vuex:

export default { state: { jobs: [ { id: 1, name: ''light'', active: false }, { id: 2, name: ''medium'', active: false }, { id: 3, name: ''heavy'', active: false } ] }, actions: { //methods newJob(context, jobName) { context.state.jobs.push({ id: context.getters.newJobId, name: jobName, active: false }); }, toggleJobState(context, id) { context.state.jobs.forEach((job) => { if(job.id === id) { job.active = !job.active; } }) } }, getters: { //computed properties newJobId(state) { return state.jobs.length + 1; } } }

Es posible agregar nuevos trabajos a la tienda y, como sugiere la propiedad "activa", puede controlar cada trabajo individual sin la necesidad de un nuevo módulo vuex personalizado.

Esta fue la pregunta que me atascó un poco. Desafortunadamente, no pude encontrar una respuesta aquí ( preguntar tampoco ayudó ). Entonces, después de investigar y preguntar aquí y allá, parece que obtuve la solución a este problema.

Si tiene una pregunta para la que ya sabe la respuesta y desea documentar ese conocimiento en público para que otros (incluyéndolo a usted) puedan encontrarlo más adelante.

Por supuesto, mi respuesta puede no ser la ideal, además sé que no lo es, ese es el punto clave por el que estoy publicando, para mejorarlo.

Tenga en cuenta, no estoy usando acciones en el ejemplo. La idea es la misma.

Vamos a comenzar con la indicación del problema:

Imagina que tenemos App.vue que genera dinámicamente su componente local llamado Hello .

<template> <div id="app"> <div> <hello v-for="i in jobs" :key="i" :id="i"></hello> <button @click="addJob">New</button> </div> </div> </template> <script> import Hello from ''./components/Hello'' export default { components: { Hello }...

store.js

export const store = new Vuex.Store({ state: { jobs: [] } })

Estamos utilizando la directiva v-for para generar componentes mediante la iteración a través de una matriz de jobs . Nuestra store partir de ahora consiste solo en un state con una matriz vacía. Botón New debería hacer 2 cosas:

1) crear un nuevo componente Hello , en otras palabras, agregar un elemento a los jobs (que sean números), que se asignarán como key e id de <hello> y se pasarán al componente local como props .

2) generar almacenes locales - módulos - para mantener los datos en el ámbito de los componentes recién creados.

Hello.vue

<template> <div> <input type="number" :value="count"> <button @click="updateCountPlus">+1</button> </div> </template> export default { props: [''id''] }

Componente simple: entrada con un botón que agrega 1.

Nuestro objetivo es diseñar algo como esto:


Para la primera operación del botón NEW ( componentes generadores ), agregamos la mutation a nuestro store.js

mutations: { addJob (state) { state.jobs.push(state.jobs.length + 1) ... }

En segundo lugar, la creación de módulos locales . Aquí vamos a utilizar reusableModule para generar múltiples instancias de un módulo. Ese módulo lo guardamos en archivo separado por conveniencia. Además, tenga en cuenta el uso de la función para declarar el estado del módulo .

const state = () => { return { count: 0 } } const getters = { count: (state) => state.count } const mutations = { updateCountPlus (state) { state.count++ } } export default { state, getters, mutations }

Para usar reusableModule lo importamos y aplicamos el registro dinámico de módulos.

store.js

import module from ''./reusableModule'' const {state: stateModule, getters, mutations} = module export const store = new Vuex.Store({ state: { jobs: [] }, mutations: { addJob (state) { state.jobs.push(state.jobs.length + 1) store.registerModule(`module${state.jobs.length}`, { state: stateModule, getters, mutations, namespaced: true // making our module reusable }) } } })

Después, vamos a vincular Hello.vue con su almacenamiento. Es posible que necesitemos state , getters , mutations , actions de vuex . Para acceder al almacenamiento necesitamos crear nuestros getters . Lo mismo con las mutations .

Home.vue

<script> export default { props: [''id''], computed: { count () { return this.$store.getters[`module${this.id}/count`] } }, methods: { updateCountPlus () { this.$store.commit(`module${this.id}/updateCountPlus`) } } } </script>

Imagina que tenemos muchos getters , mutations y actions . ¿Por qué no usar {mapGetters} o {mapMutations} ? Cuando tenemos varios módulos y conocemos la ruta necesaria para el módulo, podemos hacerlo. Desafortunadamente, no tenemos acceso al nombre del módulo.

El código se ejecuta cuando se ejecuta el módulo del componente (cuando se inicia su aplicación), no cuando se crea el componente. Por lo tanto, estos ayudantes solo pueden usarse si conoce el nombre del módulo con anticipación.

Hay poca ayuda aquí. Podemos separar a nuestros getters y mutations y luego importarlos como un objeto y mantenerlo limpio.

<script> import computed from ''../store/moduleGetters'' import methods from ''../store/moduleMutations'' export default { props: [''id''], computed, methods } </script>

Volviendo al componente de la App . Tenemos que cometer nuestra mutation y también vamos a crear un getter para la App . Para mostrar cómo podemos acceder a los datos ubicados en módulos.

store.js

export const store = new Vuex.Store({ state: { jobs: [] }, getters: { jobs: state => state.jobs, sumAll (state, getters) { let s = 0 for (let i = 1; i <= state.jobs.length; i++) { s += getters[`module${i}/count`] } return s } } ...

Código de acabado en el componente de la App

<script> import Hello from ''./components/Hello'' import {mapMutations, mapGetters} from ''vuex'' export default { components: { Hello }, computed: { ...mapGetters([ ''jobs'', ''sumAll'' ]) }, methods: { ...mapMutations([ ''addJob'' ]) } } </script>