react中父组件如何直接调用子组件的方法和属性,以及对比vue3.0父组件调用子组件的方法和属性
react hook
forwardRef(render)
useImperativeHandle(ref, createHandle, dependencies?)
import {
forwardRef,
useEffect,
useImperativeHandle,
useRef,
useState,
} from "react";
const ChildrenComponents = forwardRef(function ChildrenComponents(props, ref) {
//useImperativeHandle类似于vue3.0的defineExpose,把子组件中要暴漏给父组件属性或方法,以对象的方式抛出去
useImperativeHandle(
ref,
() => {
return {
initList,
exposeParamter() {
return {
defaultTitleRef,
};
},
defaultTitleRef,
name,
list,
};
},
[]
);
const defaultTitleRef = "我是子组件";
let [name, setName] = useState("工藤新一");
let [list, setList] = useState([
{
name: "工藤新一",
sex: "男",
},
{
name: "毛利兰",
sex: "女",
},
]);
//初始化
function initList() {
console.log("[初始化子组件数据]");
}
function sendMessage() {
// 类似于vue3.0的defineEmits
props.click("点击子组件给父组件传值");
}
useEffect(() => {
console.log("[useEffect-子组件]", props);
}, []);
return (
<>
<p>我是子组件:{name}</p>
<br />
<span onClick={sendMessage}>点击子组件给父组件传值</span>
</>
);
});
function Forward() {
const childrenRef = useRef(null);
let [title, setTitle] = useState("我想操作子组件的方法和属性");
let [defaultName, setDefaultName] = useState("");
let [list, setList] = useState([]);
function getMessageHandle(params) {
console.log("[我接收了子组件的传值]", params);
console.log(childrenRef.current.list);
}
useEffect(() => {
console.log("[useEffect-父组件如何直接调用子组件的方法和属性]");
childrenRef.current.initList();
console.log("", childrenRef.current.exposeParamter().defaultTitleRef);
console.log("[name]", childrenRef.current.name);
setDefaultName(childrenRef.current.defaultTitleRef);
setList(childrenRef.current.list);
}, []);
return (
<>
<p>forwardRef:我是父组件</p>
<p>{defaultName}</p>
{/* react通过标签的属性传值 */}
<ChildrenComponents
ref={childrenRef}
title={title}
click={getMessageHandle}
/>
{list.map((item, index) => {
return (
<p key={index}>
{item.name}-{item.sex}
</p>
);
})}
</>
);
}
export default Forward;
vue setup
父组件
<template>
<div>组件</div>
<button @click="getHandle">ok</button>
<ChildrenComponent :title="title" :paramsObject="paramsObject" ref="childrenRef" @clickHandle="operateHandle" />
{{paramsObject.name}}
</template>
<script setup>
import {
onMounted,
ref
} from "vue";
import ChildrenComponent from "../components/children.vue";
let title = ref("组件传值");
const childrenRef = ref(null)
onMounted(() => {
childrenRef.value.initFunction();
console.log("[父组件]", childrenRef.value.defaultTitle)
})
let paramsObject = ref({
name: "父组件",
age: 29,
sex: '男'
})
function getHandle() {
}
function operateHandle(params) {
console.log("[params]", params)
paramsObject.value.name = params.name;
console.log("[paramsObject]", paramsObject)
}
</script>
<style>
</style>
子组件
<template>
<div>我还是个孩子</div>
<h1>{{props.title}}</h1>
<button @click="btnHandle">点击按钮</button>
</template>
<script setup>
import {
defineProps,
defineExpose,
defineEmits,
ref
} from "vue";
const props = defineProps({
title: {
type: String,
default: () => {
return ''
}
},
paramsObject: {
type: Object,
default: () => {
return {}
}
}
});
const emits = defineEmits(["clickHandle"]);
console.log("[children]", props.paramsObject)
function initFunction() {
console.log("[初始化]")
}
function btnHandle() {
console.log("[ok]")
emits("clickHandle", {
name: '毛利兰'
})
}
let defaultTitle = ref("我是子组件")
defineExpose({
initFunction,
defaultTitle
})
</script>
<style lang="scss" scoped>
</style>