欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 产业 > Vue3.0组件之间通信(defineProps 和 defineEmits 及 defineExpose)

Vue3.0组件之间通信(defineProps 和 defineEmits 及 defineExpose)

2024/11/30 6:38:19 来源:https://blog.csdn.net/liming1016/article/details/144079723  浏览:    关键词:Vue3.0组件之间通信(defineProps 和 defineEmits 及 defineExpose)

前言:

  • 一、父传子 defineProps
  • 二、子传父 defineEmits
  • 三、子组件暴露属性和方法给父组件 defineExpose
  • 四、依赖注入Provide / Inject

在 <script setup> 中必须使用 defineProps 和 defineEmits API 来声明 props 和 emits ,它们具备完整的类型推断并且在 <script setup> 中是直接可用的。

<template> <!-- 在模板中直接使用 props 中声明的变量 --> <h1>{{ msg }}</h1> <div>{{ title }}</div> 
</template><script setup>
const props = defineProps({ msg: String, title: { type: String, default: '我是标题' }, list: { type: Array, default: () => [] } 
});
console.log(props.msg);   //使用props中的属性const emits = defineEmits(['change', 'delete']);
</script>

1. defineProps 和 defineEmits 、defineExpose 都是只能在 <script setup> 中才能使用,他们不需要被导入即可使用,并且会在编译 <script setup> 语法块时一同被编译。

2. defineProps 接收与 props 选项相同的值,defineEmits 也接收 emits 选项相同的。

defineProps 是Vue3的写法并且是一个仅在 <script setup> 中可使用的编译命令,并不需要显式地导入;在Vue3的非语法糖setup和在Vue2中的写法是 props 。

注意:defineProps() 中的参数不可以访问 <script setup> 中定义的其他变量,因为在编译时整个表达式都会被移到外部的函数中。
defineProps 只能在 setup 中使用,且只能在 setup 的顶层使用,不能在局部作用域使用。
和 vue2 一样,defineProps 里的属性只读,不能修改。

在子组件中可以使用defineProps声明需要接收父组件的哪些props,它需要定义一个包含props字段的对象,每个字段定义默认值和类型等信息。当父组件的props发生变化时,子组件也会随之响应。

defineProps支持的主要类型有:

  • String
  • Number
  • Boolean
  • Object
  • Array
  • Function

同时也支持许多高级类型,比如,枚举类型,对象类型,联合类型等等。

我们可以对props进行验证,确保传入的值符合我们期望的值。

  • type:定义数据的类型
  • required:是否必须
  • default:默认值
  • validator:自定义验证
const props = defineProps({message: {type: String,default: ''},count: {type: Number,required: true,default: 0,validator: (value) => {return value >= 0 && value <= 10}}type:{type: String,validator: (value) => {return ['success', 'warning', 'danger', 'info'].includes(value)}},      data:{type: [Array, Object],default: () => {return { name: 'jack', age: 20 }}}})

实例:父组件传值给子组件

1、定义子组件 

<template>我是子组件<p>子组件得到的name:{{ props.name }}</p><p>子组件得到的age:{{ props.age }}</p><!--可以省略前面的props直接写属性名---><p>子组件得到的name:{{ name }}</p><p>子组件得到的age:{{ age }}</p>
</template><script setup>
//方式1: 以对象的形式去接收
const props = defineProps({name: {type: String,default: "张三",},age: {type: Number,default: 22}
});// props.age = 18 // 报错,注意 defineProps 中的属性只读不能修改//方式2: 以数组的方式去接收
//const childProps = defineProps(['name', 'age']);
</script>

2、定义父组件 

<template>name: {{ name }} <br />age: {{ age }} <br /><Child :name="name" :age="age" />
</template><script setup>
import { ref } from 'vue'
import Child from './components/Child.vue'const name = ref('LiuQing');
const age = ref(18);
</script>

defineEmits 和 defineProps 一样也是Vue3的写法并且仅用于 <script setup> 中,并且不需要导入;在Vue3的非语法糖setup和在Vue2中的写法是 emits 。

defineEmits 的不同点在于,组件要触发的事件可以显式地通过 defineEmits() 来声明。

defineEmits 用于子组件向父组件传递消息,在父组件中,只需要监听子组件的自定义事件,然后执行相应的逻辑即可。

注意:如果一个原生事件的名字 (例如 click) 被定义在 emits 选项中,则监听器只会监听组件触发的 click 事件而不会再响应原生的 click 事件。

实例:子组件向父组件传值

1、定义子组件

// 子组件 child.vue 
<template><button @click="handelClick">传递给父级</button><button @click="add">加</button><button @click="decrease">减</button>
</template><script setup>
const emits = defineEmits(['clickFn', 'add', 'decrease'])// 定义一个或多个自定义事件
// 触发emits事件
const handelClick = () => {emits('clickFn', { name: '张三', age: 18, id: 1 }) // 第一个参数为自定义事件名  第二个参数为要传递的数据
}
const add = () => {emits('add', 10) // 第一个参数为自定义事件名  第二个参数为要传递的数据
}
const decrease = () => {emits('decrease', 3) // 第一个参数为自定义事件名  第二个参数为要传递的数据
} 
</script>

2、定义父组件

// 父组件 parent.vue 
<template><h3>年龄:{{ age }}</h3><child :name="name" @clickFn="updateInfo" />
</template><script setup>
import { ref } from 'vue'
import child from './components/child.vue'const name = ref('李四');
const age = ref(10);const updateInfo = (obj) => {console.log(obj) // { name: '张三', age: 18, id: 1 }name.value = obj.name;age.value = obj.age;  
}
</script>

defineExpose 是Vue3中的一个新API,它允许子组件暴露其内部属性或方法给父组件访问。可以通过将属性或方法添加到defineExpose函数中来实现。

获取用setup语法糖创建的子组件实例时,获取的实例是没有子组件自定义的属性和方法的,此时我们需要通过defineExpose来暴露子组件的属性和方法。

在父组件中,我们使用ref属性引用了子组件。需要注意的是,defineExpose函数必须在setup函数中调用,否则会报错。

1、定义子组件 

<template><p>子组件test</p>
</template><script setup>
import { ref } from 'vue'const msg = ref('Hello Vue3')const a = () => {console.log(1)
}const handleChangeMsg = (v) => { msg.value = v 
}defineExpose({msg, a, handleChangeMsg 
})
</script>

2、定义父组件

<template><Test ref="testInstanceRef" /><button @click="handleChangeMsg">handleChangeMsg</button>
</template><script setup>
import { ref, onMounted } from "vue";
import Test from "./components/Test.vue";const testInstanceRef = ref();onMounted(() => {const testInstance = testInstanceRef.value;console.log(testInstance.$el)   // p标签console.log(testInstance.msg)   // msg属性console.log(testInstance.a)    // a方法,如果不使用defineExpose暴露是拿不到的
})const handleChangeMsg = () => { testInstanceRef.value.handleChangeMsg('Hello TS') 
}
</script>

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com