vue3setup-props传参及事件监听

72 阅读2分钟

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

  1. <script setup>中需要使用defineProps宏,它不需要显示导入返回的对象包含了所有传递给组件的 props
  2. 在未使用<script setup>时需要显示的声明props props对象会作为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>