1.不能在子组件中改变prop
解决方法: 1.从props获取值,定义一个新的局部数据属性
const props = defineProps(['initialCounter'])
const counter = ref(props.initialCounter)
2.基于prop定义一个计算属性
const props = defineProps(['size'])
// 该 prop 变更时计算属性也会自动更新
const normalizedSize = computed(() => props.size.trim().toLowerCase())
2.当prop为数组和对象时
子组件可以更改对象数组内部的值,这是因为js对象数组是通过索引来进行传递的;
vue中虽然可能会生效但是性能会有损耗,子组件应尽量避免并通过抛出一个事件来让父组件进行更改
props
- 在
<script setup>中需要使用defineProps宏,它不需要显示导入返回的对象包含了所有传递给组件的props - 在未使用
<script setup>时需要显示的声明propsprops对象会作为setup()函数的第一个参数
export default {
props: ['title'],
setup(props) {
console.log(props.title)
}
}
3.使用一个对象来绑定多个prop,即将一个对象的所有属性都当作props传入,
可以使用没有参数的v-bind
const post = {
id: 1,
title: 'My Journey with Vue'
}
<BlogPost v-bind="post" />
//等价于
<BlogPost :id="post.id" :title="post.title" />
props校验
defineProps({
// 基础类型检查
// (给出 `null` 和 `undefined` 值则会跳过任何类型检查)
propA: Number,
// 多种可能的类型
propB: [String, Number],
// 必传,且为 String 类型
propC: {
type: String,
required: true
},
// Number 类型的默认值
propD: {
type: Number,
default: 100
},
// 对象类型的默认值
propE: {
type: Object,
// 对象或数组的默认值
// 必须从一个工厂函数返回。
// 该函数接收组件所接收到的原始 prop 作为参数。
default(rawProps) {
return { message: 'hello' }
}
},
// 自定义类型校验函数
// 在 3.4+ 中完整的 props 作为第二个参数传入
propF: {
validator(value, props) {
// The value must match one of these strings
return ['success', 'warning', 'danger'].includes(value)
}
},
// 函数类型的默认值
propG: {
type: Function,
// 不像对象或数组的默认,这不是一个
// 工厂函数。这会是一个用来作为默认值的函数
default() {
return 'Default function'
}
}
})
事件监听
子组件通过调用内置的 $emit 方法,通过传入事件名称来抛出一个事件:
<!-- BlogPost.vue, 省略了 <script> -->
<template>
<div class="blog-post">
<h4>{{ title }}</h4>
<button @click="$emit('enlarge-text')">Enlarge text</button>
</div>
</template>
父组件中@事件名称来调用
<BlogPost
@enlarge-text="postFontSize += 0.1"
/>
defineEmits宏
- 仅在
<script setup>中使用,不需导入,返回一个等同于$emit方法的emit函数。 - 它可以被用于在组件的
<script setup>中抛出事件 -defineEmits声明一个组件可能触发的所有事件,可以对事件参数进行验证 同时避免被隐式应用于子组件的根元素上
事件参数
在声明的事件名称后面可以传参
<button @click="$emit('increaseBy', 1)">
Increase by 1
</button>
defineEmits()宏
- 组件
scrpt setup的内部通过defineEmits()会返回一个<template>中$emit相同作用的函数
<script setup>
const emit = defineEmits(['inFocus', 'submit'])
function buttonClick() {
emit('submit')
}
</script>
-defineEmits()宏不能在子函数中使用,需要直接放置在<script setup>顶级作用域下
事件参数检验
<script setup>
const emit = defineEmits({
// 没有校验
click: null,
// 校验 submit 事件
submit: ({ email, password }) => {
if (email && password) {
return true
} else {
console.warn('Invalid submit event payload!')
return false
}
}
})
function submitForm(email, password) {
emit('submit', { email, password })
}
</script>