Vue 中父子组件、兄弟组件通信(不使用Vuex)

一、父子组件通信

1.父组件与子组件通信(通过props属性来完成的)

props 可以是数组或对象,用于接收来自父组件的数据。props 可以是简单的数组,或者使用对象作为替代,对象允许配置高级选项,如类型检测、自定义校验和设置默认值。

1.1.父组件是通过props属性给子组件通信的

父组件:

// 这是父组件的code

<div id="parent">
  <child-f :child1-content="content1" :child1-name="name1" @on-clicks="onClickF"></child-f>
  <child-s :child2-content="content2" @on-clicks="onClickS"></child-s>
</div>
data () {
  return {
    content1: 'this is child1 content',
    content2: 'this is child2 content',
    name1: 'my name is child1',
    name2: 'my name is child2'
  }
}

1.2.子组件通过props来接受数据

第一种写法

props: ['child1Content','child1Name']

第二种方法

props: {

          child1Content: String, //这里指定了字符串类型,如果类型不一致会警告的哦

           child1Name: String

}

第三种方法

props: {
  child1Content: String, // 这里指定了字符串类型,如果类型不一致会警告的哦
  child1Name: {
    type: String,
    default: 'my name is child'// 这里指定了一个默认值
  }
}

1.3.子组件改变props值,并向父组件传值

   1.3.1.prop 作为初始值传入后,子组件想把它当作局部数据来用;

  1.3.2.prop 作为初始值传入,由子组件处理成其它数据输出。

  对这两种原因,正确的应对方式是:
  定义一个局部变量,并用 prop 的值初始化它: 
 

data () {
  return {
    content: this.child1Content
  }
}


  定义一个计算属性,处理 prop 的值并返回: 
 

computed: {
  name: function () {
    return this.child1Name.toLocaleUpperCase()// 所有的字母字符都被转换为大写
  }
}

  注意在 JavaScript 中对象和数组是引用类型,指向同一个内存空间,如果 prop 是一个对象或数组,在子组件内部改变它会影响  父组件的状态。

2.子父组件通信

vue2.0只允许单向数据传递,我们通过触发事件来改变组件的数据

子组件中需要以某种方式例如点击事件的方法来触发一个自定义事件

将需要传的值作为$emit的第二个参数,该值将作为实参传给响应自定义事件的方法

在父组件中注册子组件并在子组件标签上绑定对自定义事件的监听

子组件
// code

<template>
  <div id="child1">
    <div @click="child1Click"
         style="height: 100px;width: 100px;background-color: blue;padding: 20px;margin: 20px;float: left">
      我是子组件1,我的上面有一个点击事件child1Click
    </div>
  </div>
</template>
methods: {
  child1Click () {
    console.log('this is child1Click==')
    let params = {
      name: 'child1',
      content: 'child1 mesage'
    }
    this.$emit('on-clicks', params) // 触发on-clicks方法,params为向父组件传递的数据
  }
}

父组件
// code

<child-f :child1-content="content1" :child1-name="name1" @on-clicks="onClickF"></child-f>
methods: {
  onClickF (params) {
    console.log('这是child1Click触发的事件,child1传给父组件参数==', params)
  }
}

二、兄弟组件通信

两种思想: 1.子通知父,父通知兄弟;2.事件绑定和触发

1.子通知父,父通知子(兄弟)

// 该思路就是根据父子组件之间进行通信的原理来实现兄弟组件间进行通信的,所以此处就不上代码了。

2.事件绑定和触发

借助于一个公共的Vue的实例对象,不同的组件可以通过该对象完成事件的绑定和触发

新建一个event.js文件,在里面新建一个Vue实例,这个实例就承担起了组件之间通信的桥梁了。

event.js

import Vue from 'Vue'
const bus = new Vue()
export default bus

第一步: 在child1子组件中,绑定一个点击事件child1Clicks, 在事件中我们通过公共的Vue对象bus.$emit()方法去触发一个定义事件clickstochild2,并传递我们的参数params;

第二步: 在child2组件创建的钩子(created())中监听事件clickstochild2, 并输出child1传入的参数params

子组件1

<div @click="child1Clicks"
     style="height: 100px;width: 100px;background-color: blue;padding: 20px;margin: 20px;float: left">
  子组件1,事件child1Clicks测试兄弟组件通信
</div>
// 借助于一个公共的Vue的实例对象,不同的组件可以通过该对象完成事件的绑定和触发
import bus from './event.js'

  methods: {
  child1Clicks () {
  console.log('this is child1Clicks==')
  let params = {
  name: 'child1',
  content: 'child1 mesage to child2'
  }
  // 触发clickstochild2方法,params为向兄弟组件child2组件传递的数据
  bus.$emit('clickstochild2', params)
  }
  }

子组件2

// 借助于一个公共的Vue的实例对象,不同的组件可以通过该对象完成事件的绑定和触发
import bus from './event.js'

created () {
// 调用bus中的on方法
// 在child2组件创建的钩子(created())中监听事件clickstochild2, 并输出child1传入的参数params
bus.$on('clickstochild2', (params) => {
console.log('这是监听兄弟组件child1传入的参数==', params)
})
}

三、完整代码

1.父组件

// parent.vue

<template>
  <div id="parent">
    <div class="h-border">Vue 中父子组件、兄弟组件通信(不使用Vuex)</div>
    <child-f :child1-content="content1" :child1-name="name1" @on-clicks-child1="onClickF"></child-f>
    <child-s :child2-content="content2" :child2-name="name2" @on-clicks-child2="onClickS"></child-s>
  </div>
</template>

<script type="text/ecmascript-6">
  import childF from './Child1.vue'
  import childS from './Child2.vue'
  export default {
    components: {
      childF,
      childS
    },
    data () {
      return {
        content1: 'this is child1 content',
        content2: 'this is child2 content',
        name1: 'my name is child1',
        name2: 'my name is child2'
      }
    },
    methods: {
      onClickF (params) {
        console.log('这是child1Click触发的事件,child1传给父组件参数==', params)
      },
      onClickS (params) {
        console.log('这是child2Click触发的事件,child2传给父组件参数==', params)
      }
    }
  }
</script>

<style>
  #parent {
    padding: 30px;
    line-height: 30px;
    padding-top: 50px;
    text-align: center;
  }

  .h-border {
    border-bottom: 2px solid black;
  }
</style>

2.子组件1

// Child1.vue

<template>
  <div id="child1">
    <div @click="child1Click"
         style="height: 100px;width: 100px;background-color: blue;padding: 20px;margin: 20px;float: left">
      我是子组件1,我的上面有一个点击事件child1Click
    </div>
    <div @click="child1Clicks"
         style="height: 100px;width: 100px;background-color: blue;padding: 20px;margin: 20px;float: left">
      子组件1,事件child1Clicks测试兄弟组件通信
    </div>
  </div>
</template>

<script type="text/ecmascript-6">
  // 借助于一个公共的Vue的实例对象,不同的组件可以通过该对象完成事件的绑定和触发
  import bus from './event.js'
  export default {
    props: {
      child1Content: String, // 这里指定了字符串类型,如果类型不一致会警告的哦
      child1Name: {
        type: String,
        default: 'my name is child'// 这里指定了一个默认值
      }
    },
    data () {
      return {
          // prop 作为初始值传入后,子组件想把它当作局部数据来用
        content: this.child1Content
      }
    },
    computed: {
        // prop 作为初始值传入,由子组件处理成其它数据输出。
      name: function () {
        return this.child1Name.toLocaleUpperCase()// 所有的字母字符都被转换为大写
      }
    },
    methods: {
      child1Click () {
        console.log('this is child1Click==')
        let params = {
          name: 'child1',
          content: 'child1 mesage'
        }
        this.$emit('on-clicks-child1', params) // 触发on-clicks方法,params为向父组件传递的数据
      },
      child1Clicks () {
        console.log('this is child1Clicks==')
        let params = {
          name: 'child1',
          content: 'child1 mesage to child2'
        }
        // 触发clickstochild2方法,params为向兄弟组件child2组件传递的数据
        bus.$emit('clickstochild2', params)
      }
    },
    created () {
      console.log('这是父组件传个child1的参数child1Name==', this.child1Name)
      console.log('这是父组件传个child1的参数child1Content==', this.child1Content)
      console.log('这是父组件传个child1的参数child1Content赋值给content后 this.content==', this.content)
      console.log('这是父组件传个child1的参数child1Name改变后的值  this.name==', this.name)
    }
  }
</script>

<style>

</style>

3.子组件2

// Child2.vue

<template>
  <div id="child2">
    <div @click="child2Click"
         style="height: 100px;width: 100px;background-color: red;padding: 20px;margin: 20px;float: left">
      我是子组件2,我的上面有一个点击事件child2Click
    </div>
  </div>
</template>

<script type="text/ecmascript-6">
  // 借助于一个公共的Vue的实例对象,不同的组件可以通过该对象完成事件的绑定和触发
  import bus from './event.js'
  export default {
    props: {
      child2Content: String, // 这里指定了字符串类型,如果类型不一致会警告的哦
      child2Name: {
        type: String,
        default: 'my name is child'// 这里指定了一个默认值
      }
    },
    data () {
      return {
        counter: 0
      }
    },
    methods: {
      child2Click () {
        console.log('this is child2Click==')
        let pam = {
          name: 'child2',
          content: 'child2 mesage'
        }
        this.$emit('on-clicks-child2', pam) // 触发onClick方法,params为向父组件传递的数据
      }
    },
    created () {
      console.log('这是父组件传个child2的参数child2Name==', this.child2Name)
      console.log('这是父组件传个child2的参数child2Content==', this.child2Content)
      // 调用bus中的on方法
      // 在child2组件创建的钩子(created())中监听事件clickstochild2, 并输出child1传入的参数params
      bus.$on('clickstochild2', (params) => {
        console.log('这是监听兄弟组件child1传入的参数==', params)
      })
    }
  }
</script>

<style>
</style>

4.event.js

import Vue from 'Vue'
const bus = new Vue()
export default bus

猜你喜欢

转载自blog.csdn.net/ly124100427/article/details/81708377