Vue组件间通信的8种方式有哪些?

目录

Vue组件间通信的8种方式包括:

                1. Props:父组件通过props向子组件传递数据。

        2.$emit和$on:父组件通过$emit触发事件,并在子组件中通过$on监听事件来实现父子组件之间的通信

        3.$attrs和$listeners:在父组件中通过$attrs传递属性给子组件,在子组件中通过$listeners监听事件来实现父子组件之间的通信 

        4.provide和inject:在父组件中通过provide提供数据,在子组件中通过inject注入数据来实现跨层级组件的通信

        5.$parent和$children:通过$parent引用父组件,通过$children引用子组件来实现父子组件之间的通信的实例详解

        6.Refs:通过ref属性在父组件中获取子组件的引用,从而可以直接操作子组件的方法和属性

        7. Event Bus:使用一个中央事件总线来进行组件间的通信,即创建一个用于事件通信的空的Vue实例作为中央事件总线

        8.Vuex:使用Vue的状态管理库Vuex来实现组件间的通信,通过共享的状态来进行数据的传递和更新


Vue组件间通信的8种方式包括:

1. Props:父组件通过props向子组件传递数据。


2. $emit和$on:父组件通过$emit触发事件,并在子组件中通过$on监听事件来实现父子组件之间的通信。


3. $attrs和$listeners:在父组件中通过$attrs传递属性给子组件,在子组件中通过$listeners监听事件来实现父子组件之间的通信。


4. provide和inject:在父组件中通过provide提供数据,在子组件中通过inject注入数据来实现跨层级组件的通信。


5. $parent和$children:通过$parent引用父组件,通过$children引用子组件来实现父子组件之间的通信。


6. Refs:通过ref属性在父组件中获取子组件的引用,从而可以直接操作子组件的方法和属性。


7. Event Bus:使用一个中央事件总线来进行组件间的通信,即创建一个用于事件通信的空的Vue实例作为中央事件总线。


8. Vuex:使用Vue的状态管理库Vuex来实现组件间的通信,通过共享的状态来进行数据的传递和更新。

以上这些方式各有其适用的场景,可以根据具体的需求选择合适的方式来实现组件间的通信。

1. Props:父组件通过props向子组件传递数据。

假设我们要封装一个通用的按钮组件,父组件可以通过props向子组件传递按钮的文字和点击事件。首先,在父组件中引入并注册子组件:

<template>
  <div>
    <my-button :text="buttonText" @click="handleClick"></my-button>
  </div>
</template>

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

export default {
  components: {
    MyButton
  },
  data() {
    return {
      buttonText: 'Click me'
    }
  },
  methods: {
    handleClick() {
      console.log('Button clicked');
    }
  }
}
</script>

然后,在子组件中定义props接收父组件传递的数据,并将其渲染到模板中:

<template>
  <button @click="onClick">{
    
    { text }}</button>
</template>

<script>
export default {
  props: {
    text: {
      type: String,
      required: true
    }
  },
  methods: {
    onClick() {
      this.$emit('click');
    }
  }
}
</script>

在父组件中,我们通过`:text="buttonText"`将按钮的文字传递给子组件的props,然后在子组件中通过`this.text`来获取这个值并渲染到按钮上。同时,我们通过`@click="handleClick"`将父组件的点击事件传递给子组件,子组件内部通过`this.$emit('click')`触发一个名为`click`的自定义事件。

这样,当父组件中的按钮被点击时,`handleClick`方法会被调用,并输出信息到控制台。

通过props,我们可以将数据从父组件传递给子组件,实现组件间的通信和复用。

2.$emit和$on:父组件通过$emit触发事件,并在子组件中通过$on监听事件来实现父子组件之间的通信

假设我们有一个父组件和一个子组件,我们希望当父组件中的按钮被点击时,子组件弹出一个提示框显示信息。

首先,在父组件中引入并注册子组件:

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

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

export default {
  components: {
    ChildComponent
  },
  methods: {
    handleClick() {
      this.$emit('show-message', 'Button clicked');
    }
  }
}
</script>

然后,在子组件中通过$on监听父组件发出的事件,并在回调函数中执行相应的逻辑:

<template>
  <div>
    <div v-if="showMessage" class="message-box">
      {
    
    { message }}
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      showMessage: false,
      message: ''
    }
  },
  created() {
    this.$parent.$on('show-message', this.showMessageHandler);
  },
  destroyed() {
    this.$parent.$off('show-message', this.showMessageHandler);
  },
  methods: {
    showMessageHandler(message) {
      this.showMessage = true;
      this.message = message;
      setTimeout(() => {
        this.showMessage = false;
        this.message = '';
      }, 3000);
    }
  }
}
</script>

<style>
.message-box {
  background-color: #eaeaea;
  padding: 10px;
  border-radius: 5px;
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
</style>

在父组件中,我们通过`this.$emit('show-message', 'Button clicked')`触发一个名为`show-message`的自定义事件,并将消息作为参数传递给子组件。子组件内部,我们在`created`生命周期钩子中使用`this.$parent.$on('show-message', this.showMessageHandler)`监听父组件发出的`show-message`事件,并将其与`showMessageHandler`方法绑定。在`showMessageHandler`方法中,我们更新子组件的`showMessage`和`message`属性,并设置一个定时器,在3秒后隐藏提示框。

这样,当父组件中的按钮被点击时,子组件会弹出一个提示框显示相应的消息。

通过$emit和$on,我们可以实现父子组件之间的通信,使得父组件可以向子组件发送消息,并通过事件监听机制在子组件中执行相应的逻辑。
 

3.$attrs和$listeners:在父组件中通过$attrs传递属性给子组件,在子组件中通过$listeners监听事件来实现父子组件之间的通信 

$attrs是父组件中未被props所接收的非特定属性。$listeners是父组件中未被子组件所监听的事件监听器。

让我们通过一个具体的实例来理解$attrs和$listeners的使用。

假设我们有一个父组件和一个子组件。父组件中有一个自定义的按钮组件,我们希望可以通过父组件向子组件传递按钮的样式和点击事件的监听器。

首先,在父组件中引入并注册子组件:

<template>
  <div>
    <my-button class="btn-style" @click="handleClick">Click me</my-button>
  </div>
</template>

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

export default {
  components: {
    MyButton
  },
  methods: {
    handleClick() {
      console.log('Button clicked');
    }
  }
}
</script>

然后,在子组件中使用$attrs和$listeners来接收父组件传递的属性和事件监听器:

<template>
  <button v-bind="$attrs" v-on="$listeners">{
    
    { $slots.default }}</button>
</template>

<script>
export default {
}
</script>

在父组件中,我们通过`class="btn-style"`给按钮添加了一个样式类,并通过`@click="handleClick"`监听了点击事件。

在子组件中,我们使用`v-bind="$attrs"`将父组件传递的所有属性绑定到按钮上,这样父组件中的所有属性会自动传递给子组件。同时,我们使用`v-on="$listeners"`将父组件中的所有事件监听器绑定到按钮上,这样父组件中的所有事件监听器会自动传递给子组件。

通过这样的设置,父组件向子组件传递的样式和点击事件监听器都会被应用到子组件的按钮上。

在这个例子中,$attrs和$listeners允许我们在父组件中定义按钮的样式和点击事件的监听器,并将其传递给子组件。这样可以实现父子组件之间的通信和灵活性。
 

4.provide和inject:在父组件中通过provide提供数据,在子组件中通过inject注入数据来实现跨层级组件的通信

在Vue组件中,可以使用provide和inject来实现跨层级组件的通信。provide选项允许一个组件向其所有子组件提供数据,而inject选项允许子组件在其祖先组件的任意层级中注入这些数据。

下面是一个具体的示例,说明如何在父组件中通过provide提供数据,在子组件中通过inject注入数据来实现跨层级组件的通信。

父组件:

<template>
  <div>
    <child-component></child-component>
  </div>
</template>

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

export default {
  components: {
    ChildComponent
  },
  provide() {
    // 使用provide提供数据
    return {
      message: 'Hello from parent component'
    }
  }
}
</script>

子组件:

<template>
  <div>
    <p>{
    
    { injectedMessage }}</p>
  </div>
</template>

<script>
export default {
  inject: ['message'], // 使用inject注入数据
  computed: {
    injectedMessage() {
      return this.message;
    }
  }
}
</script>

在父组件中,我们使用provide选项来提供数据。在这个例子中,我们提供了一个名为"message"的数据,值为"Hello from parent component"。

在子组件中,我们使用inject选项来注入数据。通过将"message"添加到inject数组中,子组件就可以在其祖先组件的任意层级中访问到这个数据。在子组件中,我们使用computed属性来获取并显示注入的消息。

通过使用provide和inject,父组件可以向其所有子组件传递数据,而无需显式地在每个子组件中声明props。这使得跨层级组件的通信更加方便和灵活。
 

5.$parent和$children:通过$parent引用父组件,通过$children引用子组件来实现父子组件之间的通信的实例详解

$parent和$children是Vue实例中提供的两个属性,可以用来在父子组件之间进行通信。

首先,让我们创建一个父组件和一个子组件的示例。

父组件:

<template>
  <div>
    <h2>Parent Component</h2>
    <p>Message: {
    
    { message }}</p>
    <button @click="updateMessage">Update Message</button>
    <child-component></child-component>
  </div>
</template>

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

export default {
  components: {
    ChildComponent
  },
  data() {
    return {
      message: 'Hello from parent'
    }
  },
  methods: {
    updateMessage() {
      this.message = 'Updated message from parent';
    }
  }
}
</script>

子组件:

<template>
  <div>
    <h2>Child Component</h2>
    <p>Parent Message: {
    
    { parentMessage }}</p>
    <button @click="updateParentMessage">Update Parent Message</button>
  </div>
</template>

<script>
export default {
  computed: {
    parentMessage() {
      return this.$parent.message;
    }
  },
  methods: {
    updateParentMessage() {
      this.$parent.message = 'Updated message from child';
    }
  }
}
</script>

在父组件中,我们定义了一个数据属性`message`,并在模板中显示该属性的值。还有一个方法`updateMessage`,当点击按钮时,更新`message`的值。

子组件中,我们使用计算属性`parentMessage`来获取父组件中的`message`属性的值。在方法`updateParentMessage`中,我们通过`this.$parent.message`来访问父组件的`message`属性,并进行更新。

通过这样的设置,父组件和子组件之间可以相互访问和更新彼此的数据。

需要注意的是,使用$parent和$children来访问父子组件之间的数据并不是最佳的做法,因为这种方式在组件树结构发生变化时可能会出现问题。更好的方式是使用props和事件来进行组件之间的通信。但是在某些情况下,$parent和$children可以作为一种简单的临时解决方案使用。
 

6.Refs:通过ref属性在父组件中获取子组件的引用,从而可以直接操作子组件的方法和属性

在Vue中,可以使用`ref`属性来在父组件中获取子组件的引用,从而可以直接操作子组件的方法和属性。

下面是一个具体的示例,说明如何通过`ref`属性在父组件中获取子组件的引用:

子组件:

<template>
  <div>
    <h2>Child Component</h2>
    <p>Child message: {
    
    { message }}</p>
    <button @click="updateMessage">Update Message</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello from child'
    }
  },
  methods: {
    updateMessage() {
      this.message = 'Updated message from child';
    }
  }
}
</script>

父组件:

<template>
  <div>
    <h2>Parent Component</h2>
    <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() {
      this.$refs.child.updateMessage();
    }
  }
}
</script>

在子组件中,我们定义了一个数据属性`message`,并在模板中显示该属性的值。还有一个方法`updateMessage`,当点击按钮时,更新`message`的值。

在父组件中,我们将子组件标识为`ref="child"`以通过`$refs`属性获取子组件的引用。在`callChildMethod`方法中,我们通过`this.$refs.child`访问子组件的实例,并调用其`updateMessage`方法来更新子组件的数据。

通过这样的设置,父组件可以直接操作子组件的方法和属性,实现父子组件之间的通信。

需要注意的是,`ref`属性只能用于引用子组件实例。如果要引用DOM元素,可以使用`ref`属性和`$refs`来获取DOM元素的引用。

7. Event Bus:使用一个中央事件总线来进行组件间的通信,即创建一个用于事件通信的空的Vue实例作为中央事件总线

在Vue中,Event Bus是一种通过创建一个空的Vue实例作为中央事件总线来实现组件间通信的方式。通过这个中央事件总线,不同组件可以通过事件的方式互相通信。

下面是一个使用Event Bus实现组件间通信的示例:

// Event Bus.js

import Vue from 'vue'

// 创建一个空的Vue实例作为中央事件总线
const bus = new Vue()

export default bus

在这个示例中,我们创建了一个名为Event Bus的文件,其中实例化一个空的Vue实例,并将其导出。

现在让我们在两个组件中使用Event Bus进行通信。

组件A:

<template>
  <div>
    <h2>Component A</h2>
    <button @click="sendMessage">Send Message</button>
  </div>
</template>

<script>
import Eventbus from './EventBus.js'

export default {
  methods: {
    sendMessage() {
      // 通过Event Bus发送一个事件
      Eventbus.$emit('message', 'Hello from Component A')
    }
  }
}
</script>

组件B:

<template>
  <div>
    <h2>Component B</h2>
    <p>Received Message: {
    
    { receivedMessage }}</p>
  </div>
</template>

<script>
import Eventbus from './EventBus.js'

export default {
  data() {
    return {
      receivedMessage: ''
    }
  },
  created() {
    // 通过Event Bus监听事件
    Eventbus.$on('message', message => {
      this.receivedMessage = message
    })
  }
}
</script>

在组件A中,我们导入Event Bus,并在`sendMessage`方法中使用`Eventbus.$emit`来发送一个名为`message`的事件,并传递一个消息。

在组件B中,我们也导入Event Bus,并在`created`生命周期钩子中使用`Eventbus.$on`来监听`message`事件,并更新`receivedMessage`数据。

通过这样的设置,组件A可以通过Event Bus发送一条消息,并且组件B可以通过Event Bus监听到该消息并进行相应的处理。

使用Event Bus进行组件间通信的好处是可以非常灵活地在不同的组件之间进行通信,而不需要显式地传递props或在父子组件之间建立关联。然而,也需要注意,过度使用Event Bus可能会导致组件之间的关系变得复杂,因此在设计组件之间的通信时,需要谨慎使用Event Bus。
 

8.Vuex:使用Vue的状态管理库Vuex来实现组件间的通信,通过共享的状态来进行数据的传递和更新

在Vue中,可以使用Vuex来实现组件间的通信。Vuex是Vue的官方状态管理库,它通过创建一个共享的状态存储,来实现组件之间的数据传递和更新。

下面是一个使用Vuex实现组件间通信的示例:

1. 安装Vuex

首先,需要在项目中安装Vuex。可以使用npm或者yarn来进行安装:

npm install vuex

2. 创建Vuex Store

在项目的根目录下创建一个名为store.js的文件,并在其中定义Vuex Store:

// store.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    message: 'Hello from Vuex'
  },
  mutations: {
    updateMessage(state, newMessage) {
      state.message = newMessage
    }
  }
})

export default store

在这个示例中,我们首先导入Vue和Vuex,并使用Vue的`use`方法来安装Vuex。然后,创建一个新的Vuex Store,其中包含一个名为`message`的状态,并定义一个名为`updateMessage`的mutation,用于更新`message`的值。

3. 在Vue实例中使用Vuex Store

在Vue实例中,我们需要将创建的Vuex Store实例传递给Vue的`store`选项,以便在组件中能够使用Vuex Store的状态和mutations。

// main.js

import Vue from 'vue'
import App from './App.vue'
import store from './store'

new Vue({
  store,
  render: h => h(App),
}).$mount('#app')

在这个示例中,我们将创建的Vuex Store实例传递给Vue实例的`store`选项。

4. 在组件中使用Vuex Store

现在,我们可以在组件中使用Vuex Store来进行数据的传递和更新。

<template>
  <div>
    <h2>Component A</h2>
    <p>Message: {
    
    { message }}</p>
    <button @click="updateMessage">Update Message</button>
  </div>
</template>

<script>
import { mapState, mapMutations } from 'vuex'

export default {
  computed: {
    ...mapState(['message'])
  },
  methods: {
    ...mapMutations(['updateMessage'])
  }
}
</script>

在这个示例中,我们使用`mapState`辅助函数来将Vuex Store中的`message`状态映射到组件的`message`计算属性中,并使用`mapMutations`辅助函数将Vuex Store中的`updateMessage` mutation映射到组件的`updateMessage`方法中。

通过这样的设置,我们可以在组件中使用`message`计算属性来获取Vuex Store中的`message`状态,并使用`updateMessage`方法来更新该状态。

需要注意的是,Vuex不仅仅可以用于组件间的通信,还可以用于全局状态的管理。通过Vuex,可以将共享的状态集中存储,并在任何组件中访问和修改。这样可以提高代码的可维护性和扩展性。
 

猜你喜欢

转载自blog.csdn.net/weixin_39273589/article/details/132600439