Vue组件间通信

Vue组件间通信

1、Props和Events(主要用于父子组件间通讯)

该类通讯方式基础知识介绍
Props(父传子)

props 是 Vue.js 中组件间通信的一种方式,允许父组件向其子组件传递数据。

在父组件中,你可以使用 props 关键字将数据传递到子组件中。例如:

<template>
  <child-component :my-prop="message"></child-component>
</template>

<script>
export default {
  data () {
    return {
      message: 'Hello Vue.js!'
    }
  }
}
</script>

在子组件中,你可以在其 props 选项中声明接收的属性。例如:

<template>
  <p>{{ myProp }}</p>
</template>

<script>
export default {
  props: ['myProp']
}
</script>

需要注意的是,子组件中的 props 数据是不可修改的。如果需要对数据进行修改,可以将数据复制到本地数据中,再在本地数据中进行修改。

Events(子传父)
$emit

Vue.js 中的 events 是父子组件之间通信的重要方式。events 允许父组件监听并响应来自子组件的事件。

$emit 是 Vue.js 的一个实例方法,用于向父组件传递事件。

当在子组件内部调用 $emit 方法时,可以将事件向上冒泡,从而触发父组件中的事件处理函数。

使用方法如下:

this.$emit('eventName', arg1, arg2, ...)

第一个参数 eventName 表示事件名称,可以自定义。后面的参数是传递给父组件的参数。

在父组件中,可以通过 on 指令监听该事件,并编写事件处理函数

通讯

使用方法:

  • 父组件监听事件:使用 v-on 指令监听子组件触发的事件。
<template>
  <child-component @myEvent="handleEvent"></child-component>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent,
  },
  methods: {
    handleEvent(data) {
      console.log(data);
    },
  },
};
</script>

子组件中触发事件:使用 this.$emit 函数触发事件,并传递数据。

<template>
  <div>
    <button @click="handleClick">Click me</button>
  </div>
</template>

<script>
export default {
  methods: {
    handleClick() {
      this.$emit('myEvent', 'Hello World');
    },
  },
};
</script>
通讯

Props主要用于父组件向子组件传递数据,Events则是用于子组件向父组件传递数据。下面是一个简单的示例代码,演示了如何使用Props和Events实现组件间的通讯:

父组件:

<template>
  <div>
      //:message为props,其中的内容递送给子组件
      //@child—event为event,其中的方法用来处理子组件发来的数据
    <child-component :message="parentMessage" @child-event="handleChildEvent"/>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  name: 'ParentComponent',
  components: {
    ChildComponent,
  },
  data() {
    return {
      parentMessage: 'Hello from parent component!',
    };
  },
  methods: {
    handleChildEvent(childMessage) {
      console.log(`Received message from child component: ${childMessage}`);
    },
  },
};
</script>

子组件:

<template>
  <div>
    <p>{{ message }}</p>
    <button @click="sendEvent">Send Event</button>
  </div>
</template>

<script>
export default {
  name: 'ChildComponent',
  //此数据从父组件获得
  props: {
    message: String,
  },
  methods: {
    sendEvent() {
      const childMessage = 'Hello from child component!';
      this.$emit('child-event', childMessage);
    },
  },
};
</script>

在上面的示例代码中,父组件向子组件传递数据使用了Props,子组件通过props选项接收了来自父组件的message数据,并将其显示在了页面上。父组件通过v-bind指令将parentMessage数据绑定到了子组件的message props上。

在子组件向父组件传递数据方面,使用了Events。子组件在sendEvent方法中创建了一个包含子组件发送的消息的字符串,并通过this.$emit()方法触发了名为’child-event’的自定义事件。父组件则在模板中使用@child-event监听了这个事件,并在handleChildEvent方法中接收并处理了子组件发送的消息。

2、$emit 和 $on

// ChildA.vue
<template>
  <div>
    <button @click="emitData">发送数据到ChildB组件</button>
  </div>
</template>

<script>
export default {
  methods: {
    emitData() {
      this.$emit('passData', 'hello from ChildA');
    },
  },
};
</script>
// ChildB.vue
<template>
  <div>
    <p>接收到的数据:{{ data }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      data: '',
    };
  },
  mounted() {
    //对passData数据结构进行监听,当监听道passData变化时,调用receiveData
    this.$on('passData', this.receiveData);
  },
  methods: {
    receiveData(data) {
      this.data = data;
    },
  },
  beforeDestroy() {
    this.$off('passData', this.receiveData);
  },
};
</script>

在这个例子中,ChildA 组件定义了一个 emitData 方法,并在点击按钮时触发 $emit('passData', 'hello from ChildA'),其中第一个参数 'passData' 是事件名称,第二个参数 'hello from ChildA' 是要传递的数据。

ChildB 组件中在 mounted 钩子中使用 $on 方法监听事件 'passData',并在事件触发时执行 receiveData 方法,将接收到的数据保存在 data 中。在 beforeDestroy 钩子中使用 $off 方法移除监听器,以避免内存泄漏。

这种方式通过 $emit$on 方法实现了父组件向子组件传递数据的功能,也可以通过将 $emit 改为在子组件上触发事件来实现子组件向父组件传递数据。

3、$refs

$refs简介

Vue 中的 $refs 是一个 Vue 实例的属性,它可以用来访问模板中的 DOM 元素,组件,或某些子组件。

$refs 不是响应式数据,不能直接在模板中使用,仅可以在 JavaScript 代码中使用。

使用 $refs 的方法是在某个 DOM 元素或组件上加上 ref 属性,并将其作为 $refs 的一个属性来访问,代码示例如下:

HTML:

<template>
  <div>
    <input type="text" ref="inputRef">
    <button @click="sayHello">Click Me</button>
  </div>
</template>

JavaScript:

<script>
export default {
  methods: {
    sayHello() {
      console.log(this.$refs.inputRef.value)
    }
  }
}
</script>

​ 在上面的代码中,我们为输入框添加了 ref 属性,并在点击按钮时使用 $refs 访问该输入框的值。

总的来说,$refs 可以帮助我们访问模板中的某些特定元素,但是应该尽量少用,因为它不是响应式的,并且它的使用有可能导致代码变得不可维护。因此,对于大多数情况,应该使用响应式数据和计算属性。

通讯

可以通过$refs属性访问子组件的实例,从而直接调用子组件的方法或访问子组件的数据。下面是一个简单的示例:

父组件:

<template>
  <div>
    <child-component ref="child"></child-component>
    <button @click="callChildMethod">Call Child Method</button>
  </div>
</template>
<script>
  import ChildComponent from './ChildComponent.vue';

  export default {
    components: {
      ChildComponent
    },
    methods: {
      callChildMethod() {
        // 通过 $refs 访问子组件的方法
        this.$refs.child.childMethod();
      }
    }
  }
</script>

子组件:

<template>
  <div>
    <p>{{ message }}</p>
  </div>
</template>
<script>
  export default {
    data() {
      return {
        message: 'Hello from Child Component'
      }
    },
    methods: {
      childMethod() {
        console.log('This is a method in child component');
      }
    }
  }
</script>

4、Vuex方式

Vue组件间通信的Vuex方式是通过Vuex状态管理库来实现的。它允许我们在一个单独的地方维护应用程序的状态,并在所有组件中共享这个状态。以下是一个简单的示例,展示了如何在两个组件之间使用Vuex进行通信:

1、首先,在src目录下新建一个store.js文件,用来创建Vuex store。
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  //state:存储应用程序的状态,通常是一个对象。
  state: {
    message: ''
  },
  //mutations:修改state的唯一途径,它们是同步的事务。
  mutations: {
    setMessage(state, payload) {
      state.message = payload
    }
  },
  //actions:提交mutations,但是可以包含任意异步操作。
  actions: {
    setMessage(context, payload) {
      context.commit('setMessage', payload)
    }
  },
  //getters:对state进行派生,通常是一些计算属性。
  getters: {
    getMessage(state) {
      return state.message
    }
  }
})
2、在需要使用Vuex的组件中引入store。
import store from '@/store'
3、在发送组件中触发Vuex中的action,以更新state中的值。
<template>
  <div>
    <input type="text" v-model="message">
    <button @click="setMessage">Send</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: ''
    }
  },
  methods: {
    setMessage() {
      this.$store.dispatch('setMessage', this.message)
    }
  }
}
</script>
4、在接收组件中通过计算属性获取Vuex中的值。
<template>
  <div>
    <p>Received message: {{ message }}</p>
  </div>
</template>

<script>
export default {
  computed: {
    message() {
      return this.$store.getters.getMessage
    }
  }
}
</script>

在这个示例中,我们创建了一个名为message的状态属性,并定义了一个名为setMessage的mutation来更新该属性的值。我们还定义了一个名为setMessage的action来提交mutation,以便我们可以从发送组件中调用它。

在发送组件中,我们将message的值绑定到一个文本输入框,并创建一个名为setMessage的方法,该方法将使用dispatch方法触发Vuex action来更新状态值。

在接收组件中,我们使用计算属性来获取Vuex中的值,以便我们可以在模板中显示它。

5、Bus(事件总线)方式

使用Vue实例作为事件总线,组件之间通过事件总线进行通信。

<template>
  <div>
    <p>{{ message }}</p>
    <button @click="sendMessage">发送消息</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: ''
    }
  },
  methods: {
    sendMessage() {
      // 向事件总线发送消息
      this.$bus.$emit('message', 'Hello World!');
    }
  },
  created() {
    // 监听事件总线的消息
    this.$bus.$on('message', (message) => {
      this.message = message;
    });
  }
}
</script>

在上面的示例中,我们创建了一个名为 $bus 的新的Vue实例,并通过 $emit 方法向事件总线发送消息,在组件的 created 钩子中通过 $on 方法监听事件总线的消息,并将接收到的消息保存到组件的 message 变量中。

当需要在另一个组件中接收这个消息时,也可以使用 $bus.$on 方法监听同样的事件名,并在回调函数中处理接收到的消息。

需要注意的是,当使用Bus方式实现组件间通信时,需要手动销毁事件总线。可以在组件的 beforeDestroy 钩子中使用 $bus.$off 方法移除事件监听,以避免内存泄漏。

6、Provide 和 Inject

ProvideInject 是 Vue 提供的一种高级组件间通讯方式,它可以让祖先组件向后代组件注入一个依赖,使得子孙组件可以访问到这个依赖。

使用 ProvideInject 时,我们需要在父组件中通过 provide 方法提供一个值,然后在子组件中通过 inject 方法注入这个值。这个值可以是任何 JavaScript 数据类型,例如对象、数组、字符串等。

<template>
  <div>
    <p>父组件数据:{{data}}</p>
    <child-component></child-component>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent,
  },
  data() {
    return {
      data: '这是父组件的数据',
    };
  },
  provide() {
    // 将数据注入provide对象中
    return {
      data: this.data,
    };
  },
};
</script>
<template>
  <div>
    <p>子组件数据:{{data}}</p>
  </div>
</template>

<script>
export default {
  inject: ['data'], // 注入父组件provide对象中的数据
  data() {
    return {
      data: '',
    };
  },
  created() {
    // 使用注入的数据
    this.data = this.data || '这是子组件的默认数据';
  },
};
</script>

在这个例子中,父组件中的provide选项将数据注入了provide对象中,而子组件中使用inject选项来注入provide对象中的数据,实现了父子组件之间的通信。

需要注意的是,provideinject并不是响应式的,所以需要手动触发组件更新来重新渲染页面。同时,在使用inject时需要注意默认值的处理,否则可能会导致数据未正常显示的问题。

Provide 和 Inject 的优点:

  • 方便数据共享。使用 Provide 和 Inject,可以方便的共享数据。
  • 不依赖于父子关系。使用 Provide 和 Inject,可以在任意组件间共享数据,不仅限于父子关系。
  • 可以保证数据的响应式。在 Provide 中定义的数据是响应式的,并且可以在子组件中直接使用。
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学不会只能哭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值