vue3第十九节(编译宏defineProps与defineEmits)用法注意事项

发布于:2024-04-16 ⋅ 阅读:(187) ⋅ 点赞:(0)

作用

1、vue3中编译宏,是一种特殊的代码,在编译时候,可以根据不同的宏,编译成不同的代码
2、vue3中编译宏,只能用在setup顶层语法糖中,如果将编译宏写在setup的 非顶层语法里,则会将编译宏原样输出,从而导致找不到编译宏的定义,而报错
3、vue3 中的编译宏,不需要引入,直接使用即可;因为在编译阶段,defineComponent()会将其转化为对应的代码
比如:

<script setup >
  const props = defineProps({
    person: {
      type: Object,
      default: () => ({})
    }
  })

</script>

编译之后代码为:

<script>
  import { props, defineComponent } from 'vue'

  ……
  defineComponent({
    props: {
      person: {
        type: Object.
        default: () => ({})
      }
    }
    setup(props, { emit }) {}
  }
  ……
</script>

defineProps()/defineEmits()

用于在 setup语法糖中 定义 props和emits
由于数据流是单项的,故defineProps()里面的属性是只读,不能直接在子组件中修改,若要进行二次修改,需要定义额外属性进行接收;
defineProps() 函数返回一个对象,是一个 proxy ,所有的特性和 reactive 基本相同,可以直接在模版上进行使用;

defineProps({
  person: {
    type: Object, // 类型
    default: () => ({}), // 默认值
    required: true, // 是否必填
    validator: (value) => {} //
  }
})

defineEmits() 函数返回一个函数,该函数可以触发父组件的事件与模板里面的 $emit 相同作用的函数来触发
defineEmits() 接收一个数组

如:js 中 defineEmits(['changeAge'])
ts 中 const emit = defineEmits<{
  (e: 'change', id: number): void
  (e: 'update', value: string): void
}>()
// 或者
const emit = defineEmits<{
  change: [id: number] // 具名元组语法
  update: [value: string]
}>()

例如父组件:

<template>
<div class="parents-container">
  This is a parents page.
  <hr>
  <el-button type="primary" @click="changeName">父组件更改名字</el-button>
  <hr>
  <Child :person="person" @handleChangeAge="handleChangeAge"></Child>
</div>
</template>
<script setup>
import { ref, reactive, computed, watch, onMounted, onUnmounted } from 'vue'
import Child from './components/Children.vue'
const person = ref({
  name: '',
  job: 'dev'
})
const changeName = () => {
  person.value.name = `${person.value.name} + $`
  console.log('==person.value.age==', person.value.age)
  person.value.age = person.value.age ? (person.value.age + 1 ): 18
}
// 父组件监听子组件的 changeAge 事件
const handleChangeAge = (data) => {
  console.log('==handleChangeAge==', data)
  person.age = data
  person.name = `${person.name} + ${data}`
} 
</script>

子组件中:

<template>
<div class="children-container">
  This is a child page.
  <div>person.name:{{ person.name }}</div>
  <el-button type="primary" @click="handleGetName">子组件获取name</el-button>
</div>
</template>
<script setup>
import { computed, watch, ref } from 'vue'
const props = defineProps({
  person: Object,
  default: () => ({}),
  reqiured: true, // 是否必须传,
  // validator: (val) => val > 10 // 自定义校验
})
// const newPropsRef = ref(props.person) 不要使用这种形式 会导致newPropsRef不会跟随props.person变化而变化


// 如若子组件需要二次加工使用 person ,
// 1、使用computed()
const personCom = computed(() => {
  const { name, job,age } = props.person
  return {
    name,
    job,
    age
  }
})

// 2、或者使用 toRefs() 给每个属性设置代理
// const personCom = toRefs(props.person)
const handleGetName = () => {
  // const { name } = props.person
  // console.log('=person.name==', props.person.name)
  // console.log('=person.name==',{ ...props.person})
  console.log('=newPropsRef===', personCom.value.age, personCom)
}
watch(() => personCom.value, (n, o) => {
  console.log('==Child watch==',n , o)
  handleGetName()
}, {
  immediate: true,
  deep: true
})
// 子组件触发父组件事件
const emits = defineEmits(['handleChangeAge'])
const handleChangeAge = () => {
  emits('handleChangeAge', 1)
}
</script>

更多组件传参方法请查看组件之间传参

以上仅代表个人看法,若有错误欢迎批评指正


网站公告

今日签到

点亮在社区的每一天
去签到