Vue中双向绑定props的正确方式是啥?

Posted

技术标签:

【中文标题】Vue中双向绑定props的正确方式是啥?【英文标题】:What's the correct ways of two-way binding props in Vue?Vue中双向绑定props的正确方式是什么? 【发布时间】:2020-04-12 22:25:42 【问题描述】:

这里我有两个组件:

msg.vue

<template>
 <div>
   <input type="text" v-model="msg" />
 </div>
</template>
<script>
export default 
 name: "msg",
 props: ["msg"]
;
</script>

samples.vue

<template>
  <div>
    <h2> msg </h2>
  </div>
</template>
<script>
export default 
  name: "samples",
  props: ["msg"]
;
</script>

最后,

App.vue

<template>
  <div id="app">
    <samples v-bind:msg="msg"></samples>
    <msg :msg="msg"></msg>
  </div>
</template>

<script>
import samples from "./components/samples.vue";
import msg from "./components/msg.vue";
export default 
  name: "app",
  components: 
    samples,
    msg
  ,
  data: () => 
    return 
      msg: "Hello World"
    ;
  
;
</script>

<style>
#app 
  font-family: "Poppins", Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  margin-top: 60px;

</style>

我想做的是用msg组件我想改变App.vue的数据中的msg组件。但是当我更改值时,Vue 会发出警告:

所以我不明白接下来要做什么。请帮帮我。

【问题讨论】:

【参考方案1】:

1.什么是v-model

<input v-model="msg" />

基本上会转译为

<input :value="msg" @input="msg = $event.target.value" />

2. data vs props

2.1 data 应该是自包含的组件,而 props 是从父级传递的。 2.2 data 在组件内应该是可变的,props 不应该。为什么?因为2.1。

3. mutating a prop locally is considered an anti-pattern in Vue 2


结果:这是我从你的只更改了 2 行代码的解决方案:

App.vue

<template>
  <div id="app">
    <samples v-bind:msg="msg"></samples>
    <msg :msg="msg" @update:msg="msg = $event"></msg> // changed this line
  </div>
</template>

msg.vue

<template>
 <div>
   <input type="text" :value="msg" @input="$emit('uddate:msg', $event.target.value)" /> // changed this line
 </div>
</template>

【讨论】:

感谢@Loi Nguyen Huynh 提供最完整的答案!! @ObnoxiousNerd 不客气,一路上我也学到了很多东西。【参考方案2】:

你根本不允许改变 props,你只能改变 data 变量。

要解决您的问题,您可以这样做。在组件上实现v-model,因此msg 始终保持同步,同样在App

App.vue

<template>
  <div id="app">
    <samples v-bind:msg="msg"></samples>
    <msg v-model="msg"></msg>
  </div>
</template>

<script>
import samples from "./components/samples.vue";
import msg from "./components/msg.vue";
export default 
  name: "app",
  components: 
    samples,
    msg
  ,
  data: () => 
    return 
      msg: "Hello World"
    ;
  
;
</script>

msg.vue

<template>
 <div>
   <input type="text" v-model="selected" />
 </div>
</template>
<script>
export default 
 name: "msg",
 props: ["value"],
 computed: 
   selected: 
     get() 
       return this.value;
     ,
     set(value) 
       return this.$emit('input', value)
     
   
 
;
</script>

【讨论】:

【参考方案3】:

不要使用v-model,而是使用$emit

消息组件

      Vue.component('msg',
        props:["msg"],
        template: `<div>
          <input @keyup="changeMsg" :value="msg">
        </div>`,
        methods:
          changeMsg:function(e)
            this.$emit("changed",e.target.value);
          
        
      );


    <msg @changed="msg = $event" :msg="msg"></msg>

Check Solution in CodePen

【讨论】:

【参考方案4】:

一个简单的解决方案是使用v-bind.sync。按照链接查看文档和用法。通过使用它,您需要更改 2 行代码 以使其工作:

App.vue中:

change
<msg :msg="msg"></msg>
to
<msg :msg.sync="msg"></msg>

msg.vue 中:

change
<input type="text" v-model="msg" />
to
<input type="text" @input="$emit('update:msg',$event.target.value)" />

不过,这个是not recommended by Vue

【讨论】:

以上是关于Vue中双向绑定props的正确方式是啥?的主要内容,如果未能解决你的问题,请参考以下文章

vue中数据双向绑定的原理是啥?

理解VUE2双向数据绑定原理和实现

前端面试被问到,vue实现数据双向绑定,原理是什么

VUE双向绑定原理

Vue props双向绑定

对vue的props实现双向数据流