开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第3天,点击查看活动详情
父->子
1-props
- 子组件接收到数据之后,不能直接修改父组件的数据。
<template>
<div>
<Child :msg="msg" :name="name"></Child>
</div>
</template>
<script>
import Child from './Child.vue'
export default {
components: {
Child
},
data() {
return {
msg: '父组件',
name: 'Father'
}
},
}
</script>
<template>
<div>
<div>{{msg}}</div>
<div>{{name}}</div>
</div>
</template>
<script>
export default {
data() {
return {
}
},
props: ['msg', 'name']
}
</script>
- 这里的prop是只读属性,可以传递数组也可以传递对象,如果是传递对象形式的:
props: {
msg: Number,
name: {
type: String, // 数据类型
default: 'Hello', // 默认值
required: true, // 是否必填
validator: function (value) { // 自定义校验
return value.length > 3
}
},
obj: {
type: Object,
default: ()=> {}
},
arr: {
type: Array,
default: ()=> []
}
}
2-.sync
<template>
<div>
<Child :msg.sync="msg"></Child>
</div>
</template>
<script>
import Child from './Child.vue'
export default {
components: {
Child
},
data() {
return {
msg: '父组件',
}
},
}
</script>
<template>
<div>
<div>{{msg}}</div>
<button @click="changeMsg">changeMsg</button>
</div>
</template>
<script>
export default {
props: ['msg'],
methods: {
changeMsg() {
this.$emit("update:msg", '子组件')
}
},
}
</script>
3-v-model
<template>
<div>
<Child v-model="msg"></Child>
</div>
</template>
<script>
import Child from './Child.vue'
export default {
components: {
Child
},
data() {
return {
msg: '父组件',
}
},
}
</script>
<template>
<div>
<div>{{msg}}</div>
<button @click="changeMsg">changeMsg</button>
</div>
</template>
<script>
export default {
props: ['msg'],
model:{
prop:'msg',
event:"updateValue"
},
methods: {
changeMsg() {
this.$emit("updateValue", '子组件')
}
},
}
</script>
4-ref
- ref 如果在普通的DOM元素上,引用指向的就是该DOM元素; 如果在子组件上,引用的指向就是子组件实例;
- 父组件可以通过 ref 主动获取子组件的属性或者调用子组件的方法
<template>
<div>
<button @click="transfer">向子组件传值</button>
<hr>
<Child ref="child"></Child>
</div>
</template>
<script>
import Child from './Child.vue'
export default {
components: {
Child
},
methods: {
transfer() {
this.$refs.child.msg = '我是父组件'
this.$refs.child.countAdd(5)
}
},
}
</script>
<template>
<div>
<div>{{count}}</div>
<div>{{msg}}</div>
</div>
</template>
<script>
export default {
data() {
return {
count: 0,
msg: '我是子组件'
}
},
methods: {
countAdd(val) {
this.count += val
}
},
}
</script>
子->父
5-$emit
<template>
<div>
<div>{{msg}}</div>
<hr>
<Child @getMsg="getMsg"></Child>
</div>
</template>
<script>
import Child from './Child.vue'
export default {
components: {
Child
},
data() {
return {
msg: '我是父组件'
}
},
methods: {
getMsg(val) {
this.msg = val
}
},
}
</script>
<template>
<div>
<div>{{msg}}</div>
<button @click="transfer">transfer</button>
</div>
</template>
<script>
export default {
data() {
return {
msg: '我是子组件'
}
},
methods: {
transfer() {
this.$emit('getMsg', this.msg)
}
},
}
</script>
6-slot
<template>
<div>
<div>{{title}}</div>
<hr>
<Child>
<template v-slot:test1="slotProps">
<div>在父组件渲染子组件的值 {{slotProps.obj.msg}}</div>
</template>
<template v-slot:test2="slotProps">
<div>在父组件渲染子组件的值 {{slotProps.obj.msg}}</div>
</template>
</Child>
</div>
</template>
<script>
import Child from './Child.vue'
export default {
components: {
Child
},
data() {
return {
title: '我是父组件'
}
},
}
</script>
<template>
<div>
<slot name="test1" :obj="obj"></slot>
<slot name="test2" :obj="obj2"></slot>
</div>
</template>
<script>
export default {
data() {
return {
obj: {
msg: '我是子组件'
},
obj2: {
msg: '我是子组件2'
}
}
},
}
</script>
父->子/孙
7-$attrs / $listeners
- $attrs获取 父传子中未在 props 定义 的值
- 父组件的方法 可以通过 v-on="$listeners" 传入内部组件
其实listeners相当于是一个中转,主要用在父亲组件上。爷组件和孙组件保持以前的使用即可!
<template>
<div>
<div>{{title}}</div>
<hr>
<Child :title="title" :msg="title" @changeTitle="changeTitle"></Child>
</div>
</template>
<script>
import Child from './Child.vue'
export default {
components: {
Child
},
data() {
return {
title: '我是父组件'
}
},
methods: {
changeTitle() {
this.title = '新 标题'
}
},
}
</script>
<template>
<div>
<div>{{msg}}</div>
<button @click="getFather">getFather</button>
<Sun v-bind="$attrs" v-on="$listeners"></Sun>
</div>
</template>
<script>
import Sun from './Sun.vue'
export default {
components: {
Sun
},
// props: ['title'], // 这里可以接收,也可以不接收(Sun.vue 同理)
data() {
return {
msg: '我是子组件'
}
},
methods: {
getFather() {
console.log(this.$attrs); // 如果props接收了title 就是 { msg: "我是父组件" },否则就是 { title: "我是父组件", msg: "我是父组件" }
this.msg = this.$attrs.msg
this.$listeners.changeTitle()
}
},
}
</script>
<template>
<div>
<hr>
<div>{{msg}}</div>
<button @click="getFather">getFather</button>
</div>
</template>
<script>
export default {
data() {
return {
msg: '我是孙组件'
}
},
// props: ['title'], // 这里可以接收,也可以不接收
methods: {
getFather() {
console.log(this.$attrs);
console.log(this.$listeners);
this.$listeners.changeTitle()
}
},
}
</script>
8-provide / inject
- provide / inject 是依赖注入,在一些插件或组件库里被常用
- provide:可以让我们指定想要提供给后代组件的数据或方法
- inject:在任何后代组件中接收想要添加在这个组件上的数据或方法,不管组件嵌套多深都可以直接拿来用
- 要注意的是 provide 和 inject 传递的数据不是响应式的
<template>
<div>
<div>{{title}}</div>
<hr>
<Child></Child>
</div>
</template>
<script>
import Child from './Child.vue'
export default {
components: {
Child
},
data() {
return {
title: '我是父组件'
}
},
provide() {
return {
title: this.title,
changeTitle: this.changeTitle
}
},
methods: {
changeTitle() {
this.title = '新 标题'
},
},
}
</script>
<template>
<div>
<div>{{msg}}</div>
<button @click="getFather">getFather</button>
</div>
</template>
<script>
export default {
data() {
return {
msg: '我是子组件'
}
},
inject: ["title", "changeTitle"],
methods: {
getFather() {
console.log(this.title)
this.changeTitle()
}
},
}
</script>
父 <-->子
9-$children / $parent
- $children:获取到一个包含所有子组件(不包含孙子组件)的 VueComponent 对象数组,可以直接拿到子组件中所有数据和方法等
- $parent:获取到一个父节点的 VueComponent 对象,同样包含父节点中所有数据和方法等
<template>
<div>
<div>{{title}}</div>
<button @click="getChild">getChild</button>
<hr>
<Child :title="title"></Child>
</div>
</template>
<script>
import Child from './Child.vue'
export default {
components: {
Child
},
data() {
return {
title: '我是父组件'
}
},
methods: {
changeTitle() {
this.title = '新 标题'
},
getChild() {
this.$children[0].changeMsg() // 调用第一个子组件的方法
this.title = this.$children[0].msg // 获取第一个子组件中的属性
}
},
}
</script>
<template>
<div>
<div>{{msg}}</div>
<button @click="getFather">getFather</button>
</div>
</template>
<script>
export default {
data() {
return {
msg: '我是子组件'
}
},
methods: {
changeMsg() {
this.msg = '新 子组件标题'
},
getFather() {
this.$parent.changeTitle() // 调用父组件的方法
this.msg = this.$parent.title // 获取父组件中的属性
}
},
}
</script>
others
10-EventBus
- EventBus 是中央事件总线,不管是父子组件,兄弟组件,跨层级组件等都可以使用它完成通信操作
- 抽离成一个单独的 js 文件 Bus.js ,然后在需要的地方引入
import Vue from "vue"
export default new Vue()
<template>
<div>
<div>{{title}}</div>
<button @click="handlerClick">发消息</button>
<hr>
<Child></Child>
</div>
</template>
<script>
import Child from './Child.vue'
import Bus from "../utils/Bus.js"
export default {
components: {
Child
},
data() {
return {
title: '我是父组件'
}
},
methods: {
handlerClick() {
// 自定义事件名 sendMsg
Bus.$emit("sendMsg", "父组件发消息")
}
},
}
</script>
<template>
<div>
<div>{{msg}}</div>
</div>
</template>
<script>
import Bus from "../utils/Bus.js"
export default {
data() {
return {
msg: '我是子组件'
}
},
mounted() {
// 监听事件的触发
Bus.$on("sendMsg", data => {
this.msg += data
})
},
beforeDestroy() {
// 取消监听
Bus.$off("sendMsg")
}
}
</script>
11-Vuex
Vuex
12-$root
- 访问根组件中的属性或方法 $root只对根组件有用
- 当前组件树的根组件实例。如果当前实例没有父组件,那么这个值就是它自己。
this.$root.xxx