2017-04-19 28 views
1

我试图访问我的根Vue实例中的组件数据。我试图完成的是,你点击一个按钮并出现一组输入。每个输入集都是localStorage中自己的对象,具有密钥id,行李和金额。当我更新一组输入时,它们的值应该在localStorage中更新。我无法弄清楚如何访问我的组件的数据袋和金额。我认为我应该使用的是道具,因为这是我在React中使用的。但是,我不太愿意在Vue中使用它们。VueJS从组件Vue实例中访问数据

这是我到目前为止有:

var STORAGE_KEY = "orders"; 

var orderStorage = { 
    fetch: function() { 
    var orders = JSON.parse(localStorage.getItem(STORAGE_KEY) || "[]"); 
    orders.forEach(function(order, index) { 
     order.id = index; 
    }); 
    orderStorage.uid = orders.length; 
    return orders; 
    }, 
    save: function(orders) { 
    localStorage.setItem(STORAGE_KEY, JSON.stringify(orders)); 
    } 
}; 

组件

Vue.component('order', { 
    template: ` 
    <div> 
     <select v-model="selected"> 
     <option v-for="option in options" v-bind:value="option.value"> 
      {{ option.text }} 
     </option> 
     </select> 
     <input class="input" id="bags" v-model="bags" type="number" placeholder="Bags"> 
     <input class="input" id="amount" v-model="amount" type="number" placeholder="Amount"> 
     <button @click="$emit('remove')">Remove</button> 
    </div> 
    `, 
    props: { 
    bags: this.bags, // I must be doing this wrong 
    amount: this.amount 
    }, 
    data() { 
    return { 
     bags: null, 
     amount: null, 
     selected: null, 
     options: [{ 
     text: "Product (25kg)", 
     value: 25 
     }, { 
     text: "Product (50kg)", 
     value: 50 
     }, { 
     text: "Product (75kg)", 
     value: 75 
     }] 
    } 
    }, 
    watch: { 
    bags(newValue) { 
     this.amount = newValue * this.selected; 
    }, 
    amount(newValue) { 
     this.bags = newValue/this.selected; 
    } 
    } 
}); 

根Vue的实例

new Vue({ 
    el: '#app', 
    data: { 
    orders: orderStorage.fetch(), 
    bags: null, 
    amount: null, 
    }, 
    watch: { 
    orders: { 
     handler: function(orders) { 
     orderStorage.save(orders); 
     }, 
     deep: true 
    } 
    }, 
    methods: { 
    addProduct: function() { 
     this.orders.push({ 
     id: orderStorage.uid++, 
     bags: this.bags, // component.bags ? 
     amount: this.amount// component.amount? 
     }); 
     console.log(localStorage); 
    } 
    } 
}); 

HTML

<div id="app"> 
    <button @click="addProduct">Add</button> 

    <div class="orders"> 
    <order v-for="(order, index) in orders" :id="index" :key="order" @remove="orders.splice(index, 1)" :bags="bags" :amount="amount"></order> 
    </div> 
</div> 

例如:https://codepen.io/anon/pen/YVwxpz?editors=1010

回答

1

通常情况下,您不希望触及组件以获取其数据。你想要组件$emit它。 Vue通常是props down, events up

我修改了您的订单组件以支持v-model。这允许组件的更改自动反映到父项中。

Vue.component('order', { 
    props:["value"], 
    template: ` 
    <div> 
     <select v-model="order.value"> 
     <option v-for="option in options" v-bind:value="option.value"> 
      {{ option.text }} 
     </option> 
     </select> 
     <input class="input" id="bags" v-model="order.bags" type="number" @input="onBags" placeholder="Bags"> 
     <input class="input" id="amount" v-model="order.volume" type="number" @input="onVolume" placeholder="Amount"> 
     <button @click="$emit('remove')">Remove</button> 
    </div> 
    `, 
    data() { 
    return { 
     options: [{ 
     text: "Product (25kg)", 
     value: 25 
     }, { 
     text: "Product (50kg)", 
     value: 50 
     }, { 
     text: "Product (75kg)", 
     value: 75 
     }], 
     order: this.value 
    } 
    }, 
    methods: { 
    onBags() { 
     this.order.volume = this.order.bags * this.order.value; 
     this.$emit("input", this.order) 
    }, 
    onVolume() { 
     this.order.bags = this.order.volume/this.order.value; 
     this.$emit("input", this.order) 
    } 
    } 
}) 

new Vue({ 
    el: '#app', 
    data: { 
    orders: orderStorage.fetch(), 
    }, 
    watch: { 
    orders: { 
     handler: orders => orderStorage.save(orders), 
     deep: true 
    } 
    }, 
    methods: { 
    addProduct: function(order) { 
     this.orders.push({ 
     id: orderStorage.uid++, 
     bags: 0, 
     volume: 0, 
     value: 25 
     }); 
    } 
    } 
}); 

这样做,你不必通过bagsamount,你只是传递的顺序。然后,当订单改变时,修改后的订单就会发出。

一个工作示例是here

此外,我将value属性添加到您的order对象。如果你没有保存,那么你无法正确计算行李和音量的变化。

1

如果道具让您感到困惑,请务必阅读关于Composing Components的文章,其中讨论了“支持道具,举办活动”的约定。

道具是从组件外部控制的数据。组件不应修改其道具(正如您在watch中所做的那样,因为您通过与v-model一起使用它们而隐式地进行操作)。

你可能想使组件data项目,你从道具初始化(给他们的道具名称differerent名!),那么你可以操纵这些值。

由于您希望父母知道对这些值所做的更改,因此发生更改时应该使用emit events。父母可以捕获这些事件并采取适当的措施,例如将其保存到订单对象和localStorage中。