编译器宏
defineProps
父组件向子组件传递 属性 时,子组件需使用 defineProps
来接收,有三种使用方式:
typescript
const { msg } = defineProps<{ msg?: string }>();
// JavaScript原生语法设置默认值
const { msg = 'hello' } = defineProps<{ msg?: string }>()
typescript
const { msg } = defineProps({
msg: {
type: String,
// 类型可以为多种的情况
// type: [String, null],
default: "Hello world",
required: true
}
});
typescript
interface IProps {
msg?: string;
label?: string[];
}
// 基于 interface 类型声明时,就失去了为 props 声明默认值的能力,可以通过 withDefaults 编译器宏解决
const { msg, label } = withDefaults(defineProps<IProps>(), {
msg: "Hello world",
label: () => ["one", "two"]
});
props的命名规范
如果一个 prop 的名字很长,应使用 camelCase 形式:
typescript
defineProps({
greetingMessage: String
})
但在组件中传递属性时,为了和 HTML attribute 对齐,我们通常会将其写为 kebab-case 形式:
vue
<MyComponent greeting-message="hello" />
defineEmits
事件校验
要为 defineEmits
添加事件校验,需要返回一个布尔值来表明事件是否合法。
vue
<template>
<HelloWorld @submit="handleSubmit" />
</template>
<script setup lang="ts">
import HelloWorld from "./components/HelloWorld.vue"
function handleSubmit(value: object) {
console.log(value)
}
</script>
vue
<template>
<button @click="handleSubmit('admin', '123456')">submit</button>
</template>
<script setup lang="ts">
const emit = defineEmits({
click: null,
submit: ({ username, password }) => {
if (username && password) {
return true
} else {
console.warn("Invalid submit event payload!")
return false
}
}
})
function handleSubmit(username: string, password: string) {
emit("submit", { username, password })
}
</script>
defineOptions3.3+
defineOptions
宏可以用来直接在 <script setup>
中声明 组件选项,而不必使用单独的 script
块:
vue
<script>
export default {
name: "MyComponent"
}
</script>
<script lang="ts" setup></script>
vue
<script>
import { defineComponent, defineOptions, ref } from 'vue'
export default defineComponent({
name: "MyComponent",
setup() {
defineOptions({
name: "MyComponent"
})
}
})
</script>
vue
<script lang="ts" setup>
defineOptions({
name: "MyComponent",
inheritAttrs: false,
customOptions: {
/* ... */
}
})
</script>
defineModel
definedModel()
宏返回的是一个 ref
,它可以正常使用 .value
被访问和修改,它最重要的作用是在 父组件和子组件之间实现双向绑定。
- 子组件的
.value
和父组件的v-model
的值同步; - 当子组件的值变化了,会立马触发父组件绑定的值一起更新;
默认v-model
vue
<template>
<h5>{{ count }}</h5>
<HelloWorld v-model="count" />
</template>
<script setup lang="ts">
import { ref } from "vue";
import HelloWorld from "./components/HelloWorld.vue";
const count = ref<Number>(2000);
</script>
vue
<template>
<input type="text" v-model="model" />
</template>
<script setup lang="ts">
const model = defineModel<Number>();
console.log(modle.value); // 2000
</script>
具名v-model
vue
<template>
<h5>{{ count }}</h5>
<HelloWorld v-model:count="count" />
</template>
<script setup lang="ts">
import { ref } from "vue";
import HelloWorld from "./components/HelloWorld.vue";
const count = ref<Number>(2000);
</script>
vue
<template>
<input type="text" v-model="model" />
</template>
<script setup lang="ts">
const model = defineModel<Number>("count");
console.log(model.value); // 2000
</script>
绑定多个v-model
vue
<template>
<h5>{{ count }}</h5>
<HelloWorld v-model:count="count" v-model:name="name" />
<h5>{{ name }}</h5>
<HelloWorld v-model:count="count" v-model:name="name" />
</template>
<script setup lang="ts">
import { ref } from "vue";
import HelloWorld from "./components/HelloWorld.vue";
const count = ref<Number>(2000);
const name = ref<String>("tom");
</script>
vue
<template>
<input type="text" v-model="model" />
<input type="text" v-model="model2" />
</template>
<script setup lang="ts">
const model = defineModel<Number>("count");
console.log(model.value); // 2000
const model2 = defineModel<String>("name");
console.log(model2.value); // tom
</script>
props选项
vue
<template>
<h5>{{ visible }}</h5>
<HelloWorld v-model:visible="visible" />
</template>
<script setup lang="ts">
import { ref } from "vue";
import HelloWorld from "./components/HelloWorld.vue";
const visible = ref<boolean>(true);
</script>
vue
<template>
<input type="text" v-model="model" />
</template>
<script setup lang="ts">
const model = defineModel("visible", {
type: boolean,
required: true,
default: true,
// 校验值,传入的值必须是true或false
validator: (value: string) => [true, false].includes(value)
});
</script>