VUE-父子组件通信 及 v-model实现通信

一、父组件向子组件传值

1、首先创建父组件(parent)和子组件(child),并在父组件中注册子组件

2、在父组件调用子组件标签中添加一个自定义属性(msg)

// 父组件
	<template>
        <div class="parent">
            <Child :msg="parentMsg"></Child>
        </div>
    </template>
    <script>
        import Child from './child.vue';
        export default {
            data() {
                return {
                    parentMsg: "我是传给子组件的值"
                };
            },
            components: {
                Child
            },
        }
	</script>

3、在子组件的props中将父组件中自定义属性(msg)添加进去,则该属性在子组件中可以像data中定义的属性一样使用

// 子组件
 	<template>
        <div class="child">
            <p>{{ msg }}</p>
        </div>
    </template>
    <script>
        export default {
            props: {
                msg:{
                    type:String,
                    default:""
                }
            }
        }
    </script>

二、子组件向父组件传值

1、在子组件中创建一个按钮,给按钮绑定一个点击事件

2、在响应 点击事件的函数中使用$emit来发送一个自定义事件(listenChildEvent)给父组件,并传递一个参数

	<template>
        <div class="child">
            <p>{{ msg }}</p>
            <button @click="sendMsg">向父组件传值</button>
        </div>
    </template>
    <script>
        export default {
            props: {
                msg:{
                    type:String,
                    default:""
                }
            },
            methods:{
                sendMsg(){
                    this.$emit("listenChildEvent","this message is from child");
                }
            }
        }
    </script>

3、在父组件调用子组件标签中,监听该自定义事件(listenChildEvent)并添加一个响应该事件的处理方法,并接收子组件传过来的数据

<template>
        <div class="parent">
            <Child :msg="parentMsg" @listenChildEvent="acceptMsgFromChild"></Child>
        </div>
    </template>
    <script>
        import Child from './child.vue';
        export default {
            data() {
                return {
                    parentMsg: "我是传给子组件的值"
                };
            },
            components: {
                Child
            },
            methods:{
                acceptMsgFromChild(data){
                    console.log(data);//或者将接受值处理
                }
            }
        }
    </script>

三、使用v-model实现父子组件通信

1、v-model一般用于表单的双向数据绑定

<template>
  <div>
    <input type="text"
           v-model="msg">
    <p>{{msg}}</p>
  </div>
</template>
<script>
export default {
  data () {
    return {
      msg: ''
    }
  }
}
</script>

2、v-model原理

由此看出,v-model是v-bindv-on:input的结合,即监听了表单的input事件,然后修改value属性对应的值

<template>
  <div>
    <input type="text"
           :value="msg"
           @input="bind">
    <p>{{msg}}</p>
  </div>
</template>
<script>
export default {
  data () {
    return {
      msg: ''
    }
  },
  methods: {
    bind () {
      this.msg = event.target.value
    }
  }
}
</script>

3、v-model除了在输入表单上可以使用之外,在组件上也可以使用,以实现父子组件的双向数据绑定

// -------------------------------父组件
<template>
  <div>
    <!-- 在父组件中用v-model相当于,v-bind绑定了value,以及执行了v-on:input事件 -->
    <child v-model="flag"></child>
    <div>{{flag}}</div>
  </div>
</template>
<script>
export default {
  data () {
    return {
      flag: ''
    }
  },
  components: {
    child
  }
}
</script>

// -------------------------------子组件
<template>
  <div>
      <div class="btn" @click="confirm">确定</div>
  </div>
</template>
<script>
export default {
// 用props接收父组件传递的value值,从而实现双向数据绑定
  props: {
    value: {
      type: Boolean,
      default: true
    }
  },
  methods: {
    // 通过$emit触发父组件的input事件,并将第二个参数作为值传递给父组件
    confirm () {
      this.$emit('input', false)
    }
  }
}
</script>

最后,父组件中的flag默认为true,点击了子组件中的“确定”后,子组件将false传递给了父组件的flag

4、v-model添加model选项

以上这种方式实现的父子组件的v-model通信,限制了popos接收的属性名必须为value和emit触发的必须为input,这样容易有冲突,特别是在表单里面。所以,为了更优雅的使用v-model通信,可以在子组件中使用model选项

// 子组件
<template>
  <div>
      <div class="btn" @click="confirm">确定</div>
  </div>
</template>
<script>
export default {
// model选项用来避免冲突,prop属性用来指定props属性中的哪个值用来接收父组件v-model传递的值,例如:这里用props中的flag1来接收父组件传递的v-model值;event属性可以理解为父组件@input的别名,从而避免冲突,即emit时要提交的事件名。
  model: {
	prop: 'flag1',
	event: 'changed'
  }
// 用props接收父组件传递的value值,从而实现双向数据绑定
  props: {
    value: {
      type: Boolean,
      default: true
    }
  },
  methods: {
    // 通过$emit触发父组件的input事件,并将第二个参数作为值传递给父组件
    confirm () {
      this.$emit('input', false)
    }
  }
}
</script>

5、v-model实现动态传值

<template>
  <div>
    <new-input v-model="name"></new-input>{{name}}
  </div>
</template>
<script>
import Vue from 'vue'
Vue.component('new-input', {
  props: {
    value: {
      type: String
    }
  },
  template: '<label><input type="text" v-model="newValue" /> 你的名字:</label>',
  computed: {
    newValue: {
      get: function () {
        return this.value
      },
      set: function (value) {
        this.$emit('input', value)
      }
    }
  }
})

export default {
  data () {
    return {
      name: 'nick'
    }
  }
}
</script>
posted @ 2020-08-14 14:51  sunidol  阅读(2794)  评论(0编辑  收藏  举报