Vue组件之间的关系与传值方法
Soya / 2020-09-11 / 默认分类 / 阅读量 311

Vue组件之间的关系与传值方法

父子关系

父传子 props

  • 父组件传递子组件 只需要在子组件上绑定一个自定义属性 子组件内使用props接收自定义属性即可
 // 父组件 简写
 // template
    <Son :msg="msg"></Son>
    
// script
     <script>
       components: {
          Son
        },
         data() {
            return {
              msg: "你好啊"
            };
          },
    </script>

// 子组件

 // template
    <h2>这是儿子:{{msg}}</h2>
// script
    <script>
     // 父传子
      props: {
        // 参数
        msg: {
          // 类型
          type: String,
          // 默认值
          default: "儿子",
        },
        /* 
         可以简写成 
         props:['msg']
        */
      },
    </script>

子传父 $emit

  • 子组件传递父组件 需要在子组件内使用 $emit 触发父组件绑定在子组件上的自定义事件
 // 父组件 
 // template
         <h1>儿子给的信息:{{sonMsg}}</h1>
         <!-- 这里自定义一个子组件内 emit 内的自定义事件 用于接收子组件传递的信息 -->
    <Son @sonChange="sonEmit"></Son>
    
// script
     <script>
       components: {
          Son
        },
         data() {
            return {
              sonMsg: ""
            };
          },
          methods: {
            // 默认一个 e 参数,为子组件传递的信息,可以加工处理
            sonEmit(e) {
              this.sonMsg = e;
            }
          }
    </script>

// 子组件

 // template
    <button @click="change">给爸爸的说句话</button>
// script
    <script>
    methods: {
      change(e) {
        // $emit('父组件内的@方法名',传过去的值),第一个参数要和父组件内的自定义事件对应
        this.$emit("sonChange", "回家吃饭了");
      }
    }
    </script>

祖孙关系 provide 和 inject

  • 官方文档内说明 provideinject 主要在开发高阶插件/组件库时使用。并不推荐用于普通应用程序代码中。一般推荐使用Vuex,或者 $bus
 // 爷爷组件 
 // template
         <h1>儿子给的信息:{{sonMsg}}</h1>
         <!-- 这里自定义一个子组件内 emit 内的自定义事件 用于接收子组件传递的信息 -->
    <Son @sonChange="sonEmit"></Son>
    
// script
     <script>
       components: {
          Son
        },
       data() {
         return {
           sonMsg: "",
           grandSonName:'给孙子的名字'
            };
          },
       methods: {
            // 默认一个 e 参数,为子组件传递的信息,可以加工处理
            sonEmit(e) {
              this.sonMsg = e;
            }
          }
       // 爷爷组件使用 provide 函数
       provide() {
          return {
            // 提示:provide 和 inject 绑定并不是可响应的。这是官方说的。
            giveGrandSonSmallName: "GoodBoy",
            
            
            // 如果这里传入了一个可监听的对象,那么其对象的 property 还是可响应的。 这里使用箭头函数,简写,不需要写 return,如果多行的话需要使用 {} 包围,并加上 return 
            giveGrandSonBigName: () => this.grandSonName,
          };
        },
    </script>
// 爸爸组件
 // template
    <button @click="change">给爸爸的说句话</button>
    <Grandson></Grandson>
// script
    <script>
    components: {
      Grandson,
    },
    methods: {
      change(e) {
        // $emit('父组件内的@方法名',传过去的值),第一个参数要和父组件内的自定义事件对应
        this.$emit("sonChange", "回家吃饭了");
      }
    }
    </script>
// 孙子组件

 // template
    <h4>这是爷爷传来的名字:{{getGrandSonName}}</h4>
    <h4>这是爷爷传来的小名:{{giveGrandSonSmallName}}</h4>
// script
    <script>
    // 孙子组件使用 inject 来接收 爷爷组件内用 provide 传递过来的key,
    inject:['giveGrandSonSmallName','giveGrandSonName'],
    
    // giveGrandSonName 是需要可响应的,我们这里可以使用计算属性来监听该属性
    computed: {
      getGrandSonName: function (val) {
      // 因为 giveGrandSonName 是一个函数,所以我们这里需要执行一次,获取到return 的结果
        return this.giveGrandSonName()
      }
    },

    </script>

兄弟关系 一、bus

  • 兄弟组件之间通信我们可以使用 bus , 在使用bus 之前我们需要先配置一下 main.js
  • 我们先创建一个文件 bus.js,个人习惯吧工具类的文件放到一个 utils 文件夹里面

// bus.js
    import Vue from 'vue'
    const Bus = new Vue()
    export default Bus
  • 然后我们在 main.js 中引入我们刚刚创建的 bus.js
// main.js

//  一、先引入Bus 
import Bus from '@/utils/bus'
//  二、在将Bus 绑定在 Vue的prototype上 此后可以直接 this.$bus 来使用
Vue.prototype.$bus = Bus
// 这两行要放在 new Vue 之前
  • 使用3个组件演示
// template
   <Friend></Friend>
     <OtherFriend></OtherFriend>
// Friend.vue

// template
    <button @click="friend">给朋友的消息</button>
// script
    <script>
     data() {
      return {
        friendName: "Soya呦",
      };
    },
    methods: {
        friend() {
          // $bus.$emit('触发方法',传递值) 用于触发传递
          this.$bus.$emit("friendName", this.friendName);
        },
     },
    </script>
// OtherFriend.vue

// template
    <h1>朋友给的:{{name}}</h1>
// script
    <script>
     data() {
      return {
        name: "",
      };
    },
    created() {
      // $bus.$on('触发方法',接收信息)  on 用于监听方法是否被触发,触发后可以获取到传递过来的值
      this.$bus.$on("friendName", (e) => {
        this.name = e;
      });
    },
    </script>

兄弟关系 二、Vuex

  • 借用官方的一句话 Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
  • 这里简单说明一下 Mutation 和 State ,怎么引入和具体更深用法可以上官网文档查看
// store/index.js

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

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    yeName:''
  },
  mutations: {
    // 参数(默认state,传递进来的值)
    giveYeName(state,newName){
      // 操作 state 赋予新的值
      state.yeName = newName
    }
  },
  actions: {
  },
  modules: {
  }
})
  • 借用 bus 中的3个组件
// template
   <Friend></Friend>
     <OtherFriend></OtherFriend>
// Friend.vue

// template
    <h1>朋友给我的名字:{{friendSonName}}</h1>
    <button @click="friend">给朋友的消息</button>
// script
    <script>
     data() {
      return {
        friendName: "Soya呦",
      };
    },
    computed:{
      friendSonName(){
        // 使用 state 获取 Vuex中的 state定义的值,
        return this.$store.state.yeName
      }
    },
    methods: {
        friend() {
          // $bus.$emit('触发方法',传递值) 用于触发传递
          this.$bus.$emit("friendName", this.friendName);
        },
     },
    </script>
// OtherFriend.vue

// template
    <h1>朋友给的:{{name}}</h1>
    <button @click="giveYeName">给朋友起个名字</button>
// script
    <script>
     data() {
      return {
        name: "",
      };
    },
    created() {
      // $bus.$on('触发方法',接收信息)  on 用于监听方法是否被触发,触发后可以获取到传递过来的值
      this.$bus.$on("friendName", (e) => {
        this.name = e;
      });
    },
    methods: {
      giveYeName() {
        // 使用 commit 触发 vuex 中的 mutations 方法 参数 (mutations中的方法名,传递的值)
        this.$store.commit("giveYeName", "朋友儿子给爷爷的名字");
      },
    },
    </script>