Vue常见的几种组件传值方式

组件系统是 Vue.js 其中一个重要的概念,它提供了一种抽象,让我们可以使用独立可复用的小组件来构建大型应用。在 Vue.js 应用程序开发过程中常常需要处理组件传值的问题,下面详细列举几种常见的组件传值方法。

1. props

父组件代码:

<template>

  <child-component title="子组件标题"></child-component> // 传输静态值

  <child-component v-bind:title="title"></child-component> // 传输动态值

</template>

<script>

import ChildComponent from './ChildComponent'

export default {

  components: { ChildComponent },

  data() {

    return {

      title: '子组件标题'

    }

  }

}

</script>


子组件 ChildComponent.vue 代码:

<template>

  <h1>{{title}}</h1>

</template>

<script>

export default {

  props: ['title']

}

</script>

1

2

3

4

5

6

7

8

9

10

所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。

2. vm.$refs

适用于父组件获取子组件的值。

父组件代码:

<template>

  <div>

    <child-component ref="child"></child-component>

    <button @click="getChildProp()">获取子组件的属性的值</button>

    <button @click="getChildMethod()">获取子组件的方法</button>

  </div>

</template>

<script>

import ChildComponent from './components/ChildComponent.vue'

export default {

  components:{ ChildComponent },

  methods: {

    getChildProp () {

      alert(this.$refs.child.msg) // 子组件child的值

    },

    getChildMethod () {

      this.$refs.child.func() // 子组件child的方法

    }

  }

}

</script>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

子组件 ChildComponent.vue 代码:

<template>

<div></div>

</template>

<script>

export default {

  data () {

    return {

      msg: "子组件child的值"

    }

  },

  methods: {

    func () {

      alert("子组件child的方法")

    }

  }

}

</script>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

注意:因为 ref 本身是作为渲染结果被创建的,在初始渲染的时候你不能访问它们 - 它们还不存在!$refs 也不是响应式的,因此你不应该试图用它在模板中做数据绑定。

3. vm.$parent

适用于子组件获取父组件的值。

父组件代码:

<template>

  <child-component></child-component>

</template>

<script>

import ChildComponent from './components/ChildComponent.vue'

export default {

  components:{ ChildComponent },

  data () {

    return {

      title: '标题'

    }

  }

}

</script>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

子组件 ChildComponent.vue 代码:

<script>

export default {

  created () {

    alert(this.$parent.title) // 标题

  }

}

</script>

1

2

3

4

5

6

7

8

4. vm.$emit(eventName, […args])

适用于子组件向父组件传值,子组件可以通过触发父组件事件传递参数。

父组件代码:

<template>

  <child-component v-on:handleClick="handleEvent"></child-component>

</template>

<script>

import ChildComponent from './ChildComponent'

export default {

  components: { ChildComponent },

  methods: {

    handleEvent (value) {

      alert(value) // 'abc'

    }

  }

}

</script>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

子组件 ChildComponent.vue 代码:

<template>

  <button v-on:click="handleClickEvent"></button>

</template>

<script>

export default {

  methods: {

    handleClickEvent () {

      this.$emit('handleClick', 'abc')

    }

  }

}

</script>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

5.vm.emit/vm.$on

适用于父子组件及兄弟组件传值。

通过 $emit 触发当前实例上的事件,并将参数传递给监听器,通过 o n 监 听 当 前 实 例 上 的 自 定 义 事 件 。 下 面 介 绍 通 过 v m . on 监听当前实例上的自定义事件。下面介绍通过 vm.on监听当前实例上的自定义事件。下面介绍通过vm.emit / vm.$on 实现兄弟组件传值:

main.js代码:

import Vue from 'vue'

import App from './App.vue'

var bus = new Vue() // 定义公共实例

export default bus

new Vue({

  render: h => h(App),

}).$mount('#app')

1

2

3

4

5

6

7

8

9

父组件 App.vue 代码:

<template>

  <div>

    <child-one></child-one>

    <child-two></child-two>

  </div>

</template>

<script>

import ChildOne from './components/ChildOne.vue'

import ChildTwo from './components/ChildTwo.vue'

export default {

  components:{ ChildOne, ChildTwo }

}

</script>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

子组件 ChildOne.vue 代码:

<template>

  <button @click="btnClick">点击按钮</button>

</template>

<script>

import bus from '../main.js'

export default {

  methods: {

    btnClick () {

      bus.$emit('getTitle', '标题')

    }

  }

}

</script>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

子组件 ChildTwo.vue 代码:

<template>

  <div></div>

</template>

<script>

import bus from '../main.js'

export default {

  mounted () {

    bus.$on('getTitle', (value) => {

      alert(value) // 标题

    })

  }

}

</script>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

注意: vm.e m i t / v m . emit / vm.emit/vm.on 自定义事件必须是在一个公共的实例上才能触发。

6. provide / inject

适用于祖先组件向其所有子孙后代组件传值。

祖先组件通过 provide 定义变量后,无论组件层次有多深,它的子孙后代组件都能够通过 inject 获取变量值。

父组件代码:

<template>

  <child></child>

</template>

<script>

import Child from './Child.vue'

export default {

  provide: { title: "标题" },

  components:{ Child }

}

</script>

1

2

3

4

5

6

7

8

9

10

11

12

子组件 Child.vue 代码:

<template>

  <div>

    {{title}} // 标题

    <grandson></grandson>

  </div>

</template>

<script>

import Grandson from './Grandson.vue'

export default {

  inject: ['title'],

  components:{ Grandson }

}

</script>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

子组件的子组件 Grandson.vue 代码:

<template>

  <div>{{title}}</div> // 标题

</template>

<script>

export default {

  inject: ['title']

}

</script>

1

2

3

4

5

6

7

8

9

10

注意:provide 和 inject 主要为高阶插件/组件库提供用例。并不推荐直接用于应用程序代码中。

7. 路由

通过路由地址参数传值,适用于组件路由切换场景

路由传参的方式有多种,详细信息可以查看 Vue Router 官网,下面简单介绍一种:

跳转前的组件相关代码:

this.$router.push({

  path: '/App',

  query: {

    title: '标题'

  }

})

1

2

3

4

5

6

7

对应路由相关配置:

{

  path: '/app',

  name: 'App',

  component: App

1

2

3

4

5

跳转后组件调用方法:

this.$route.query.title // 标题

1

2

注意:避免敏感数据通过路由地址传参显示在页面url后面。

8. localStorage / sessionStorage

适用于组件间任意传值,常用于存储客户端临时信息。

localStorage 生命周期是永久的,可以实现同一浏览器下不同窗口传值。而 sessionStorage 的生命周期为当前窗口或标签页,一旦窗口或标签页关闭,通过 sessionStorage 存储的信息则会被清空。以 localStorage 为例:

组件存储信息调用方法:

var obj = {'title': '标题'}

localStorage.setItem('info', JSON.stringify(obj));

1

2

3

组件获取信息调用方法:

var info = JSON.parse(localStorage.getItem('info')) // {'title': '标题'}

1

2

9. Vuex

适用于组件间任意传值,常用于开发大型页面应用中。

Vuex 是专为 Vue.js 应用程序开发的状态管理器,可以简单理解为一个全局变量,在 Vuex 中定义的变量可以被各个组件使用。但是我们不能像传统 JS 的那种直接赋值形式来修改,我们必须得按照 Vuex 给我们提供的规则来修改。

————————————————

版权声明:本文为CSDN博主「姜天生i」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/qq_37041819/article/details/105550147

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

推荐阅读更多精彩内容