Vue.js - v-model에서 매개 변수를 전달하여 중첩된 속성 변경
v-for와 함께 어레이 '제품'을 표시했다.각 제품에는 '주문' 객체에 제품을 추가하는 버튼이 있다.개체 '순서'가
order: {
products: [{
quantity: 0,
otherProperties
}]
}
그 버튼을 두 번째로 클릭했을 때 1로 수량을 늘리고 싶다.
클릭한 개체를 전달하는 Vuex에서는
increaseQuantity(state, product){
state.order.products.find((orderProduct)=>{
return product.id === orderProduct.id
}).quantity++;
지금까지는 좋다.크롬 개발 도구에서 수량 증가를 볼 수 있다.
까다로운 건, 어떻게 해야 할지 전혀 모르겠네, 쉽긴 하지만.버튼 옆에 있는 입력란에 각 제품의 수량을 보여주고 싶다.문제는 다음과 같은 v-model에서 선택한 제품이 필요하다는 것이다.
<div v-for="product in products" :key="product.id">
<input v-model="order.products.find((orderProduct)=>{
return product.id === orderProduct.id
}).quantity" />
</div>
제품을 '주문' 객체에 추가하는 순간 0의 수량 값이 입력 필드에 표시되므로 DOM이 업데이트된다.그러나 수량이 바뀌어도 DOM에서는 아무것도 변하지 않는다.하지만 vuex 매장에서 수량이 바뀌었다.
이걸 해결할 방법이 있을까?v-model이 아닌 :value로 시도해봤지만 같은 문제였습니다.
이러한 변화를 사후 대응적으로 만드는 데 사용해야 한다.
increaseQuantity(state, product){
let index= state.order.products.findIndex((orderProduct)=>{
return product.id === orderProduct.id
})
state.order.products.quantity++;
this.$set(state.order.products,index,state.order.products[index])
}
당신은 가게를 비반복적으로 변이시킨 것 같다. 즉, Vue가 당신의 변경 사항을 추적하지 않기 때문에 DOM은 업데이트되지 않는다.
나는 다음 조각으로 너의 코드를 조금 다시 작성했다.
const store = new Vuex.Store({
state: {
products: [
{
id: 1,
quantity: 0
},
{
id: 2,
quantity: 0
}
]
},
mutations: {
ADD_PRODUCT(state, { id: productId, amount }) {
const product = state.products.find(({ id }) => id === productId)
if (product) {
if (!product.hasOwnProperty('order')) {
// this is the way to set data in a reactive-way
Vue.set(product, 'order', true)
} else {
product.quantity = Number(amount)
}
}
}
},
actions: {
addProduct({ commit }, data) {
commit('ADD_PRODUCT', data)
}
},
getters: {
getProducts: ({ products }) => products,
getOrdered: ({ products }) => {
return products.filter(product => {
return product.hasOwnProperty('order') ? product : false
})
}
}
})
Vue.component('Product', {
props: ['product'],
computed: {
buttonText() {
if (!this.product.order) {
return 'ADD TO ORDER'
} else {
return 'SET ORDERED QUANTITY'
}
}
},
data() {
return {
amount: 0
}
},
template: `
<div>Product: {{ product.id }}, {{ product.quantity }}
<button @click="addToOrder(product.id, amount)">{{ buttonText }}</button>
<input
v-if="product.order"
type="number"
v-model="amount"
min="0"
@input="addToOrder(product.id, amount)"
>
</div>`,
methods: {
addToOrder(id, amount) {
this.$store.dispatch('addProduct', { id, amount })
}
}
})
Vue.component('Ordered', {
props: ['product'],
template: `
<div>
Product {{ product.id }} quantity: {{ product.quantity }}
</div>
`
})
new Vue({
el: '#app',
store,
computed: {
products() {
return this.$store.getters.getProducts
},
ordered() {
return this.$store.getters.getOrdered
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://unpkg.com/vuex@3.5.1/dist/vuex.js"></script>
<div id="app">
<div>
<h3>PRODUCT LIST</h3>
<product
v-for="product in products"
:key="product.id"
:product="product"
/>
</div>
<hr />
<h3>ORDERED LIST</h3>
<ordered
v-for="product in ordered"
:key="`ordered-${ product.id }`"
:product="product"
/>
</div>
제품만 바꿔준다는 생각이다.order
전체 순서가 무엇인지 추적하기 위한 속성나는 또한 a를 만들었다.getter
주문된 제품을 걸러내는 것(그래서 어느 시점에 필요한 제품만 있다면, 나는 그것을 그냥 그렇게 부른다.getter
).
이것은 간단한 방법이다.
- 입력 필드만으로 주문 금액을 설정할 수 있다.
- 모든 제품에 대한 배열이 하나뿐입니다.
- 제품이 자신의 상태를 추적한다(속성 및 금액).
부에 반응성에 대한 자세한 내용은 https://vuejs.org/v2/guide/reactivity.html를 참조하십시오.
'IT이야기' 카테고리의 다른 글
Java 바이트 배열에서 문자열로 바이트 배열 (0) | 2022.05.15 |
---|---|
@Before, @BeforeClass, @BeforeAll과 @BeforeAll 사이의 차이 (0) | 2022.05.15 |
Vue Watch가 트리거하지 않음 (0) | 2022.05.15 |
어레이 항목을 이동할 때 v-for와 함께 렌더링되는 구성 요소 내부에 포함된 Youtube 비디오 다시 로드 (0) | 2022.05.15 |
다양한 매크로에서 논쟁을 반복하는 것이 가능한가? (0) | 2022.05.15 |