当属性发生变化时,vuejs数据不会发生变化

时间:2018-04-26 12:50:57

标签: vuejs2 vue-component

我是Vuejs的新手,所以尽管我可以通过使用观察者或生命周期钩子自己设计一个解决方案,但我想了解为什么以下不起作用以及应该做些什么。

问题是,只要组件使用者更改属性cellContent,变异的本地数据就不会更新。父母拥有cellContent,因此直接使用该属性是禁忌(Vue似乎同意)。

<template>
  <textarea
    v-model="mutableCellContent"
    @keyup.ctrl.enter="$emit('value-submit', mutableCellContent)"
    @keyup.esc="$emit('cancel')">
  </textarea>
</template>

<script>
export default {
  name: 'CellEditor',
  props: ['cellContent', 'cellId'],
  data () {
    return {
      mutableCellContent: this.cellContent
    }
  }
}
</script>

<style>
...
</style>

2 个答案:

答案 0 :(得分:1)

您必须为道具cellContent创建一个观察者。

&#13;
&#13;
Vue.config.productionTip = false
Vue.config.devtools = false
Vue.config.debug = false
Vue.config.silent = true


Vue.component('component-1', {
  name: 'CellEditor',
  props: ['cellContent', 'cellId'],
  data() {
    return {
      mutableCellContent: this.cellContent
    }
  },
  template: `
    <textarea
      v-model="mutableCellContent"
      @keyup.ctrl.enter="$emit('value-submit', mutableCellContent)"
      @keyup.esc="$emit('cancel')">
    </textarea>
  `,
  watch: {
    cellContent(value) {
      this.mutableCellContent = value;
    }
  }
});

var vm = new Vue({
  el: '#app',
  data() {
    return {
      out: "",
      cellContent: ""
    }
  },
  methods: {
    toOut(...args) {
      this.out = JSON.stringify(args);
    },
    changeCellContent() {
      this.cellContent = "changed at " + Date.now();
    }
  }
});
&#13;
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
  <component-1 :cell-content="cellContent" @value-submit="toOut" @cancel="toOut"></component-1>
  <p>{{out}}</p>
  <button @click="changeCellContent">change prop</button>
</div>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

datamutableCellContent: this.cellContent)中,您正在创建道具的副本,这就是为什么当父级更改时,本地副本(mutableCellContent)是没有更新。 (如果你必须有本地副本,你必须看父母更新它。)

相反,您不应该在子组件中保留副本,只需让状态在父级中(并通过子级中发出的事件更改它)。这是一个众所周知的最佳实践(不仅在Vue中,而且在其他框架中,如果我可以这么说的话)。

示例:

Vue.component('cell-editor', {
  template: '#celleditor',
  name: 'CellEditor',
  props: ['cellContent', 'cellId'],
  data () {
    return {}
  }
});

new Vue({
  el: '#app',
  data: {
    message: "Hello, Vue.js!"
  }
});
textarea { height: 50px; width: 300px; }
<script src="https://unpkg.com/vue"></script>

<template id="celleditor">
  <textarea
    :value="cellContent"
    @keyup.ctrl.enter="$emit('value-submit', $event.currentTarget.value)"
    @keyup.esc="$event.currentTarget.value = cellContent">
  </textarea>
</template>

<div id="app">
  {{ message }}
  <br>
  <cell-editor :cell-content="message" @value-submit="message = $event"></cell-editor>
  <br>
  <button @click="message += 'parent!'">Change message in parent</button>
</div>