【转】vue的7种常见通信

一、props / $emit

Prop 是你可以在组件上注册的一些自定义特性。当一个值传递给一个 prop 特性的时候,它就变成了那个组件实例的一个属性。和react的props类似。

// Demo父组件
<template>
  <div class="father">
   /** 向子组件传值 */
    <Child :age="age"></Child>
  </div>
</template>

<script>
import Child from './child.vue'
export default {
  name: 'child',
  components: { Child },
  data() {
    return {
      age: 12
    }
  }
}
</script>

// 子组件中使用props
<template>
  <div>
    {{age}}
  </div>
</template>

<script>
export default {
  props: {
    age: {
      type: Number
    }
  }
}
</script>

$emit 触发当前实例上的事件。附加参数都会传给监听器回调。

<template>
  <div @click="callFatherListener">
    {{age}}
  </div>
</template>

<script>
export default {
  props: {
    age: {
      type: Number
    }
  },
  methods: {
    callFatherListener () {
      // 点击时,调用父组件的方法,前提是该方法已被注册
      this.$emit('fatherEvent', 'msg from son')
    }
  }
}
</script>

//  ---父组件中---
<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
<!--    父组件注册这个事件监听器,当被子组件调用后会捕获-->
    <Son :age="1" @fatherEvent="fatherEvent"></Son>
  </div>
</template>
<script>
import Son from './Son'
export default {
  components: {Son},
  name: 'Father',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  },
  methods: {
    fatherEvent (msg) {
      console.log(msg)
    }
  }
}
</script>

二、$parent / $children
指定已创建的实例之父实例,在两者之间建立父子关系。子实例可以用this.$parent访问父实例,子实例被推入父实例的 $children数组中。

<!--父组件中-->
<template>
  <div class="hello">
    <h1 @click="changeSonMsg">点击改变子组件的值</h1>
    <Son></Son>
  </div>
</template>

<script>
import Son from './Son'
export default {
  components: {Son},
  name: 'Father',
  data () {
    return {
      msg: '爸爸的msg'
    }
  },
  methods: {
    changeSonMsg () {
      // 改变子组件的值
      this.$children[0].msg = 'change from father'
      // 调用父组件的方法
      this.$children[0].sonFunc('儿子你给我嘿嘿嘿')
    },
    fatherFunc () {
      console.log('爸爸你也嘿嘿嘿')
    }
  }
}
</script>

<!--子组件中-->
<template>
  <div>
    {{msg}}
    <p @click="callFatherFunc">获取爸爸组件的值为: {{fatherVal}}</p>
  </div>
</template>

<script>
export default {
  data () {
    return {
      msg: 'default msg'
    }
  },
  methods: {
    sonFunc (msg) {
      console.log(msg)
    },
    callFatherFunc () {
     //  调用父组件的方法
      this.$parent.fatherFunc()
    }
  },
  computed: {
    fatherVal () {
      // 通过$parent获取父组件的属性
      return this.$parent.msg
    }
  }
}
</script>

 

要注意边界情况,如在#app上拿$parent得到的是new Vue()的实例,在这实例上再拿$parent得到的是undefined,而在最底层的子组件拿$children是个空数组。也要注意得到$parent$children的值不一样,$children 的值是数组,而$parent是个对象,另外根实例可以通过 $root拿到。
 
三、provide / inject
  • 2.2.0 新增
  • 无论嵌套多深,都能通信
  • provide 选项应该是一个对象或返回一个对象的函数。该对象包含可注入其子孙的属性。
  • inject 选项应该是:
    • 一个字符串数组,或
    • 一个对象,对象的 key 是本地的绑定名


      <!--父组件中--> <template> <div class="hello"> <Son></Son> </div> </template> <script> import Son from './Son' export default { components: {Son}, name: 'Father', provide: { for: 'Father provide msg' } } </script> <!--子组件中--> <template> <div> 父级获取的属性: {{msg}} </div> </template> <script> export default { data () { return { msg: this.for } }, inject: ['for'] } </script>


provide 和inject 主要为高阶插件/组件库提供用例,所以这里有个笔者写的一个高级的例子

四、ref / refs
ref 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例。

<!--子组件中-->
<template>
  <div>
    {{msg}}
  </div>
</template>

<script>
export default {
  data () {
    return {
      msg: 'son\'s msg'
    }
  }
}
</script>

<!--父组件中-->
<template>
  <div class="hello">
    <Son ref="son"></Son>
    <p @click="showSonMsg">点击打印son的msg</p>
  </div>
</template>

<script>
import Son from './Son'
export default {
  components: {Son},
  name: 'Father',
  methods: {
    showSonMsg () {
      console.log(this.$refs.son.msg)
    }
  }
}
</script> 

 

五、eventBus

eventBus又称事件总线,笔者用的很少,具体可以去官网。
vuex加入后,对组件之间的通信有了更加清晰的操作,对于中大型的项目来说,一开始就把vuex的使用计划在内是明智的选择。

六 、vuex

 

组件不允许直接修改属于 store 实例的 state,而应执行 action 来分发 (dispatch) 事件通知 store 去改变,我们最终达成了 Flux 架构。这样约定的好处是,我们能够记录所有 store 中发生的 state 改变 

this.$store.commit('selectMenu',"xxx")
 

总结

父子关系可以用props-$emit,parent-children等,如果是兄弟层级或关联度不高的组件之间的通信,推荐使用vuex。

借用官方的说法,一般简单项目没必要使用vuex,中大型项目复制项目建议使用vuex。

和redux相比,react16.8以后推出hook,借用阮一峰老师的话,'这个api是react的未来'。


七、localstorage和sessionStorage

应该说不单是vue,凡是前端都可以用这种方式通信,跨页面跨层级的。

原文链接:https://www.jianshu.com/p/6c776936083c
posted @ 2020-03-03 23:05  前端小厨-美食博主  阅读(293)  评论(0编辑  收藏  举报