• vue2的组件通信方式


    组件交互/通信/传值

    组件 A 在它的模板中使用了组件 B。它们之间必然需要相互通信:父组件可能要给子组件下发数据,子组件则可能要将它内部发生的事情告知父组件。在 Vue 中,父子组件的关系可以总结为 prop 向下传递,事件向上传递。父组件通过 prop 给子组件下发数据,子组件通过事件给父组件发送消息。

    1.子组件内使用父组件数据  父-子

    1.父组件传递数据给子组件 (可以传递静态属性 动态属性 )

    	<my-com title='' :msg='msg' attr-a=''>

    2.子组件接收并处理数据

    1. {
    2. ​ props:['title','msg','attrA],
    3. ​ template:``
    4. ​ }

    App.vue

    1. <template>
    2. <div id="app">
    3. <Shcool />
    4. <Student name="科大" :age="19" />
    5. </div>
    6. </template>
    7. <script>
    8. import Shcool from "./components/Shcool.vue";
    9. import Student from "./components/Student.vue";
    10. export default {
    11. name: "app",
    12. components: { Shcool, Student },
    13. };
    14. </script>
    15. <style>
    16. #app {
    17. background-color: orange;
    18. padding: 15px;
    19. }
    20. </style>

    Student.vue

    1. <template>
    2. <div id="student">
    3. <h1>学生姓名:{{ name }}</h1>
    4. <h1>学生年龄:{{ age + 1 }}</h1>
    5. </div>
    6. </template>
    7. <script>
    8. export default {
    9. data() {
    10. return {
    11. // studentName: "好学生",
    12. // age: "18",
    13. };
    14. },
    15. props: ["name", "age"],
    16. };
    17. </script>
    18. <style>
    19. #student {
    20. background-color: skyblue;
    21. }
    22. </style>

    2.父组件内使用子组件的数据

    1. 事件发射 自定义事件
    2. 在子组件内发射 在父组件内接受

    子组件发射时机

    1. 1.手动按钮发送
    2. 2.监听子组件内数据变化,然后发射

    2.1 props实现子传父

    1. props传参同props父传子参数类似,具体实现原理是父组件定义函数,并将函数传递给子组件,在子组件中调用,并将自己的数据作为参数传递给父组件的函数。大体可分为四步。
    2. 第一步,在子组件 标签上 上使用v-bind(简写为 :)绑定传递的参数名以及传递的处理函数;
    3. 第二步,在子组件的 script 中 添加 props 属性 ,并将 参数名 接收;
    4. 第三步,在子组件中调用其他函数来触发用 props接收的参数(也就是那个函数)
    5. 第四步,子组件的参数被传递出去

    App.vue

    1. <template>
    2. <div id="app">
    3. <Shcool :getSchoolName="getSchoolName" />
    4. <!-- <Student name="科大" :age="19" /> -->
    5. <Student />
    6. </div>
    7. </template>
    8. <script>
    9. import Shcool from "./components/Shcool.vue";
    10. import Student from "./components/Student.vue";
    11. export default {
    12. name: "app",
    13. components: { Shcool, Student },
    14. methods: {
    15. getSchoolName(name) {
    16. console.log("App收到了学校名:", name);
    17. },
    18. },
    19. };
    20. </script>
    21. <style>
    22. #app {
    23. background-color: orange;
    24. padding: 15px;
    25. }
    26. </style>

    School.vue

    1. <template>
    2. <div id="school">
    3. <h1>学校名称:{{ name }}</h1>
    4. <h1>学校地址:{{ addddress }}</h1>
    5. <button @click="sendSchoolName">把学校名给App</button>
    6. </div>
    7. </template>
    8. <script>
    9. export default {
    10. //在子组件的 script 中 添加 props 属性 ,并将 参数名 接收;
    11. props: ["getSchoolName"],
    12. data() {
    13. return {
    14. name: "科大",
    15. addddress: "上海",
    16. };
    17. },
    18. methods: {
    19. sendSchoolName() {
    20. this.getSchoolName(this.name);
    21. },
    22. },
    23. };
    24. </script>
    25. <style>
    26. #school {
    27. background-color: skyblue;
    28. }
    29. </style>

    2.2 自定义事件实现子向父传递参数

    2.2.1 第一种自定义事件

    1. 靠函数参数传递的方法将数据带给父组件,具体分三步:
    2. 第一步,在子组件 标签上 上使用v-on(简写为 @)绑定自定义的 事件名 以及对应的处理函数,可以类比原生事件 @click=“handle(e)”;
    3. 第二步,在子组件中调用其他函数,使用 this.$emit(‘事件名’,参数) 的方法触发事件;
    4. 第三步,子组件的参数被传递出去

    App.vue

    1. <template>
    2. <div id="app">
    3. <Shcool :getSchoolName="getSchoolName" />
    4. <!-- <Student name="科大" :age="19" /> -->
    5. <Student v-on:lili="getStudentName" />
    6. </div>
    7. </template>
    8. <script>
    9. import Shcool from "./components/Shcool.vue";
    10. import Student from "./components/Student.vue";
    11. export default {
    12. name: "app",
    13. components: { Shcool, Student },
    14. methods: {
    15. getSchoolName(name) {
    16. console.log("App收到了学校名:", name);
    17. },
    18. getStudentName(name) {
    19. console.log("App收到学生名:", name);
    20. },
    21. },
    22. };
    23. </script>
    24. <style>
    25. #app {
    26. background-color: orange;
    27. padding: 15px;
    28. }
    29. </style>

    Student.vue

    1. <template>
    2. <div id="student">
    3. <h1>学生姓名:{{ name }}</h1>
    4. <h1>学生年龄:{{ age }}</h1>
    5. <button @click="sendStudentName">把学生名给App</button>
    6. </div>
    7. </template>
    8. <script>
    9. export default {
    10. data() {
    11. return {
    12. name: "好学生",
    13. age: "18",
    14. };
    15. },
    16. // props: ["name", "age"],
    17. methods: {
    18. sendStudentName() {
    19. this.$emit("lili", this.name);
    20. },
    21. },
    22. };
    23. </script>
    24. <style>
    25. #student {
    26. background-color: skyblue;
    27. }
    28. </style>

    2.2.2 第二种自定义事件

    1. Student组件不需要任何变化
    2. 主要变动有两处,第一处 是子组件标签中 使用ref属性;第二处 是不在methods或者watch中 定义处理函数,而是在生命周期函数中处理。
    3. 这样的好处是更加灵活,自定义事件可以添加其他异步操作,且对子组件绑定多个自定义事件时,也无需考虑太多的逻辑,不断地在 生命周期函数中 使用 $on 来处理即可。
    4. $on 接收两个参数,$on(自定义事件名,函数) 而函数可以用箭头函数来简写操作
    5. 注意:通过this.$refs.xxx.$on('atguigu',回调)绑定自定义事件时,回调要么配置在methods中,要么用箭头函数,否则this指向会出问题!

    App.vue

    1. <template>
    2. <div class="app">
    3. <h1>{{ msg }}h1>
    4. <School :getSchoolName="getSchoolName" />
    5. <hr />
    6. <Student @lili="getStudentName" />
    7. <Student ref="student" />
    8. div>
    9. template>
    10. <script>
    11. import Student from "./components/Student.vue";
    12. import School from "./components/School.vue";
    13. export default {
    14. name: "App",
    15. components: { Student, School },
    16. data() {
    17. return {
    18. msg: "你好啊",
    19. };
    20. },
    21. methods: {
    22. getSchoolName(name) {
    23. console.log("App收到了学校名:", name);
    24. },
    25. getStudentName(name) {
    26. console.log("App收到了学生名:", name);
    27. },
    28. },
    29. mounted() {
    30. this.$refs.student.$on("lili", this.getStudentName);
    31. },
    32. };
    33. script>
    34. <style scoped>
    35. .app {
    36. background-color: gold;
    37. padding: 10px;
    38. }
    39. style>

    3 全局事件总线(GlobalEventBus)

    全局事件总线是一种可以在任意组件间通信的方式,本质上就是一个对象。它必须满足以下条件:

    1. 所有的组件对象都必须能看见他
    2. 这个对象必须能够使用$on$emit$off方法去绑定、触发和解绑事件

    main.js

    1. import Vue from 'vue'
    2. import App from './App.vue'
    3. Vue.config.productionTip = false
    4. new Vue({
    5. el:'#app',
    6. render: h => h(App),
    7. beforeCreate() {
    8. Vue.prototype.$bus = this //安装全局事件总线
    9. }
    10. })

    App.vue

    1. <template>
    2. <div class="app">
    3. <School />
    4. <Student />
    5. </div>
    6. </template>
    7. <script>
    8. import Student from "./components/Student.vue";
    9. import School from "./components/School.vue";
    10. export default {
    11. name: "App",
    12. components: { Student, School },
    13. data() {
    14. return {};
    15. },
    16. };
    17. </script>
    18. <style scoped>
    19. .app {
    20. background-color: rgb(241, 207, 11);
    21. padding: 10px;
    22. }
    23. </style>

    Student.vue

    1. <template>
    2. <div class="student">
    3. <h2>学生姓名:{{ name }}</h2>
    4. <h2>学生性别:{{ sex }}</h2>
    5. <button @click="sendStudentName">把学生名给School组件</button>
    6. </div>
    7. </template>
    8. <script>
    9. export default {
    10. name: "Student",
    11. data() {
    12. return {
    13. name: "好学生",
    14. sex: "男",
    15. };
    16. },
    17. methods: {
    18. sendStudentName() {
    19. this.$bus.$emit("demo", this.name);
    20. },
    21. },
    22. };
    23. </script>
    24. <style scoped>
    25. .student {
    26. background-color: red;
    27. }
    28. </style>

    School.vue

    1. <template>
    2. <div class="dome">
    3. <h2>学校姓名:{{ name }}</h2>
    4. <h2>学校地址:{{ address }}</h2>
    5. </div>
    6. </template>
    7. <script>
    8. export default {
    9. name: "School",
    10. data() {
    11. return {
    12. name: "科大",
    13. address: "北京",
    14. };
    15. },
    16. methods: {
    17. demo(data) {
    18. console.log("我是School组件,收到了数据:", data);
    19. },
    20. },
    21. mounted() {
    22. this.$bus.$on("demo", this.demo);
    23. },
    24. beforeDestroy() {
    25. this.$bus.$off("demo");
    26. },
    27. };
    28. </script>
    29. <style >
    30. .dome {
    31. background-color: skyblue;
    32. }
    33. </style>

    总结:

    全局事件总线(GlobalEventBus):

    1. 一种组件间通信的方式,适用于任意组件间通信
    2. 安装全局事件总线:

    1. new Vue({
    2. ...
    3. beforeCreate() {
    4. Vue.prototype.$bus = this //安装全局事件总线,$bus就是当前应用的vm
    5. },
    6. ...
    7. })

    使用事件总线:

    1. 接收数据:A组件想接收数据,则在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身

    1. export default {
    2. methods(){
    3. demo(data){...}
    4. }
    5. ...
    6. mounted() {
    7. this.$bus.$on('xxx',this.demo)
    8. }
    9. }

    2.提供数据:`this.$bus.$emit('xxx',data)`

    最好在beforeDestroy钩子中,用$off去解绑当前组件所用到的事件

    4  消息的订阅预发布

    School.vue

    1. <template>
    2. <div class="dome">
    3. <h2>学校姓名:{{ name }}</h2>
    4. <h2>学校地址:{{ address }}</h2>
    5. </div>
    6. </template>
    7. <script>
    8. import pubsub from "pubsub-js";
    9. export default {
    10. name: "School",
    11. data() {
    12. return {
    13. name: "科大",
    14. address: "北京",
    15. };
    16. },
    17. methods: {
    18. demo(msgName, data) {
    19. console.log("我是School组件,收到了数据:", data);
    20. },
    21. },
    22. mounted() {
    23. this.pubId = pubsub.subscribe("demo", this.demo); //订阅消息
    24. },
    25. beforeDestroy() {
    26. pubsub.unsubscribe(this.pubId); //取消订阅
    27. },
    28. };
    29. </script>
    30. <style >
    31. .dome {
    32. background-color: skyblue;
    33. }
    34. </style>

    Student.vue

    1. <template>
    2. <div class="student">
    3. <h2>学生姓名:{{ name }}</h2>
    4. <h2>学生性别:{{ sex }}</h2>
    5. <button @click="sendStudentName">把学生名给School组件</button>
    6. </div>
    7. </template>
    8. <script>
    9. import pubsub from "pubsub-js";
    10. export default {
    11. name: "Student",
    12. data() {
    13. return {
    14. name: "好学生",
    15. sex: "男",
    16. };
    17. },
    18. methods: {
    19. sendStudentName() {
    20. // this.$bus.$emit("demo", this.name);
    21. pubsub.publish("demo", this.name); //发布消息
    22. },
    23. },
    24. };
    25. </script>
    26. <style scoped>
    27. .student {
    28. background-color: red;
    29. }
    30. </style>

    总结:

    1. 消息订阅与发布(pubsub):
    2. 消息订阅与发布是一种组件间通信的方式,适用于任意组件间通信
    3. 使用步骤:
    4. 安装pubsub:npm i pubsub-js
    5. 引入:import pubsub from 'pubsub-js'

    接收数据:A组件想接收数据,则在A组件中订阅消息,订阅的回调留在A组件自身

    1. export default {
    2. methods(){
    3. demo(data){...}
    4. }
    5. ...
    6. mounted() {
    7. this.pid = pubsub.subscribe('xxx',this.demo)
    8. }
    9. }

    提供数据:pubsub.publish('xxx',data)

    最好在beforeDestroy钩子中,使用pubsub.unsubscribe(pid)取消订阅

  • 相关阅读:
    水工建筑物荷载设计规范的技术关键点
    解读《领域驱动设计 软件核心复杂性应对之道》(二)
    SQL注入——搜索型
    C#中的方法
    原生js小方法的封装
    国庆第五天
    2022.9.6-----leetcode.828
    深入理解与应用CSS clip-path 属性
    信号量全面解析与使用
    初识Java 7-1 多态
  • 原文地址:https://blog.csdn.net/m0_52704461/article/details/133779818