- 父组件可以改变子组件的值,而子组件不能直接改变父组件的值!!
1.父组件->子组件 (用props)
父组件 html部分
<div class="component-study">
<h1 style="margin-bottom: 30px">component-study</h1>
<test-one :one="oneValue"></test-one><!--这里往one组件传了one参数-->
<test-two :two="twoValue"></test-two><!--这里往two组件传了two参数-->
</div>
父组件 js部分
import testOne from "../template/test-1.vue"//引入子组件one
import testTwo from "../template/test-2.vue"//引入子组件two
export default {
name: 'component-study',
data(){
return {
oneValue:'one',//传到组件one的值
twoValue:'two'//传到组件two的值
}
},
components:{
"test-one":testOne,
"test-two":testTwo
}
}
子组件 html部分
<template>
<div class="test-1">
<div class="title">组件1获取父组件的值:</div>
<div>{{one}}</div>
</div>
</template>
子组件 js部分
export default {
name: '',
props:['one'],//子组件用props接收到了父组件one参数
data(){
return {
}
},
created(){
console.log(this.one);//one 这就是父组件传的值
}
}
2.子组件->父组件 (用emit)
个人认为:子组件先声明一个方法,然后传值到父组件,父组件然后利用这个方法来获取这个值
子组件 js部分
export default {
name: '',
props:['one'],
data(){
return {
sendData:'one',
}
},
created(){
this.$emit('getOneDataName',this.sendData);//利用$emit来传值,getOneDataName是方法名,this.sendData是传的值
}
}
父组件 html部分
<template>
<div class="component-study">
<h1 style="margin-bottom: 30px">component-study</h1>
<test-one @getOneDataName="getOneData" :one="oneValue"></test-one>
<!--@getOneDataName是子组件声明的方法,记住getOneData没有括号,根据这个方法来获取值-->
</div>
</template>
父组件 js部分
export default {
name: 'component-study',
data(){
return {
oneValue:'one',
twoValue:'two'
}
},
components:{
"test-one":testOne,
"test-two":testTwo
},
methods:{
getOneData(data){//这是子组件声明的方法,这个data就是子组件传过来的值
console.log(25,data);//one
}
},
created(){
//this.getOneData;
}
}
3.组件(无需关心层级)利用eventBus
- 除了传参,还可以响应方法。
3-1 先在src目录下新建一个 eventBus.js (其实就是一个vue对象)
import Vue from 'vue'
let eventBus = new Vue()
export default eventBus
/*export default{
eventBus:new Vue()
}*/
组件A js部分
import eventBus from '../assets/js/eventBus'//引入刚刚写的组件
//利用eventBus $emit注册 一个方法
eventBus.$emit('testFn','666');//第一个参数是方法名,第二个参数是值
组件B js部分
import eventBus from '../assets/js/eventBus'//引入刚刚写的组件
//利用eventBus $on获取刚刚注册的方法
eventBus.$on('testFn',(data)=>{
console.log(data)//data的值是666
});
注意点:如果$on多次触发
- 在
beforeDestroy内销毁下
beforeDestroy () {
eventBus.$off('testFn')
},
子组件->父组件 (v-slot)
父组件触发子组件的方法
方法1
- 父组件
html
<button @click = "fatherFn">点击触发子组件方法</button>
<testComponents ref="testComponent">
</testComponents>
js
methods:{
fatherFn(){
this.$refs.testComponent.$emit('fnTest') //向子组件传递了fnTest方法
},
}
- 子组件
js
mounted(){
this.$on('fnTest', () => {
console.log('我触发了父组件的事件')
})
}
方法2,这个更简单
- 父组件
html
<button @click = "fatherFn">点击触发子组件方法</button>
<testComponents ref="testComponent">
</testComponents>
js
methods:{
fatherFn(){
this.$refs.testComponent.childFn() //直接触发子组件方法
},
}
- 子组件
js
methods: {
childFn() {
console.log('我是子组件方法')
}
}
3、爷爷孙子组件传值$attr
vue3 中的传递
A-非单文件组件传递
1、父传子
- 跟vue2相比差不多,利用props传参
- 父html
<template>
<div class="father-com">
father
<childCom :fatherValue="fatherValue"></childCom>
</div>
</template>
- 父js
<script>
import childCom from './childCom'
export default {
components: {childCom},
setup(){
const fatherValue = '我是父组件的值'
return {
fatherValue,
}
}
}
</script>
- 子组件接收js
<script>
export default {
props: ['fatherValue'],
setup(props, { emit }){
console.log(10, props.fatherValue) //获取到父元素的值
}
}
</script>
2、子元素事件触发父元素emit, 跟vue2差不多
- 子html
<template>
<div class="child-com">
child
<button @click="childClick">click</button>
</div>
</template>
- 子js
<script>
export default {
props: ['fatherValue'],
setup(props, { emit }){
console.log(10, props.fatherValue)
const childClick = ()=>{
//向外部抛出
emit('childClick', '我是子组件的值')
}
return {
childClick
}
}
}
</script>
- 父html
<childCom :fatherValue="fatherValue"
@childClick="childClick"
></childCom>
- 父js
setup(){
const fatherValue = '我是父组件的值'
// eslint-disable-next-line no-unused-vars
const childClick = (childValue)=>{ //响应子组件事件
console.log(18, childValue)
}
return {
fatherValue,
childClick
}
}
3、父组件触发子组件事件
- 获取子元素实例, 直接触发方法
- 父组件代码
//html
<childCom :fatherValue="fatherValue"
@childClick="childClick"
ref="childRef"
></childCom>
//js
const childRef = ref(null)
childRef.value.childFn()
B-单文件组件传递
1、父传子
- 子组件
<script setup>
import {defineProps} from 'vue'
const props = defineProps(['fatherValue'])
console.log(11, props.fatherValue)
const childClick = ()=>{
}
</script>
2、父触发子组件事件
- 子元素一定要暴露方法出去,不然访问不到。。
- 父组件
const childRef = ref(null)
const fatherClick = ()=> {
console.log(20, childRef)
childRef.value.childFn()
}
- 子组件
import {defineProps, defineExpose} from 'vue'
const childFn = ()=>{
console.log('我是子组件的方法')
}
//暴露出去。。。
defineExpose({
childFn
})
3、子组件事件触发父组件事件-defineEmits
- 子组件
<div class="child-com">
child
<button @click="childClick">click</button>
</div>
import {defineEmits} from 'vue' // 目前不需要这句了,默认就有
const emit = defineEmits(['refreshFn'])
const childClick = ()=>{
console.log('子组件点击')
emit('refreshFn', true)
}
- 父组件
<childCom :fatherValue="fatherValue"
ref="childRef"
@refreshFn="refreshFn"
></childCom>
<div ref="testDom">test-dom</div>
const refreshFn = (val)=>{
console.log(27, '父组件内响应事件', val)
}