You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When a component receives parent data as a child component or triggers parent events, we use defineProps, defineEmits and recently introduced defineModel macros. However, limited by the constraints of javascript/typescipt, these macros have some shortcomings in writing and functionality, and Instead of pushing grammar sugar with difficulty, it is better to create a new one <define></define> scope to extract logic between parent and child components, improving the readability of the code.
预期的效果(Expected effect)
子组件(Child Component)
<define>
name: string
// 普通参数(normal parameter)
// 形式上等同于 const { name } = defineProps<{name: string}>()
age: number = 20
// 带默认值的参数(parameter with default value)
// 形式上等同于 const { age = 20 } = defineProps<{age?: number}>()
// 也可以进行类似于typescript的自动类型推导, 可以将其写为( similar to automatic type inference in TypeScript, It can be written as):
// age = 20
#gender: 'male' | 'female'
// v-model参数(v-model parameter)
// 形式上等同于 const gender = defineModel<'male' | 'female'>('gender', { required: true })
@addYears(years: number) // 父组件事件(emits)
// 形式上等同于 const emits = defineEmits<{addYears: [years: number]}>()
</define>
<scriptsetuplang="ts">import { watch, compute } from'vue';// 声明在<define>中的`name`, 类型等同于: const name = ref<string>('<placeholder>')// `name` defined in <define>, type is equivalent to: // const name: Readonly<Ref<number>> = ref('<placeholder>')watch(name, () =>console.log('name被修改了(name has be modified)')) const nextYearAge =compute(() =>age.value+1)</script>
<template>
<h1>I'm {{ name.toUpperCase() }}, {{ age }} years old</h1>
<h2>And I will be {{ nextYearAge }} years old next year</h2>
<p>
My gender is
<selectv-model="modelValue">
<option>male</option>
<option>female</option>
</select>
</p>
<button @click="addYears(10)">Add 10 years old</button>
</template>
父组件(Parent Component)
<scriptsetuplang="ts">import { ref } from'vue';const name =ref('my_name')const age =ref(23)const gender =ref<'male'|'female'>('male')function addYears(years:number) {age.value+=years}</script>
<template>
<ChildComponent :name="name" :age="age"v-model:gender="gender" @add-years="addYears" />
</template>
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
在SFC中支持新范式-定义作用域
<define></define>
(Support define scope in SFC)当组件作为子组件接收父组件数据或触发父组件事件时, 我们使用
defineProps
,defineEmits
以及最近新引入的defineModel
宏. 但是受限于 javascript/typescipt 的约束, 这些宏在写法和功能上都有一些不足, 与其艰难地推动语法糖, 不如新创建一个<define></define>
作用域概念来将父子组件之间的逻辑抽离出来, 提高代码的可读性.When a component receives parent data as a child component or triggers parent events, we use
defineProps
,defineEmits
and recently introduceddefineModel
macros. However, limited by the constraints of javascript/typescipt, these macros have some shortcomings in writing and functionality, and Instead of pushing grammar sugar with difficulty, it is better to create a new one<define></define>
scope to extract logic between parent and child components, improving the readability of the code.预期的效果(Expected effect)
子组件(Child Component)
父组件(Parent Component)
使用外部类型(Use External Type)
外部Typescript(External TypeScript)
子组件(Child Component)
等同于(Equivalent to)
一些考虑(FAQ)
问: 这种写法并不是标准的 typescript 语法, 使用者可能有心智负担
答: 确实会这样, 但是我觉得这种心智负担是可以接受的,
在
<template>
中使用插值表达式或vue指令, 也并不符合html语法规范, 但也是被接受的.这种写法的语法和 typescript 相类似, 并不会造成很大的心智负担
Beta Was this translation helpful? Give feedback.
All reactions