Vue 组件传值

一、组件间通信传值的各种方式与场景

1、父组件向子组件(跨级)传值

1.1 父组件通过props给子组件传值
props也可以传函数
image.png
// 父组件vue文件
<template>
  <div class="home">
    <!--父组件传msg属性给子组件传值-->
    <child :msg="msg"></child>
  </div>
</template>

<script>
import Child from '@/components/Child'

export default {
  name: 'Father',
  components: {
    Child
  },
  data () {
    return {
      msg: '父组件传给子组件的值'
    }
  },
  methods: {}
}
</script>

// 子组件
<template>
  <div>{{ msg }}</div>
</template>
<script>
export default {
  name: 'Child',
  // 子组件通过props接收父组件的传值
  props: ['msg']
}
</script>
<style scoped>
</style>
1.2 父组件通过$ref给子组件传值

ref 用于给元素或子组件注册引用信息,引用信息将会注册在父组件的 refs 对象上,父组件通过refs对象上,父组件通过ref 获取到在子组件里定义的属性和方法,通过调用方法给子组件传递数据


image.png
// 父组件
<template>
  <div class="home">
    <!--父组件传msg属性给子组件传值-->
    <child ref="child"></child>
  </div>
</template>

<script>
import Child from '@/components/Child'

export default {
  name: 'Father',
  components: {
    Child
  },
  data () {
    return {
      msg: '父组件传给子组件的值'
    }
  },
  mounted () {
    // 父组件通过ref属性调用子组件的方法
    this.$refs.child.getMsg(this.msg)
  },
  methods: {}
}
</script>
// 子组件
<template>
  <div>{{ msg }}</div>
</template>

<script>
export default {
  name: 'Child',
  data () {
    return {
      msg: ''
    }
  },
  methods: {
    // 子组件获取父组件值的方法
    getMsg (val) {
      this.msg = val
    }
  }
}
</script>

<style scoped>

</style>
1.3 父组件通过$children给子组件传值

children为当前组件的直接子组件,是一个无序的数组,父组件通过 children 访问子组件并传递数据,$ children 并不保证顺序,也不是响应式的,如果能清楚的知道子组件的顺序,可以使用下标来操作对应的子组件

image.png

// 父组件
<template>
  <div class="home">
    <!--父组件传msg属性给子组件传值-->
    <child ref="child"></child>
  </div>
</template>

<script>
import Child from '@/components/Child'

export default {
  name: 'Father',
  components: {
    Child
  },
  data () {
    return {
      msg: '父组件传给子组件的值'
    }
  },
  mounted () {
    // 父组件通过$children[0]访问对应子组件
    this.$children[0].msg = this.msg
  },
  methods: {}
}
</script>
// 子组件
<template>
  <div>{{ msg }}</div>
</template>

<script>
export default {
  name: 'Child',
  data () {
    return {
      msg: ''
    }
  }
}
</script>

<style scoped>

</style>
1.4 父组件通过provide/inject给子孙组件传值

provide/inject 组合以允许一个祖先组件向其所有子孙后代组件注入一个依赖(属性和方法),不论组件层次有多深,并在其上下游关系成立的时间里始终生效,从而实现跨级父子组件通信,主要在开发高阶插件/组件库时使用


image.png
// 父组件
<template>
  <div class="home">
    <child></child>
  </div>
</template>

<script>
import Child from '@/components/Child'

export default {
  name: 'Father',
  components: {
    Child
  },
  data () {
    return {}
  },
  // 父组件通过provide方法向子孙组件提供值
  provide () {
    return {
      msg: '父组件传给子组件的值'
    }
  }
}
</script>
// 子组件
<template>
  <div>{{ msg }}</div>
</template>

<script>
export default {
  name: 'Child',
  // 子孙组件通过inject注入父组件提供的值
  inject: ['msg'],
  data () {
    return {
    }
  }
}
</script>

<style scoped>
</style>
总结:props$ref$childrenprovide/inject的主要区别:
  • props 侧重于数据的传递,并不能获取子组件里的属性和方法,适用于自定义内容的使用场景
  • $ref侧重于获取子组件里的属性和方法,并不是太适合传递数据,并且 ref 常用于获取dom元素,起到选择器的作用
  • $children 侧重于获取所有的直接子组件,得到的是一个无序的数组,并不太适合向多个子组件传递数据
  • provide/inject 侧重于在开发高阶插件/组件库时使用,并不推荐用于普通应用程序代码中。
1.5 非prop的$attrs?inheritAttrs? 提供封装组件的可扩展性

要求第1个input输入文字,第2个input输入密码

image.png
  • 设置 inheritAttrs: false


    image.png
  • v-bind="$attrs"


    image.png
  • 总结


    image.png
// 子组件
<template>
  <div class="input-con">
    <input v-bind="$attrs" :value="value" @input="$emit('input')">
    $attrs接收非props传递过来的属性:{{$attrs}},所有不包含属性 ’value‘
  </div>
</template>

<script>
export default {
  name: 'Child',
  props: ['value'],
  inheritAttrs: false // 关闭父组件传过来的属性添加到子组件的根元素
}
</script>

<style scoped>
</style>
// 父组件
<template>
  <div class="home">
<!--要求第1个input输入文字-->
<!--   第2个input输入密码-->
    <child v-model="msg" type="text"></child>
    <child v-model="msg" type="password"></child>
  </div>
</template>

<script>
import Child from '@/components/Child'
export default {
  name: 'Father',
  components: {
    Child
  },
  data () {
    return {
      msg: '你好,孩子'
    }
  }
}
</script>
1.6 $listeners

包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件——在创建更高层次的组件时非常有用。

2、子组件向父组件(跨级)传值 $emit(自定义事件名[,...param])

2.1 子组件通过触发$emit事件给父组件传值

$emit的第一个参数为自定义的事件,第二个参数为要传递给父组件的值,父组件在子组件标签上绑定自定义事件来接收子组件传递的数据

image.png

// 子组件
<template>
  <div>
    <button @click="sendMsg"></button>
  </div>
</template>

<script>
export default {
  name: 'Child',
  data () {
    return {
      msg: '子组件传给父组件的值'
    }
  },
  methods: {
    sendMsg () {
      this.$emit('getMsg', this.msg)
    }
  }
}
</script>

<style scoped>

</style>
// 父组件
<template>
  <div class="home">
    <child @getMsg="getData"></child>
    <p>{{msg}}</p>
  </div>
</template>

<script>
import Child from '@/components/Child'

export default {
  name: 'Father',
  components: {
    Child
  },
  data () {
    return {
      msg: ''
    }
  },
  methods: {
    getData (data) {
      this.msg = data
    }
  }
}
</script>
2.2 子组件通过$parent给父组件传值

$parent 可以用来从一个子组件访问父组件并传递数据

image.png

// 子组件
<template>
  <div>
    <button @click="sendMsg"></button>
  </div>
</template>

<script>
export default {
  name: 'Child',
  data () {
    return {
      msg: '子组件传给父组件的值'
    }
  },
  methods: {
    // 子组件通过$parent访问父组件
    sendMsg () {
      this.$parent.msg = this.msg
    }
  }
}
</script>
// 父组件
<template>
  <div class="home">
    <child></child>
    <p>{{msg}}</p>
  </div>
</template>

<script>
import Child from '@/components/Child'

export default {
  name: 'Father',
  components: {
    Child
  },
  data () {
    return {
      msg: ''
    }
  }
}
</script>

3、兄弟组件间通信传值 vm.$emitvm.$on

兄弟之间传值通过eventBus。
eventBus 就是一个vue实例来作为全局的事件总线,兄弟组件之间通过 eventBus. on 和 eventBus.on和eventBus.emit 注册触发事件来传递数据


image.png
// 新建一个vue实例 eventBus.js
import Vue from 'vue'
export default new Vue()
// 父组件
<template>
  <div class="home">
    <child></child>
    <child-two></child-two>
  </div>
</template>

<script>
import Child from '@/components/Child'
import ChildTwo from '@/components/ChildTwo'
export default {
  name: 'Father',
  components: {
    Child,
    ChildTwo
  },
  data () {
    return {
      msg: ''
    }
  }
}
</script>
// 子组件A
<template>
  <div>
    <button @click="sendMsg">子组件A传值给子组件B</button>
  </div>
</template>

<script>
import eventBut from '@/utils/eventBut'
export default {
  name: 'Child',
  data () {
    return {
      msg: '子组件A传给子组件B的值'
    }
  },
  methods: {
    sendMsg () {
      // 子组件A通过eventBus.$emit触发自定义事件给子组件B传值
      eventBut.$emit('getMsg', this.msg)
    }
  }
}
</script>

<style scoped>

</style>
// 子组件B
<template>
  <div>
    {{ msg }}
  </div>
</template>

<script>
import eventBut from '@/utils/eventBut'

export default {
  name: 'ChildTwo',
  data () {
    return {
      msg: ''
    }
  },
  created () {
    this.getData()
  },
  methods: {
    getData () {
      eventBut.$on('getMsg', (data) => {
        this.msg = data
      })
    }
  }
}
</script>

<style scoped>

</style>
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容