1.父组件向子组件传值
- 在父组件中引入子组件
- 注册子组件
- 在页面中使用,子组件标签上动态绑定传入动态值/静态值
- 在子组件中,使用
props
来接受父组件
传递过来的值
子组件接收的父组件的值分为引用类型
和普通类型
两种:
- 普通类型: String,Number,Boolean,Null
- 引用类型: Array,Object
#父组件
<template>
<div>
<!-- 传递值 -->
<Test
:obj="obj"
info="测试"/>
</div>
</template>
<script>
// 引入子组件
import Test from "../components/Test.vue";
export default {
name: "about",
// 注册子组件
components: {
Test,
},
data() {
return {
obj: {
name: "whl",
title: "qwe",
},
};
},
};
</script>
<template>
<div>
<h1>{{obj.name}}</h1><br>
<h2>{{obj.title}}</h2>
<h3>{{info}}</h3>
</div>
</template>
<script>
export default {
name:'test',
props:{
obj:Object,
info: [String,Number] //info值为其中一种类型即可,其他类型报警告
}
}
</script>
Vue是单项数据流,子组件不能直接修改父组件的值
2.子组件向父组件传值
- 子组件通过绑定事件,通过this.$emit(‘自定义事件名字’,想传递的参数)
#父组件
<Test
:obj="obj"
info="测试"
@modify="modifyFatherValue"/>
<script>
// 引入子组件
import Test from "../components/Test.vue";
export default {
name: "about",
// 注册子组件
components: {
Test,
},
data() {
return {
msg:'我是父组件'
};
},
methods:{
// 接受子组件传递来的值,赋值给data中的属性
modifyFatherValue(e){
this.msg = e
}
}
};
</script>
# 子组件
<button @click="modifyValue">修改父组件的值</button>
<script>
export default {
name:'test',
methods:{
modifyValue(){
this.$emit('modify','子组件传递过来的值')
}
}
}
</script>
3.父组件通过$refs/$children来获取子组件的值
$refs
:
- 获取dom元素和组件实例来获取组件的属性和方法
- 通过在子组件绑定ref,使用
this.$refs.refName.子组件属性/子组件方法
$children
- 当前实例的子组件,它返回的是一个自组件的集合,如果想获取哪个组件的属性和方法,可以通过
this.$chidren[index].子组件的属性/子组件的方法
$refs
# 子组件
<script>
export default {
name:'test',
data() {
return {
datas:"我是子组件值"
}
},
props:{
obj:Object,
info: [String,Number]
},
methods:{
getValue(){
console.log('我是Test1')
}
}
}
</script>
# 父组件
<template>
<div>
// 给子组件上绑定 ref
<Test
ref="son"
/>
<Test2/>
</div>
</template>
// 通过 $refs 示例来获取 子组件的属性和方法
console.log( this.$refs.son.datas)
this.$refs.son.getValue()
$children
// 通过 $children 来获取 子组件的属性和方法
this.$children[0].getValue(); // 我是 Test1
console.log(`---------${this.$children[1].datas}`); //我是子组件值
4.子组件通过$parent来获取父组件的实例的属性和方法
export default {
data() {
return {
obj: {
name: "whl",
},
};
},
methods: {
getName() {
console.log(this.obj.name);
},
},
};
<script>
export default {
name:'test',
created(){
console.log( this.$parent.obj )
this.$parent.getName()
},
}
</script>
5.$attrs和$listeners获取父组件实例的属性和方法(组件嵌套情况下使用)
$attrs 的作用,某些情况下需要结合 inheritAttrs 一起使用
有 4 个组件:App.vue / child1.vue / child2.vue / child3.vue,这 4 个组件分别的依次嵌套的关系。
// App.vue
<template>
<div id="app">
<p>App.vue</p><hr>
// 这里我们可以看到,app.vue向下一集的child1组件传递了5个参数,分别是name / age / job / sayHi / title
<child1 :name="name" :age="age" :job="job" :say-Hi="say" title="App.vue的title"></child1>
</div>
</template>
<script>
const child1 = () => import("./components/child1.vue");
export default {
name: 'app',
components: { child1 },
data() {
return {
name: "whl",
age: "22",
job: "FE",
say: "this is Hi~"
};
}
};
</script>
// child1.vue
<template>
<div class="child1">
<p>child1.vue</p>
<p>name: {{ name }}</p>
<p>childCom1的$attrs: {{ $attrs }}</p>
<p>可以看到,$attrs这个对象集合中的值 = 所有传值过来的参数 - props中显示定义的参数</p>
<hr>
<child2 v-bind="$attrs"></child2>
</div>
</template>
<script>
const child2 = () => import("./child2.vue");
export default {
components: {
child2
},
// 这个inheritAttrs默认值为true,不定义这个参数值就是true,可手动设置为false
// inheritAttrs的意义在用,可以在从父组件获得参数的子组件根节点上,将所有的$attrs以dom属性的方式显示
inheritAttrs: true, // 可以关闭自动挂载到组件根元素上的没有在props声明的属性
props: {
name: String // name作为props属性绑定
},
created() {
// 这里的$attrs就是所有从父组件传递过来的所有参数 然后 除去props中显式定义的参数后剩下的所有参数!!!
console.log(this.$attrs); // 输出{age: "22", job: "FE", say-Hi: "this is Hi~", title: "App.vue的title"}
}
};
</script>
// child2.vue
<template>
<div class="child2">
<p>child2.vue</p>
<p>age: {{ age }}</p>
<p>childCom2: {{ $attrs }}</p>
<hr>
<child3 v-bind="$attrs"></child3>
</div>
</template>
<script>
const child3 = () => import("./child3.vue");
export default {
components: {
child3
},
// 将inheritAttrs设置为false之后,将关闭自动挂载到组件根元素上的没有在props声明的属性
inheritAttrs: false,
props: {
age: String
},
created() {
// 同理和上面一样,$attrs这个对象集合中的值 = 所有传值过来的参数 - props中显示定义的参数
console.log(this.$attrs);
}
};
</script>
// child3.vue
<template>
<div class="child3">
<p>child3.vue</p>
<p>job: {{job}}</p>
<p>title: {{title}}</p>
<p>childCom3: {{ $attrs }}</p>
</div>
</template>
<script>
export default {
inheritAttrs: true,
props: {
job: String,
title: String
}
};
</script>
具体的显示效果
将inheritAttrs设置为false后,组件根元素上不会显示没有在props声明的属性
$listeners
三个依次嵌套的组件A,B,C
# 组件A
<template>
<div class="child1">
<child2 v-on:receive="reciveMessage"></child2>
</div>
</template>
<script>
const child2 = () => import("./child2.vue");
export default {
components: {
child2
},
methods: {
reciveMessage() {
console.log("reciveMessage success");
}
}
};
</script>
# 组件B
<template>
<div class="child2">
<child3 v-bind="$attrs" v-on="$listeners"></child3>
</div>
</template>
<script>
const child3 = () => import("./child3.vue");
export default {
components: {
child3
}
};
</script>
# 组件C
<template>
<div class="child3">
<p @click="startReceive">child3</p>
</div>
</template>
<script>
export default {
methods: {
startReceive() {
this.$emit("receive");
console.log("startReceive");
}
}
};
</script>
这里的结果是,当我们点击C组件的 child3 文字,触发 startReceive 事件,A组件就可以接收到,并触发 recive打印结果如下:
reciveMessage success"
startReceive
6.跨组件之间的传递EventBus
- 通过新建一个 js 文件,导入 vue , 导出 vue 实例; 然后通过 给导出的实例 上绑定事件 $emit 事件 , 然后再通过 $on 监听触发的事件,这样就可以达到全局组件数据共享。
- 它可以满足任意场景传递数据,
父子
组件传值 ,子父
传值 ,兄弟
组件之间传值 ,跨级
组件之间传值 .
// Vue.js
import Vue from 'vue'
export default new Vue()
// 组件A
<template>
<div>
<button @click="changeValue">改变</button>
</div>
</template>
<script>
import whlVue from '../util/vue.js';
export default {
name:'A',
data(){
return {
title:'whl',
status: false
}
},
methods:{
changeValue(){
// 通过给 vue实例绑定事件
whlVue.$emit("getTitle", this.title)
}
}
}
</script>
// 组件B
<template>
<div>
<h1>B组件</h1>
<h1>{{ title }}</h1>
</div>
</template>
<script>
import whlVue from "../util/vue.js";
export default {
name: "B",
data() {
return {
title: "dataB",
};
},
mounted(){
// 通过 vue 实例.$on 监听事件名,来接收跨级组件传递过来的值
whlVue.$on("getTitle", (data) => {
this.title = data;
console.log(data)
});
}
};
</script>
7.Vuex之后会补充
8.provide和inject实现父组件向子孙组件传值(不限层级)
provide
和inject
这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,在关系成立的时间里始终生效。provide/inject
可以轻松实现跨级访问父组件的数据
provide
- 是一个对象或者返回一个对象的函数
- 包含可注入其子孙组件的属性
inject
- 是一个字符串数组或者是一个对象
- 在子组件或者子孙组件中注入
provide
提供的父组件属性
//对象
provide:{
name:'whl'
}
//返回对象的函数
provide(){
return {
name: 'whl'
}
}
#inject
inject:['name']
# 父组件
<template>
<div>
<h1>我是父组件</h1>
<Son />
</div>
</template>
<script>
import Son from '../components/son/SonOne'
export default {
name:'father',
provide(){
return {
fatherName: 'whl'
}
},
components:{
Son
},
data(){
return{
title:'我是父组件 '
}
},
}
</script>
# 子组件
<template>
<div>
<h1>我是子组件</h1>
</div>
</template>
<script>
import SonTwo from '../son/SonTwo'
export default {
name:'sonone',
components:{
SonTwo
},
inject:['fatherName'],
created(){
console.log(`${this.fatherName}-----------SonTwo`)
},
data(){
return{
title:'我是子组件 '
}
},
}
</script>
# 子孙组件
<template>
<div>
<h1>我是子孙组件</h1>
</div>
</template>
<script>
import SonTwo from '../son/SonTwo'
export default {
name:'sonone',
components:{
SonTwo
},
inject:['fatherName'],
created(){
console.log(`${this.fatherName}-----------SonTwo`)
},
data(){
return{
title:'我是子孙组件 '
}
},
}
</script>
总结:
父子通信:
props/$emit
$parent/$children
$attrs/$listeners
provide/inject
ref
跨级通信
$attrs/$listeners
provide/inject
兄弟通信
使用vuex