vue组件传值-父子(vue3组件传值-父子)

父传子

defineProps

组件传值给子组件主要是由父组件为子组件通过v-bind绑定数值,而后传给子组件;子组件则通过defineProps接收使用
如下为父组件

<template>
  <div class="fa">
    <div style="margin: 10px;">我是父组件</div>
    <Son :fatherMessage="fatherMessage"></Son>
  </div>
</template>

<script setup lang="ts">
import Son from './Son.vue'
import {ref} from "vue";

const fatherMessage = ref<string>("我是父组件传过来的值")

</script>

<style scoped>
.fa{
  border: 3px solid cornflowerblue;
  width: 400px;
  text-align: center;
}
</style>

如下为子组件

<template>
  <div style="margin: 10px;border: 2px solid red">
    我是子组件
    <div style="margin: 5px;border: 2px solid gold">
      父组件传值接收区:{{fatherMessage}}
    </div>
  </div>
</template>

<script setup lang="ts">
interface Props {
  fatherMessage?: string,
}
defineProps<{
  fatherMessage:string
}>()
</script>


  
<template>
  <div style="margin: 10px;border: 2px solid red">
    我是子组件
    <div style="margin: 5px;border: 2px solid gold">
      父组件传值接收区:{{props.fatherMessage}}
    </div>
  </div>
</template>  
<script setup>
// let props = defineProps(["fatherMessage"]);
const props = defineProps({
 fatherMessage:{ 
	type:string,
  default''
}
})
</script>

父组件Father.vue中在调用Son.vue这个子组件时,使用v-bind绑定参数fatherMessage,并传给Son.vue
子组件Son.vue使用defineProps接收fatherMessage这个参数,而后就可以正常使用该参数。

props


<template>
    <div>
        <div>{{msg}}</div>
        <div>{{str}}</div>
    </div>
</template>
<script>
import {computed} from 'vue'
export default {
    props:{
        msg:String
    },
    setup(props){//提供的函数props直接用就完事了嗷~~~
        const str = computed(()=>{
            return '父组件值为:'+ props.msg
        })
        return{
            str
        }
    }
}
</script>
<template>
    <child :msg="msg"></child>
</template>
<script>
import Child from './Child.vue'
import {ref} from 'vue'
export default {
    components:{
        Child
    },
    setup(){
        const msg = ref('I am father value!')
        return{
            msg
        }
    }
}
</script>

子传父

defineEmits

子组件传值给父组件主要是子组件通过defineEmits注册一个自定义事件,而后触发emit去调用该自定义事件,并传递参数给父组件。
在父组件中调用子组件时,通过v-on绑定一个函数,通过该函数获取传过来的值。
如下为子组件

<template>
  <div style="margin: 10px;border: 2px solid red">
    我是子组件
    <button @click="transValue" style="margin: 5px">传值给父组件</button>
  </div>
</template>

<script setup lang="ts">
import { ref, defineEmits } from "vue";

// 定义所要传给父组件的值
const value = ref<String>("我是子组件传给父组件的值")

// 使用defineEmits注册一个自定义事件
const emit = defineEmits(["getValue"])

// 点击事件触发emit,去调用我们注册的自定义事件getValue,并传递value参数至父组件
const transValue = () => {
  emit("getValue", value.value)
}

</script>

如下为父组件

<template>
  <div class="fa">
    <div style="margin: 10px;">我是父组件</div>
    父组件接收子组件传的值:{{sonMessage}}
    <Son @getValue="getSonValue"></Son>
  </div>
</template>

<script setup lang="ts">
import Son from './Son.vue'
import {ref} from "vue";

const sonMessage = ref<string>("")
const getSonValue = (value: string) => {
  sonMessage.value = value
}
</script>

<style scoped>
.fa{
  border: 3px solid cornflowerblue;
  width: 400px;
  text-align: center;
}
</style>

父组件Father.vue中在调用Son.vue这个子组件时,当子组件Son.vue需要传参给父组件Father.vue时,使用defineEmits注册一个事件getValue,而后设置点击事件transValue去触发emit,去调用我们注册的自定义事件getValue,并传递value参数至父组件。

父组件Father.vue在获取子组件Son.vue传过来的值时,通过在子组件上使用v-on设置响应函数getValue(该函数与子组件中的注册自定义事件getValue名称需一致),并绑定一个函数getSonValue来获取传过来的值。

emit


<template>
  <div>
    子组件: <button @click="childEmit">传值给父组件</button>
  </div>
</template>
<script>
export default {
    setup(props,{emit}){ //分解context对象取出emit
        function childEmit(){
            emit('my-emit','我是子组件值')
        }
        return{
            childEmit
        }
    }
};
</script>
<template>
  <div>
    父组件 <child @my-emit="parentEmit"></child>
  </div>
</template>
 
<script>
import Child from "./Child.vue";
import { ref } from "vue";
export default {
  components: {
    Child,
  },
  setup() {
    function parentEmit(val){
        alert(val)
    }
    return{
        parentEmit
    }
  },
};
</script>

子组件暴露属性给父组件 defineExpose

当父组件想直接调用父组件的属性或者方法时,子组件可以使用defineExpose暴露自身的属性或者方法,父组件中使用ref调用子组件暴露的属性或方法。
如下为子组件

<template>
  <div style="margin: 10px;border: 2px solid red">
    我是子组件

  </div>
</template>

<script setup lang="ts">
import {ref, defineExpose} from "vue";

// 暴露给父组件的值
const toFatherValue = ref<string>("我是要暴露给父组件的值")

// 暴露给父组件的方法
const toFatherMethod = () => {
  console.log("我是要暴露给父组件的方法")
}
// 暴露方法和属性给父组件
defineExpose({toFatherMethod, toFatherValue})

</script>

如下为父组件

<template>
  <div class="fa">
    <div style="margin: 10px;">我是父组件</div>
    <button @click="getSonMethod">获取子组件的方法</button>
    <Son ref="sonMethodRef"></Son>
  </div>
</template>

<script setup lang="ts">
import Son from './Son.vue'
import {ref} from "vue";

const sonMethodRef = ref()

const getSonMethod = () => {
  sonMethodRef.value.toFatherMethod()
  console.log(sonMethodRef.value.toFatherValue)
}

</script>

<style scoped>
.fa{
  border: 3px solid cornflowerblue;
  width: 400px;
  text-align: center;
}
</style>

在子组件中定义属性toFatherValue和方法toFatherMethod,而后通过defineExpose暴露出来。
父组件调用时,为子组件绑定一个ref,并定义一个ref变量sonMethodRef,通过调用sonMethodRef,来获取子组件暴露出来的属性和方法。

依赖注入Provide / Inject

从上面的介绍里我们可以了解到父子组件之间的通信,但是却存在这样的情况:有一些多层级嵌套的组件,形成了一颗巨大的组件树,而某个深层的子组件需要一个较远的祖先组件中的部分数据。在这种情况下,如果仅使用 props 则必须将其沿着组件链逐级传递下去,这会非常麻烦:
image.png
虽然这里的 Footer 组件可能根本不关心这些 props,但为了使 DeepChild 能访问到它们,仍然需要定义并向下传递。如果组件链路非常长,可能会影响到更多这条路上的组件。这一问题被称为“prop 逐级透传”,显然是我们希望尽量避免的情况。
provide 和 inject 可以帮助我们解决这一问题。 一个父组件相对于其所有的后代组件,会作为依赖提供者。任何后代的组件树,无论层级有多深,都可以注入由父组件提供给整条链路的依赖。

image.png
如下为父组件

<template>
  <div>
    我是root组件
    <Footer></Footer>
  </div>
</template>

<script setup lang="ts">
import { provide, ref } from 'vue'
import Footer from './Footer.vue'

const toChildValue= ref<string>("我是给所有子组件的值")

// 将toChildValue注入到所有子组件中
provide(/* 注入名 */ 'toChildValue', /* 值 */ toChildValue)

</script>

如下为子组件

<template>
  <div>
    我是footer组件
    <div>
      接收父组件的值:{{getFatherValue}}
    </div>
    <DeepChild></DeepChild>
  </div>
</template>

<script setup lang="ts">
import DeepChild from "./DeepChild.vue"
import {ref,inject,Ref} from "vue";

// 获取父组件提供的值
// 如果没有祖先组件提供 "toChildValue"
// ref("") 会是 "这是默认值"
const getFatherValue = inject<Ref<string>>(/* 注入名 */"toChildValue",/* 默认值 */ ref(""))

如下为孙子组件

<template>
  <div>
    我是deepChild组件
    <div>
      接收爷爷组件的值:{{getGrandFatherValue}}
    </div>
  </div>
</template>

<script setup lang="ts">
import {inject, ref, Ref} from "vue";

// 获取爷爷组件提供的值
// 如果没有爷爷组件提供 "toChildValue"
// value 会是 ""
const getGrandFatherValue = inject<Ref<string>>(/* 注入名 */"toChildValue",/* 默认值 */ ref(""))
</script>

当最顶层的组件Root.vue传值给所有子组件时,使用provide进行注入

provide(/* 注入名 */ 'toChildValue', /* 值 */ toChildValue)
1
而后无论哪个子组件想要获取toChildValue的值,只需使用inject即可

inject<Ref<string>>(/* 注入名 */"toChildValue",/* 默认值 */ ref(""))

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值