vue3父子组件通信

1 阅读3分钟

父子组件通信

blog.csdn.net/qq_26018335…

defineProps父组件向子组件传值

defineProps 是一个仅 <script setup> 中可用的编译宏命令,并不需要显式地导入。声明的 props 会自动暴露给模板。defineProps 会返回一个对象,其中包含了可以传递给组件的所有 props:

 <MyComponent v-model:foo="foo" />
 const foo = ref(1)
 <script setup>
 const props = defineProps(['foo'])
 console.log(props.foo)
 </script>
 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' }
     }
   },
   // 自定义类型校验函数
   propF: {
     validator(value) {
       // The value must match one of these strings
       return ['success', 'warning', 'danger'].includes(value)
     }
   },
   // 函数类型的默认值
   propG: {
     type: Function,
     // 不像对象或数组的默认,这不是一个
     // 工厂函数。这会是一个用来作为默认值的函数
     default() {
       return 'Default function'
     }
   }
 })

一些补充细节:

  • 所有 prop 默认都是可选的,除非声明了 required: true
  • Boolean 外的未传递的可选 prop 将会有一个默认值 undefined
  • Boolean 类型的未传递 prop 将被转换为 false。这可以通过为它设置 default 来更改——例如:设置为 default: undefined 将与非布尔类型的 prop 的行为保持一致。
  • 如果声明了 default 值,那么在 prop 的值被解析为 undefined 时,无论 prop 是未被传递还是显式指明的 undefined,都会改为 default 值。

子组件向父组件传值/触发事件

defineEmits触发父组件事件

可以通过defineEmits宏来声明需要抛出的事件

 <script setup>
 import { ref } from 'vue'
 import BlogPost from './BlogPost.vue'
 </script>
 ​
 <template>
   <div :style="{ fontSize: postFontSize + 'em' }">
     <BlogPost
       @enlarge-text="postFontSize += 0.1"
     ></BlogPost>
   </div>
 </template>
 <script setup>
 defineEmits(['enlarge-text'])
 </script>
 ​
 <template>
   <div class="blog-post">
     <button @click="$emit('enlarge-text')">Enlarge text</button>
   </div>
 </template>
defineEmits向父组件传值

子组件的传递方式

 <template>
   <button @click="clickChild">点击子组件</button>
 </template>
  
 <script setup>
 import { defineEmits } from 'vue'
 // 使用defineEmits创建名称,接受一个数组
 const emit = defineEmits(['clickChild'])
 const clickChild=()=>{
   //传递给父组件
   emit('clickChild',{content:'b'})
 }
 </script>

父组件接收与使用

 <template>
   <div class="hello">
   <!-- clickChild是子组件绑定的事件,click是父组件接受方式 -->
    <Child  @clickChild="clickEven"></Child>
    <p>子组件传递的值是 {{result}}</p>
  </div>
 </template>
  
 <script setup>
 import Child from './Child'
 import {ref} from 'vue'
 const result=ref('')
 const clickEven=(val)=>{
   result.value=val.content
   console.log("触发了父组件方法")
 }
 </script>

双向绑定 prop

emit-update

3.4 之前的用法

 <script setup>
 defineProps({
   firstName: String,
   lastName: String
 })
 ​
 defineEmits(['update:firstName', 'update:lastName'])
 </script>
 ​
 <template>
   <input
     type="text"
     :value="firstName"
     @input="$emit('update:firstName', $event.target.value)"
   />
   <input
     type="text"
     :value="lastName"
     @input="$emit('update:lastName', $event.target.value)"
   />
 </template>

通过触发 update:title 事件更新父组件值

defineModel

这个宏可以用来声明一个双向绑定 prop

 // 声明 "modelValue" prop,由父组件通过 v-model 使用
 const model = defineModel()
 // 或者:声明带选项的 "modelValue" prop
 const model = defineModel({ type: String })
 ​
 // 在被修改时,触发 "update:modelValue" 事件
 model.value = "hello"
 ​
 // 声明 "count" prop,由父组件通过 v-model:count 使用
 const count = defineModel("count")
 // 或者:声明带选项的 "count" prop
 const count = defineModel("count", { type: Number, default: 0 })
 ​
 function inc() {
   // 在被修改时,触发 "update:count" 事件
   count.value++
 }

如果为 defineModel prop 设置了一个 default 值且父组件没有为该 prop 提供任何值,会导致父组件与子组件之间不同步。在下面的示例中,父组件的 myRef 是 undefined,而子组件的 model 是 1:

 // 子组件:
 const model = defineModel({ default: 1 })
 ​
 // 父组件
 const myRef = ref()
 <Child v-model="myRef"></Child>

ref父组件获取子组件的属性/方法

当时用语法糖时,需要将组建的属性及方法通过defineExpose导出,父组件才能访问到数据,否则拿不到子组件的数据

子组件的传递方式

 <template>
   <div>
     <h2> 我是子组件</h2>
     <p>性别:{{ sex}}</p>
   </div>
 </template>
  
 <script setup>
 import { reactive, ref,defineExpose } from "vue";
 let sex=ref('男')
 let info=reactive({
     like:'王者荣耀',
     age:18
 })
 defineExpose({sex, info})
 </script>
  
 <style>
  
 </style>

父组件显示方式

 <template>
   <div class="hello">
   我是父组件
     <Child ref="testcomRef"></Child>
     <button @click="getSonHander">获取子组件中的数据</button>
  </div>
 </template>
  
 <script setup>
 import Child from './Child'
 import {ref} from 'vue'
 const testcomRef = ref()
 const getSonHander=()=>{
   console.log('获取子组件中的性别', testcomRef.value.sex );
    console.log('获取子组件中的其他信息', testcomRef.value.info )
 }
 </script>
  
 <style scoped>
  
 </style>