前言
其实现依赖于:React + TypeScript
问题:如何将一个组件的方法暴露给其他组件呢?
NOTE:以下的方法都不是绝对的,可能会有更好的方式实现,又或者会有更多的方式去暴露子组件的 API,这里只是提供一个思路。
通过 ref
注:本节示例使用的是函数式组件 Ref (Hook)的方式。
这其中有关基本知识如下:
// parent.tsx
import React, { useRef } from "react"
import Child from "./child"
const Parent = () => {
const classChildRef: any = useRef(null)
// 调用子组件实例上的 childGet()
const getClassChildFn = () => classChildRef.current.childGet()
return (
<div>
<Child ref={classChildRef} />
<button onClick={getClassChildFn}>获取子组件值</button>
</div>
)
}
export default Parent
// child.tsx
import React, { useImperativeHandle, useRef } from "react"
// 使用 React.forwardRef() 将 ref 属性暴露(使得任意一个组件都可以使用该 ref),该函数本身返回一个 React 结点。
const Child = React.forwardRef(
(props: any, ref: any) => {
let state = { index: 0 }
// 第 1 个参数:暴露 ref 属性。
// 第 2 个参数:具体暴露的值。
useImperativeHandle(ref, () => (
{
childGet() { console.log(state.index) },
}
))
return (<div>Child</div>)
}
)
export default Child
当单击父组件按钮(获取子组件值)时,就会调用子组件实例使用 useImperativeHandle Hook
暴露出来的 childGet()
,从而在控制台输出子组件实例的 state.index
值。
传递 props
// parent.tsx
import React from 'react';
import Child from "./child";
const Parent = () => (<Child sayHello={{ sayHello: "hello" }} />)
export default Parent
// child.tsx
import {useEffect} from 'react';
const Child = (props: any) => {
const sayHello = (v: any) => { console.log(v) }
// 当父组件有向子组件传递 props(sayHello) 时,就调用子组件的某个方法,或干脆调用父组件传递这个 props.
useEffect(() => props.sayHello
? sayHello(props.sayHello)
: console.error('sayHello is not passed'))
return (<div className="child" />)
}
export default Child;
当在父组件使用子组件时,只需要向子组件传递约定的 props,那么子组件将按照某种方式对传递的 props 进行处理,或者说是工作。
Child 的静态属性
// parent.tsx
import React from 'react';
import Child from "./child";
const Parent = () => (<UseExport />)
Child.say('Yomua'); // 控制台输出:Yomua
export default Parent;
// child.tsx
import React from 'react';
const Child = () => (<div>Child</div>)
// 为 Child 定义静态属性
Child.say = (v: any) => { console.log(v) }
export default Child;
由于子组件存在静态属性,所以父组件中只要导入子组件,就可以直接使用:子组件.静态属性
实例化子组件
// parent.tsx
import React, { Component } from 'react';
import Child from "./child";
const ClassParent = () => {
const getChildValue = () => {
let child = new ClassChild("")
child.childGet(); // 输出:0
}
return (
<div>
<ClassChild />
<button onClick={getChildValue}>获取子组件值</button>
</div>
)
}
export default Parent
// child.tsx
import {Component} from "react"
class ClassChild extends Component {
static childGet: Function;
state: { index: number, }
constructor(props: any) {
super(props)
this.state = { index: 0 }
}
// 这个方法 可以被父组件获取到(只要父组件实例化子组件即可)
childGet = () => { console.log(this.state.index) }
render() {return (<div>Child</div>) }
}
export default ClassChild;
由于父组件需要实例化子组件,所以子组件最好使用 class component 的形式,或者使用函数式组件(除了箭头式的函数式组件除外)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。