vue 组件相互传值
Part.1 传值几种方式
在写项目时,遇到组件传值问题,特此记录一波~~~
(1) 父传子
(2) 子传父
(2) 兄弟组件传值
Part.2 父传子
顾名思义,就是父组件传值给子组件
子组件:
<template> <div class="hello"> <h1>{{ msg }}</h1> </div> </template> <script> export default { name: "HelloWorld", props: { msg: String } }; </script>
父组件:
<template> <div class="home"> <img alt="Vue logo" src="../assets/logo.png" /> <HelloWorld msg="Welcome to Your Vue.js App" /> </div> </template> <script> import HelloWorld from "@/components/HelloWorld.vue"; export default { name: "home", components: { HelloWorld } }; </script>
效果:
Part.3 子传父
子组件传值给父组件
子组件:
<template> <div class="hello"> <h1 @click="goFather">{{ msg }}</h1> </div> </template> <script> export default { name: "HelloWorld", data() { return{ msg: '我是子组件的值' } }, methods: { goFather() { this.$emit('goFather', this.msg) } } }; </script>
父组件:
<template> <div class="home"> <img alt="Vue logo" src="../assets/logo.png" /> <HelloWorld @goFather="getValue"/> <h1>{{msg}}</h1> </div> </template> <script> import HelloWorld from "@/components/HelloWorld.vue"; export default { name: "home", data() { return { msg: '我现在没值' } }, methods: { getValue(data) { this.msg = data } }, components: { HelloWorld } }; </script>
效果:
点击之前
点击之后
Part.3 兄弟组件传值
我把兄弟组件传值分为两种情况:
1. 通过点击事件触发
2. 窗体加载时就触发
首先创建一个供传值使用的媒介 JS 文件, 例如 a.js
内容如下:
import Vue from 'vue' export default new Vue
其次,父组件如下
<template> <div id="app"> <div id="nav"> <!-- 兄弟组件 Home & About --> <Home></Home> <About></About> </div> </div> </template> <script> import Home from './views/Home' import About from './views/About' export default { name: "home", components: { Home, About } }; </script>
我们开始第一种情况:点击触发
Home 子组件:
<template> <div class="home"> <h1 @click="goAbout">{{msg}}</h1> </div> </template> <script> import a from '../assets/a' export default { name: "home", data() { return { msg: '我是兄弟组件一' } }, methods: { goAbout: function() { a.$emit('userDefinedEvent',this.msg) } } }; </script>
About 子组件:
<template> <div class="about"> <h1>{{msg}}</h1> <h2>{{msg2}}</h2> </div> </template> <script> import a from '../assets/a' export default { name: "About", data() { return { msg: '我是兄弟组件二', msg2: '默认值' } }, created() { a.$on('userDefinedEvent',(e)=>{ this.msg2 = e }) } }; </script>
效果:
点击之前:
点击之后
OK!再看第二种情况
Home 组件:
<template> <div class="home"> <h1>{{msg}}</h1> </div> </template> <script> import a from '../assets/a' export default { name: "home", data() { return { msg: '我是兄弟组件一' } }, created() { a.$emit('userDefinedEvent',this.msg) } }; </script>
About 组件:
<template> <div class="about"> <h1>{{msg}}</h1> <h2>{{msg2}}</h2> </div> </template> <script> import a from '../assets/a' export default { name: "About", data() { return { msg: '我是兄弟组件二', msg2: '默认值' } }, created() { a.$on('userDefinedEvent',(e)=>{ this.msg2 = e }) } }; </script>
搞定,运行!
效果:
蛋疼的结果出现了,一直没值,根本没监听到!????
冷静,认真分析
$emit 可以理解为抛出
$on 可以理解为监听
如果我先抛出,再去执行监听!肯定监听不到阿,哇!找到问题所在:我们需要 监听 在 抛出 之前
这里就涉及到 vue 的生命周期和钩子函数,感兴趣的小伙伴可以瞅瞅:https://cn.vuejs.org/v2/guide/instance.html#%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E5%9B%BE%E7%A4%BA
我们看到
About 子组件中:
created() { a.$on('userDefinedEvent',(e)=>{ this.msg2 = e }) }
Home 子组件中:
created() { a.$emit('userDefinedEvent',this.msg) }
我们发现他们的生命周期相同,但是我们需要让 Home 子组件滞后执行
将 Home 子组件 created() 钩子函数修改为 mounted() , 因为 mounted 会在 created 之后执行
mounted() { a.$emit('userDefinedEvent',this.msg) }
效果如下:
搞定!!!~