web-dev-qa-db-ja.com

Vue.js小道具の変更

コンポーネント内のプロパティを変更する方法について少し混乱しています。次のコンポーネントがあるとします。

{
    props: {
        visible: {
            type: Boolean,
            default: true
        }
    },
    methods: {
         hide() {
              this.visible = false;
         }
    }
} 

動作しますが、次の警告が表示されます。

親コンポーネントが再レンダリングされるたびに値が上書きされるため、プロップを直接変更しないでください。代わりに、小道具の値に基づいてデータまたは計算されたプロパティを使用します。変化するプロップ: "visible"(コンポーネントにあります)

今、私はこれを処理する最良の方法が何であるか疑問に思っています、明らかにvisibleプロパティはDOMでコンポーネントを作成するときに渡されます:<Foo :visible="false"></Foo>

21
woutr_be

your fiddle のコードを参照する

どういうわけか、2つではなく州が住む1つの場所を決める必要があります。 Alertに入れるのが適切か、ユースケースの親に入れるのが適切かはわかりませんが、選択する必要があります。

状態がどこに住んでいるかを決定する方法

親または兄弟コンポーネントは状態に依存しますか?

  • はい:それは親(または外部の状態管理)にある必要があります
  • いいえ:その後、コンポーネント自体の状態にする方が簡単です
  • 両方とも:以下を参照

まれに、組み合わせが必要な場合があります。おそらく、親と子の両方に子を隠す機能を与えたいと思うでしょう。次に、親と子の両方に状態があるはずです(そのため、子の中で子の小道具を編集する必要はありません)。

たとえば、次の場合に子を表示できます:visible && state_visible、ここでvisibleは小道具から派生し、親の状態の値を反映し、state_visibleは子の状態からのものです。

これがあなたが望む行動であるかどうかはわかりませんが、 ここはフィドルです 。子をクリックすると、親コンポーネントのtoggleAlertを実際に呼び出したいだけだと思います。

14
ArneHugo

最新のコメントを読んだ後、親のアラートを表示/非表示するロジックを持っていることに懸念があるようです。したがって、次のことをお勧めします。

# template
<alert :alert-visible="alertVisible"></alert>

# script
data () {
  alertVisible: false,
  ...
},
...

次に、子アラートで、小道具の値を$ watchし、すべてのロジックをアラートに移動します。

子(アラート)

# script
data: {
  visible: false,
  ...
},
methods: {
  hide () {
    this.visible = false
  },
  show () {
    this.visible = true
  },
  ...
},
props: [
  'alertVisible',
],
watch: {
  alertVisible () {
    if (this.alertVisible && !this.visible) this.show()
    else if (!this.alertVisible && this.visible) this.hide()
  },
  ...
},
...
4
GuyC

小道具がこの子コンポーネントにのみ有用な場合、子にpropのような_initialVisibledataのようなmutableVisible、およびcreatedフック(コンポーネントのデータ構造がアセンブルされるときに呼び出されます)では、単にthis.mutableVisible = this.initialVisible

プロップが親コンポーネントの他の子と共有されている場合、それを親のdataにする必要がありますすべての子供。次に、子でthis.$emit('visibleChanged', currentVisible)を変更して親にvisibleを変更するよう通知します。親のテンプレートで、<ThatChild ... :visibleChanged="setVisible" ...>を使用します。ガイドをご覧ください: http://vuejs.org/v2/guide/components.html

3

誰かを助けるために、私は同じ問題に直面していました。 v-model = ""内の変数をprops配列からデータに変更しました。小道具とデータの違いを覚えておいてください、私の場合、それを変更するのは問題ではありませんでした。

例えば。:

<v-dialog v-model="dialog" fullscreen hide-overlay transition="dialog-bottom-transition">

前:

export default {
    data: function () {
        return {
            any-vars: false
        }
    },
    props: {
            dialog: false,
            notifications: false,
            sound: false,
            widgets: false
        },
    methods: {
        open: function () {
            var vm = this;

            vm.dialog = true;
        }
    }
}

後:

export default {
    data: function () {
        return {
            dialog: false
        }
    },
    props: {
            notifications: false,
            sound: false,
            widgets: false
        },
    methods: {
        open: function () {
            var vm = this;

            vm.dialog = true;
        }
    }
}
2
Marco

Vue.jsコンポーネントドキュメント によると:

親プロパティが更新されると、それは子に流れますが、その逆ではありません。それで、何かが起こったとき、どのように親に連絡しますか?これがVueのカスタムイベントシステムの出番です。

子の$emit('my-event)を使用して、親にイベントを送信します。 v-on:my-event(または@my-event)を使用して、親内の子宣言でイベン​​トを受け取ります。

作業例:

// child

Vue.component('child', {
  template: '<div><p>Child</p> <button @click="hide">Hide</button></div>',
  methods: {
    hide () {
      this.$emit('child-hide-event')
    }
  },
})

// parent

new Vue({
  el: '#app',
  data: {
    childVisible: true
  },
  methods: {
    childHide () {
      this.childVisible = false
    },
    childShow () {
      this.childVisible = true
    }
  }
})
.box {
  border: solid 1px grey;
  padding: 16px;
}
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<div id="app" class="box">
  <p>Parent | childVisible: {{ childVisible }}</p>
  <button @click="childHide">Hide</button>
  <button @click="childShow">Show</button>
  <p> </p>
  <child @child-hide-event="childHide" v-if="childVisible" class="box"></child>
</div>
0

ハックのように見えて、単一のデータソースの概念に違反しているかもしれませんが、その作業)このソリューションはローカルプロキシ変数を作成し、小道具からデータを継承しています。次にプロキシ変数を使用します。

Vue.component("vote", {
    data: function() {
        return {
            like_: this.like,
            dislike_: this.dislike,
        }
    },

    props: {
        like: {
            type: [String, Number],
            default: 0
        },
        dislike: {
            type: [String, Number],
            default: 0
        },
        item: {
            type: Object
        }
    },

    template: '<div class="tm-voteing"><span class="tm-vote tm-vote-like" @click="onVote(item, \'like\')"><span class="fa tm-icon"></span><span class="tm-vote-count">{{like_}}</span></span><span class="tm-vote tm-vote-dislike" @click="onVote(item, \'dislike\')"><span class="fa tm-icon"></span><span class="tm-vote-count">{{dislike_}}</span></span></div>',

    methods: {
        onVote: function(data, action) {
            var $this = this;
            // instead of jquery ajax can be axios or vue-resource
            $.ajax({
                method: "POST",
                url: "/api/vote/vote",
                data: {id: data.id, action: action},
                success: function(response) {
                    if(response.status === "insert") {
                        $this[action + "_"] = Number($this[action + "_"]) + 1;
                    } else {
                        $this[action + "_"] = Number($this[action + "_"]) - 1;
                    }
                },
                error: function(response) {
                    console.error(response);
                }
            });
        }
    }
});

コンポーネントを使用して小道具を渡す

<vote :like="item.vote_like" :dislike="item.vote_dislike" :item="item"></vote>
0
Vitaliy