Vue
父子组件通信
父传子(Props 传值)
使用 defineProps 声明接收的 props
//父组件
<template>
<div class="container">
<h1>父传子---父组件</h1>
<p>输入的值:{{ inputValue }}</p>
<input type="text" v-model="inputValue" />
<ChildComponent :title="inputValue" />
</div>
</template>
<script setup>
import { ref } from 'vue'
import ChildComponent from '../components/ChildComponent.vue'
// 父传子
const inputValue = ref('')
</script>
//子组件
<template>
<div class="child">
<h2>父传子---子组件</h2>
<div class="title">{{ title }}</div>
</div>
</template>
<script setup>
import { ref, defineModel } from 'vue'
// 父传子
const props = defineProps({
title: {
type: String,
},
})
</script>
子传父(Emit 事件)
使用 defineEmits 声明事件
//父组件
<template>
<div class="container">
<h1>子传父---父组件</h1>
<ChildComponent @update="handleUpdate" />
<div>{{ valueParent }}</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import ChildComponent from '../components/ChildComponent.vue'
// 子传父
const valueParent = ref('')
const handleUpdate = (res) => {
valueParent.value = res
}
</script>
<template>
<div class="child">
<h2>子传父---子组件</h2>
<button @click="sendData">点击传值</button>
<button @click="sendData2">点击传值2</button>
</div>
</template>
<script setup>
import { ref, defineModel } from 'vue'
// 子传父
// 定义一个名为 update 的自定义事件
const emit = defineEmits(['update'])
const sendData = () => {
// 触发 update 事件,并传递参数,事件名可以根据需要自定义
emit('update', '子传父')
}
const sendData2 = () => {
// 触发 update 事件,并传递一个对象作为参数
emit('update', {
name: '子传父',
age: 18,
})
}
</script>
跨层级通信
Provide / Inject(基础版)
- 先使用
Provide在祖先组件中声明共享数据 - 之后使用
Inject在后代组件中获取数据 - 使用
响应式数据会自动更新所有注入组件 - 数据流向:单向(祖先 → 后代)
祖先组件向任意深层后代传递数据
//父组件
<template>
<div class="container">
<h1>跨层级通信---祖先组件</h1>
<ChildComponent />
<p>祖先的counter: {{ counter }}</p>
</div>
</template>
<script setup>
import { ref, provide } from 'vue'
import ChildComponent from '../components/ChildComponent.vue'
// 跨层级通信 爷孙传值
const counter = ref(0)
// 通过provide函数提供名称为 counterName 的数据给后代组件
provide('counterName', counter) // 提供响应式数据
</script>
<template>
<div class="child">
<h2>跨层级通信---后代组件</h2>
<button @click="increment">后代修改: {{ counter }}</button>
</div>
</template>
<script setup>
import { inject } from 'vue'
// 跨层级通信 爷孙传值
// 通过inject函数注入名称为 counterName 的数据
const counter = inject('counterName') // 注入数据
const increment = () => counter.value++
</script>
Provide / Inject + 方法(进阶版)
跨层级修改数据(类似全局状态)
封装业务逻辑,避免直接修改数据
//父组件
<template>
<div class="container">
<h1>跨层级通信Provide / Inject + 方法(进阶版)---祖先组件</h1>
<ChildComponent />
<p>祖先的name: {{ user.name }}</p>
</div>
</template>
<script setup>
import { ref, provide, reactive } from 'vue'
import ChildComponent from '../components/ChildComponent.vue'
// 跨层级通信 Provide / Inject + 方法(进阶版)
const user = reactive({ name: 'Alice' })
provide('userContext', {
// 提供数据+方法
user,
updateName: (newName) => {
if (user.name != newName) {
user.name = newName
} else {
user.name = 'Alice'
}
},
})
</script>
//子组件
<template>
<div class="child">
<h2>跨层级通信Provide / Inject + 方法(进阶版)---后代组件</h2>
<p>当前用户: {{ user.name }}</p>
<button @click="updateName('Bob')">改名</button>
</div>
</template>
<!-- 跨层级组件通信 -->
<script setup>
import { inject } from 'vue'
// 跨层级通信 Provide / Inject + 方法(进阶版)
const { user, updateName } = inject('userContext')
</script>
Pinia
Pinia 在任意组件中使用(无需关心层级)
使用前要创建一个 js/ts 文件来存储数据信息
在需要使用的地方,引入数据文件来获取或修改数据信息
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
state: () => ({
profile: { name: 'Alice', age: 25 },
}),
actions: {
updateProfile(newProfile) {
this.profile = { ...this.profile, ...newProfile }
},
},
})
<template>
<div class="container">
<div>Pinia---任意组件(无需关心层级)</div>
<p>{{ userStore.profile.name }}</p>
<p>{{ userStore.profile.age }}</p>
<button @click="userInfo">修改年龄</button>
</div>
</template>
<script setup>
import { useUserStore } from '../../stores/user'
const userStore = useUserStore()
const userInfo = () => {
userStore.updateProfile({ age: 26 })
}
</script>
模板引用通信
v-model 双向绑定
v-model 是 :modelValue + @update:modelValue 的语法糖:
//父组件
<template>
<div class="container">
<h1>父组件 v-model 双向绑定</h1>
<ChildComponent v-model="inputValue" />
<div>输入值:{{ inputValue }}</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import ChildComponent from '../components/ChildComponent.vue'
const inputValue = ref('')
</script>
//子组件
<template>
<div class="child">
<h2>子组件 v-model 双向绑定</h2>
<input
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
</div>
</template>
<script setup>
import { ref } from 'vue'
defineProps(['modelValue'])
defineEmits(['update:modelValue'])
</script>
ref + Expose 模版引用
调用子组件内的方法
访问子组件中的DOM
<template>
<ChildComponent ref="childRef" />
<button @click="handleClick">播放</button>
</template>
<script setup>
import { ref } from 'vue'
import ChildComponent from '../components/ChildComponent.vue'
const childRef = ref(null)
const handleClick = () => {
childRef.value.play()
}
</script>
<template>
<input type="text" :value="valueUse" />
</template>
<script setup>
import { ref } from 'vue'
const valueUse = ref('')
const play = () => {
console.log('播放视频')
valueUse.value = '播放视频'
}
defineExpose({ play }) // 暴露方法
</script>
React
父子组件通信
父传子(props传值)
//父组件
import React, { useState } from 'react'
import Child01 from '../components/child01'
export default function index() {
const [name, setName] = useState('张三')
const [age, setAge] = useState(18)
const changeInfo = () => {
setName('李四')
setAge(20)
}
return (
<div>
<h1>react01</h1>
<Child01 name={name} age={age}>
{/* <div>123</div> */}
</Child01>
<button
onClick={() => {
changeInfo()
}}
>
点击
</button>
</div>
)
}
//子组件
import React from 'react'
//多个参数的 函数
interface IProps {
name: string
age: number
// children: React.ReactNode
}
export default function index(props: IProps) {
return (
<div>
<div>{props.name}</div>
<div>{props.age}</div>
//<div>{props.children}</div>
</div>
)
}
如果需要在封装的组件内嵌套内容,则需要在子组件中声明一个
children: React.ReactNode属性,就可以接收并渲染其内部嵌套的任何内容。
子传父(回调函数)
//父组件
import React, { useState } from 'react'
import Child02 from '../components/child02'
export default function index() {
const [msg, setMsg] = useState('')
const handleEvent = (msg: string) => {
console.log(msg)
setMsg(msg)
}
return (
<div>
<h1>react02</h1>
<Child02 onEvent={handleEvent} />
<div>{msg}</div>
</div>
)
}
//子组件
import React from 'react'
interface IProps {
onEvent: (msg: string) => void
}
export default function index(props: IProps) {
return (
<div>
<button onClick={() => props.onEvent('点击了子组件')}>点击</button>
</div>
)
}
1238

被折叠的 条评论
为什么被折叠?



