🙌:讲讲vue3 setup语法糖里定义组件props的宏函数—defineProps...

215 阅读2分钟

🏃‍♀️ 背景(👉为什么突然间要写起 defineProps)

有一次有个例子要做teleport,具体代码如下,看到同事在template模板中props.show这种,后面我说:“在模板中,不需要通过props.show这种形式,直接用show直接用也可以”,遂有了此文做记录📝。

大概代码如下:

<!--
可定制插槽和 CSS 过渡效果的模态框组件。
-->

<script setup>
import Modal from './Modal.vue'
import { ref } from 'vue'

const showModal = ref(false)
</script>

<template>
  <button id="show-modal" @click="showModal = true">Show Modal</button>

  <Teleport to="body">
    <!-- 使用这个 modal 组件,传入 prop -->
    <modal :show="showModal" @close="showModal = false">
      <template #header>
        <h3>Custom Header</h3>
      </template>
    </modal>
  </Teleport>
</template>

// model.vue

<script setup>
const props = defineProps({
  show: Boolean
})
</script>

<template>
  <Transition name="modal">
    <!-- 这里直接用show -->
    <div v-if="show" class="modal-mask">
      <div class="modal-container">
        <div class="modal-header">
          <slot name="header">default header</slot>
        </div>

        <div class="modal-body">
          <slot name="body">default body</slot>
        </div>

        <div class="modal-footer">
          <slot name="footer">
            default footer
            <button
              class="modal-default-button"
              @click="$emit('close')"
            >OK</button>
          </slot>
        </div>
      </div>
    </div>
  </Transition>
</template>

大概上面👆teleport的效果是这样的:

效果图.gif

640.gif

🏃‍♀️ 正文(解释)

模板中自动解构

setup 语法糖:

在 <script setup> 中,Vue 会自动将通过 defineProps 和 defineEmits 声明的 props 和 emits 注入到模板的作用域中。也就是说,Vue 会在内部做一些处理,使得这些 props 和 emits 可以像在 <script setup> 中定义的局部变量一样在模板中直接使用。

<template>
  <!-- 可以直接使用 show,而不需要 props.show -->
  <div v-if="show" class="modal-mask">
    这是一个模态框
  </div>
</template>

<script setup>
import { defineProps } from 'vue';

// 定义 props
const props = defineProps({
  show: Boolean
});

// 在 <script setup> 中仍然可以通过 props 对象访问
console.log(props.show); 
</script>

在上述代码中,defineProps 定义了一个名为 show 的布尔类型的 prop。在模板中,我们可以直接使用 show 来判断是否显示模态框,而不需要写成 props.show

如果不用setup这种组合式,用选项式来写的话,大致代码如下:

<template>
  <!-- 需要使用 this.$props.show -->
  <div v-if="this.$props.show" class="modal-mask">
    这是一个模态框
  </div>
</template>

<script>
export default {
  props: {
    show: Boolean
  },
  mounted() {
    console.log(this.$props.show);
  }
};
</script>

<script setup> 语法通过自动注入 props 到模板作用域,简化了模板中对 props 的使用,使代码更加简洁和直观。

基本用法

在 <script setup> 中使用 defineProps 定义 props 非常简单,只需调用该函数并传入一个对象,对象的键为 prop 的名称,值为 prop 的类型或类型定义。

<template>
  <div>
    <!-- 直接使用 prop -->
    <p>{{ message }}</p> 
  </div>
</template>

<script setup>
import { defineProps } from 'vue';

// 定义 props
const props = defineProps({
  message: String
});
</script>

在上述代码中,定义了一个名为 message 的 prop,其类型为 String。在模板中可以直接使用 message 来显示从父组件传递过来的数据。

复杂类型定义 并 设默认值

<template>
  <div>
    <p>{{ user.name }}</p>
    <p>{{ user.age }}</p>
  </div>
</template>

<script setup>
import { defineProps } from 'vue';

const props = defineProps({
  user: {
    type: Object,
    default: () => ({
      name: 'Guest',
      age: 18
    })
  }
});
</script>

这里定义了一个 user prop,其类型为 Object,并设置了默认值。如果父组件没有传递 user prop,子组件将使用默认值。

类型检查和必填项设置

可以通过 required 选项来指定某个 prop 是否为必填项。

<script setup>
import { defineProps } from 'vue';

const props = defineProps({
  id: {
    type: Number,
    required: true
  },
  title: {
    type: String,
    default: 'Default Title'
  }
});
</script>

在这个例子中,id 是必填的 Number 类型 prop,而 title 是可选的 String 类型 prop,有默认值。

640.gif

🏃‍♀️ 小结(复盘)

<script setup> 语法为开发者提供了更简洁的语法糖,使得通过 defineProps 定义的 props 可以直接在模板中使用,减少了代码的冗余,提高了开发效率。但在 <script setup> 内部,仍然可以通过 props 对象来访问这些 props。

  • 语法简洁:在 <script setup> 中使用 defineProps 避免了传统选项式 API 中复杂的 props 选项定义,使代码更加简洁易读。
  • 自动注入:通过 defineProps 定义的 props 会自动注入到模板的作用域中,在模板中可以直接使用 prop 名称,而不需要通过 props.xxx 的形式访问。
  • 静态分析支持:Vue 3 的编译器可以对 defineProps 进行静态分析,提供更好的类型检查和 IDE 支持,有助于在开发过程中尽早发现错误。

☎️ 希望对大家有所帮助,如有错误,望不吝赐教,欢迎评论区留言互相学习。