Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
293 views
in Technique[技术] by (71.8m points)

javascript - Writing to object from parent component in VueJS

I'd like to have a list which maps the modified values back to the description in the container. In other way, I want the container to have a prop shortcuts like:

[{action: "foo"}]

with text being editable in the component created from the list.

I've got the container:

    Vue.component("shortcuts", {
      data: function () {
        return {
          shortcuts: []
        }
      },
      methods: {
        add: function() {
          this.shortcuts.push({
            action: "",
          })
        },
      },
      template: '<div>
        <shortcut-entry v-for="(shortcut, index) in shortcuts" is="shortcut-entry" v-bind:key="index" v-bind="shortcut" @remove="shortcuts.splice(index, 1)"></shortcut-entry>
        <br>
        <button v-on:click=add>Add</button>
        </div>'
    })

And the list element:

    Vue.component("shortcut-entry", {
      methods: {
        clearParams: function() {
          this.params = {}
        },
        remove: function() {
          this.$emit("remove")
        }
      },
      props: {
        action: String,
      },
      template: '<div>
        <input type="text" v-model="action"></input>
        <button v-on:click="remove">Remove</button>
        </div>'
    })

However this results in a warning:

Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders.

But if I use data instead of props in the shortcut-entry, the changes do not propagate into the objects in the list either.

What am I missing here? How can I bind the text entry in the item back to the object in the list in the container?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Use v-model to update the state:

Vue.component('shortcuts', {
  props: {
    value: Array // Of shortcuts
  },
  methods: {
    add: function () {
      const newValue = [...this.value, { action: '' }]
      this.$emit('input', newValue)
    },
    remove: function (index) {
      const newValue = [...this.value]
      newValue.splice(index, 1)
      this.$emit('input', newValue)
    }
  },
  template: '<div>
  <shortcut-entry v-for="(shortcut, index) in value" is="shortcut-entry" v-bind:key="index" v-bind="shortcut" @remove="remove(index)"></shortcut-entry>
  <br>
  <button v-on:click=add>Add</button>
  </div>'

And the parent component is something like this:

Vue.component('parent-comp', {
  data () {
    return {
      shortcuts: []
    }
  },
  template: '<shortcut v-model="shortcuts"></shortcut>'
})

*** Use .sync ***

Vue.component('shortcuts', {
  props: {
    shortcuts: Array // Of shortcuts
  },
  methods: {
    add: function () {
      const newValue = [...this.shortcuts, { action: '' }]
      this.$emit('update:shortcuts', newValue)
    },
    remove: function (index) {
      const newValue = [...this.shortcuts]
      newValue.splice(index, 1)
      this.$emit('update:shortcuts', newValue)
    }
  },
  template: '<div>
  <shortcut-entry v-for="(shortcut, index) in shortcuts" is="shortcut-entry" v-bind:key="index" v-bind="shortcut" @remove="remove(index)"></shortcut-entry>
  <br>
  <button v-on:click=add>Add</button>
  </div>'
})

So, the caller component:

Vue.component('parent-comp', {
  data () {
    return {
      shortcuts: []
    }
  },
  template: '<shortcut :shortcuts.sync="shortcuts"></shortcut>'
})

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...