vue组件之间通信的八种方式: props、$attrs、$root、$parent、$refs、$emit、依赖注入、Vuex

今天看vue的API,看到组件通信这一块,发现通信方式有好多种,但官网上的说明都是一笔带过,而且语句有点拗口,里面又有很多不理解的专有名词,以致于以前看的时候漏掉了很多东西,今天就好好总结一下。

1. props传值
props方式是用得比较多的:

  <div id="app">
    <child :value="msg" :fun="printMsg"></child>
  </div>
  • 1
  • 2
  • 3
  Vue.component('child', {
    props: ['value', 'fun'],
    mounted() {
      this.fun(' 我是在child组件中加入的参数')
    },
    template: `
      <div>{{value}}</div>
    `
  })
  new Vue({
    el: '#app',
    data: {
      msg: '我是app内的msg'
    },
    methods: {
      printMsg(str = '') {
        console.log('msg:', this.msg + str) // msg: 我是app内的msg 我是在child组件中加入的参数
      }
    }
  })
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

上例中根组件向子组件传了两个值,分别是一个字符串和一个方法,在子组件中,传入的值会放到vm实例中,可用this来访问。
传入的方法(不是用箭头函数定义的)在调用时,方法内部的this仍然指向根的Vue实例,并且能获取子组件传递的参数,这样就能方便的在子组件中调用父组件的方法。
特点:

  1. 在子组件调用时给子组件写入的属性,在子组件内用props注册后会添加到子组件的vm实例上;
  2. 在子组件中不能直接修改props传入的值;
  3. 只能是父组件传子组件,不能‘隔代’;

2. $attrs
$attrs是2.4版本添加的内容,目的是解决props在‘隔代’传值时反复注册props属性的问题。

若现在有三个组件grand, parent 和 child,parent是grand的子组件,child是parent的子组件,现在需要grand组件传值到child组件,如果用props来注册的话,不管parent组件需不需要用到这个值,都必须在parent中用props注册,再传给child。

$attrs是一个对象,它的值是组件在调用时写入的属性(不包括style, class以及在子组件中注册的props)。使用$attrs就可以避免过多的注册props:

 <div id="app">
   <parent :value="msg"></parent>
 </div>
  • 1
  • 2
  • 3
  Vue.component('parent', {
    data() {
      return {
        msg: ''
      }
    },
    mounted() {
      console.log('parent', this.$attrs)
    },
    template: `
      <div>
        <child :value="$attrs.value"></child>
      </div>
    `
  })

Vue.component('child', {
props: ['value'],
mounted() {
console.log('child', this.value)
},
template:&lt;div&gt;&lt;/div&gt;
})

new Vue({
el: '#app',
data: {
msg: '我是app内的msg'
},
})

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

上例中parent组件没有注册props,通过$attrs将值传给了child

3. $root
在任何一个组件中,$root都指向根组件实例,即_uid 为0的vue实例,通过vm.$root可以访问到根上的属性和方法

 <div id="app">
	 <child></child>
 </div>
  • 1
  • 2
  • 3
  Vue.component('child', {
    mounted() {
      this.$root.fun('子组件的参数')
    },
    template:`<div></div>`
  })

new Vue({
el: '#app',
data: {
msg: '我是app内的msg'
},
methods: {
fun (str) {
console.log(this.msg + str) // 我是app内的msg 子组件的参数
}
}
})

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

4. $parent和$children
$parent指向父组件实例,在根实例中的值为undefined
$children是一个数组,包含了该组件下的所有子组件

 <div id="app">
	 <child></child>
 </div>
  • 1
  • 2
  • 3
  Vue.component('child', {
    mounted() {
      this.$parent.fun('子组件的参数')
    },
    template:`<div></div>`
  })

new Vue({
el: '#app',
data: {
msg: '我是app内的msg'
},
methods: {
fun (str) {
console.log(this.msg + str) // 我是app内的msg 子组件的参数
}
}
})

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

5. $refs
这个也比较常用,直接上码:

<body>
  <div id="app">
    <child ref="child"></child>
    <div ref="myDiv"></div>
  </div>
</body>
<script>
  Vue.component('child', {
    data () {
      return {
        msg: '我是子组件的msg'
      }
    },
    methods: {
      fun(str) {
        console.log(this.msg + str)
      }
    },
    template: `<div></div>`
  })
  new Vue({
    el: '#app',
    mounted () {
      this.$refs['child'].fun(' 我是父组件的参数') // 我是子组件的msg 我是父组件的参数
      console.log('myDiv',this.$refs['myDiv']) // 这是一个DOM对象
    }
  })
</script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

6. $emit
子传父常用的方法,上码:

<body>
  <div id="app">
    <child @getmsg="fun"></child>
  </div>
</body>
<script>
  Vue.component('child', {
    data () {
      return {
        msg: '我是子组件的msg'
      }
    },
    mounted() {
      this.$emit('getmsg', this.msg)
    },
    template: `<div></div>`
  })
  new Vue({
    el: '#app',
    methods: {
      fun (msg) {
        console.log(msg) // 我是子组件的msg
      }
    },
  })
</script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

7. 依赖注入
使用 $parent 属性无法很好的扩展到更深层级的嵌套组件上。这也是依赖注入的用武之地,它用到了两个新的实例选项:provide 和 inject。
provide 选项允许我们指定我们想要提供给后代组件的数据/方法。
然后在任何后代组件里,我们都可以使用 inject 选项来接收指定的我们想要添加在这个实例上的属性:

<body>
  <div id="app">
    <child></child>
  </div>
</body>
<script>
  Vue.component('child', {
    inject: ['value'],
    mounted() {
      console.log(this.value) // 我是根组件的msg
    },
    template: `<div></div>`
  })
  new Vue({
    el: '#app',
    data: {
      msg: '我是根组件的msg'
    },
    provide() {
      return {
        value: this.msg
      }
    }
  })
</script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

8. Vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式,更多信息请移步官网

出处:https://blog.csdn.net/qq_38513816/article/details/88343911
posted @ 2021-01-28 22:25  十点书屋  阅读(483)  评论(0)    收藏  举报