简体   繁体   English

VueJS 从根 Vue 实例中的组件访问数据

[英]VueJS accessing data from component in root Vue instance

I'm trying to access a component's data in my root Vue instance.我正在尝试访问我的根 Vue 实例中的组件数据。 What I'm trying to accomplish is, you click on a button and a set of inputs appear.我想要完成的是,您单击一个按钮并出现一组输入。 Each set of inputs is its own object in localStorage with the keys id, bags, and amount.每组输入都是 localStorage 中自己的对象,具有键 id、bags 和 amount。 When I update a set of inputs, their values should update in localStorage.当我更新一组输入时,它们的值应该在 localStorage 中更新。 I'm having trouble figuring out how to access my component's data for bags and amount.我无法弄清楚如何访问我的组件的袋子和数量数据。 What I think I'm supposed to be using is props because that's what I used in React.我认为我应该使用的是道具,因为那是我在 React 中使用的。 However, I'm not too comfortable with using them yet in Vue.但是,我还不太习惯在 Vue 中使用它们。

Here is what I have so far:这是我到目前为止所拥有的:

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));
  }
};

Component零件

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;
    }
  }
});

Root Vue Instance根 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 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>

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

Typically, you do not want to reach into a component to get its data.通常,您不想进入组件来获取其数据。 You want the component to $emit it.您希望组件$emit它。 Vue is, generally, props down, events up . Vue 通常是props down , events up

I've modified your order component to support v-model .我已经修改了您的订单组件以支持v-model This allows the changes to the component to be reflected in the parent automatically.这允许对组件的更改自动反映在父级中。

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
      });
    }
  }
});

Doing this, you don't have to pass bags and amount , you just pass the order.这样做,您不必传递bagsamount ,您只需传递订单。 Then, when the order changes, the modified order is emitted.然后,当订单发生变化时,会发出修改后的订单。

A working example is here .一个工作示例是here

Additionally, I added the value property to your order objects.此外,我将value属性添加到您的order对象中。 If you don't save that, then you can't properly calculate the changes to bags and volume.如果不保存,则无法正确计算袋子和体积的变化。

If props are confusing you, be sure to read about Composing Components , which talks about the "props down, events up" convention.如果 props 让您感到困惑,请务必阅读Composing Components ,其中讨论了“props down, events up”的约定。

Props are data that is controlled from outside the component.道具是从组件外部控制的数据。 The component should not make modifications to its props (as you are doing in your watch , and as you are implicitly doing by using them with v-model ).组件不应修改其 props(就像您在watch中所做的那样,以及通过将它们与v-model一起使用而隐含地做的那样)。

You probably want to make component data items that you initialize from the props (give them names differerent from the props names!) You can then manipulate those values.您可能希望创建从道具初始化的组件data项(给它们命名与道具名称不同!)然后您可以操作这些值。

Since you want the parent to be aware of changes to the values, you should emit events when changes happen.由于您希望父级知道值的更改,因此您应该在发生更改时发出事件 The parent can catch those events and take appropriate action, like saving them to the order object and to localStorage.父级可以捕获这些事件并采取适当的措施,例如将它们保存到订单对象和 localStorage。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM