Estoy usando Nuxt 2.15.3 .
En mi aplicación, los usuarios pueden configurar preguntas que sus clientes pueden responder, y las preguntas pueden ser de una variedad de tipos, una de ellas es una pregunta de opción múltiple. Este tipo de preguntas tienen un título, así como múltiples opciones de respuesta entre las que las personas pueden elegir.
En mi página de Preguntas, enumero todas las preguntas del usuario y quiero permitirles editar cualquier pregunta, pero tengo algunos problemas para averiguar cómo hacerlo exactamente, al menos cuando se trata de editar preguntas de opción múltiple. Tal como está actualmente, tengo un componente EditQuestion al que paso un accesorio de question de mi componente QuestionCard , el accesorio son solo los detalles de la pregunta que se almacena en Vuex.
Mi versión actual (simplificada para SO) del componente EditQuestion :
<template> <input v-model="questionTitle" type="text"> <div v-if="question.type === 'multiple_choice'"> <input v-for="option in questionOptions" v-model="option.content" type="text"> </div> <button @click.prevent="updateQuestion"></button> </template> <script> export default { props: { question: {} }, data() { return { questionTitle: this.question.title, questionOptions: this.question.options } }, methods: { updateQuestion() { // Call the API with the new question details } } } </script> Si solo estuviera editando títulos de preguntas, esto funciona muy bien. Sin embargo, mi problema proviene de las opciones. Si trato de actualizar uno, Vuex me advierte sobre la mutación del estado de la tienda fuera de una mutación, y me advierte de todos modos incluso si clono question.options , por ejemplo, haciendo questionOptions: Object.assign({}, this.question.options) o questionOptions: {...this.question.options}. La parte que me confunde es por qué Vuex no se queja cuando modifico el objeto de datos questionTitle , y solo cuando edito questionOptions.
Como referencia, si es relevante, question.title es solo una cadena simple, mientras que question.options es un objeto que se parece a esto:
{ "0": { "id": 0, "content": "Option 1" }, "1": { "id": 1, "content": "Option 2" } }¿Cuál es la mejor manera para mí de permitir que las personas editen las opciones de preguntas de opción múltiple?
En JavaScript, las primitivas ( String , Number , BigInt , Boolean , undefined y null ) se copian por valor , mientras que los objetos (incluidos Array , Map , WeakMap , Set , WeakSet ) se copian por referencia .
this.question.title es una String , por lo que se copia por valor en la nueva variable. Por otro lado, this.question.options es un objeto (parece un Array ), por lo que se copia por referencia en questionOptions y, por lo tanto, questionOptions y this.question.options se refieren al mismo objeto en Vuex.
Su idea de clonar el this.question.options entrante está en el camino correcto hacia una solución, pero Object.assign() y el operador de propagación solo crean copias superficiales que todavía se refieren al mismo objeto original, lo que explica la mutación de estado de Vuex advertencias cuando su componente intentó modificar la copia superficial.
Hay varias formas de copiar en profundidad un objeto , una de las cuales se proporciona en la otra respuesta aquí :
export default { data() { return { questionTitle: this.question.title, questionOptions: JSON.parse(JSON.stringify(this.question.options)) } } }Intente hacer una copia local del objeto de la question y realice todas las actualizaciones solo en esa copia local, algo como esto:
<script> export default { props: { question: {} }, data() { return { localCopyOfQuestion: JSON.parse(JSON.stringify(this.question)), questionTitle: this.localCopyOfQuestion.title, questionOptions: this.localCopyOfquestion.options } }, methods: { updateQuestion() { // Call the API with the new question details } } } </script>