likes
comments
collection
share

通过vue3学习react17(二) - 父组件调用子组件方法Ref(ts)

作者站长头像
站长
· 阅读数 25

今天主要学习ref方法去调用子组件的方法, react hook和vue 单文件都使用到

喜欢的可以点赞

React

useRef 仅能用在 FunctionComponent,createRef 仅能用在 ClassComponent。

使用useRef

子组件(Child.tsx)
# Child.tsx
export interface ChildProps {
  count: number;
  setCount: (params: ChildProps["count"]) => void;
}

const Child = (_props: any, ref: any) => {
  let [count, setCount] = useState(0);
  useImperativeHandle(ref, () => ({
    count,
    setCount,
  }));
  return (
    <div>
      <p>{count}</p>
    </div>
  );
};
export default Child;
# or
export interface ChildProps {
  count: number;
  setCount: (params: ChildProps["count"]) => void;
}

interface refInterface {
  cRef: React.MutableRefObject<ChildProps | undefined>;
}

const Child: React.FC<refInterface> = (props) => {
  const { cRef } = props;
  let [count, setCount] = useState(0);
  useImperativeHandle(cRef, () => ({
    count,
    setCount,
  }));
  return (
    <div>
      <p>{count}</p>
    </div>
  );
};

export default Child;
父组件(Parent.tsx)
# Parent.tsx
function Parent() {
  const childRef = useRef<ChildProps>();
  const updateChildState = () => {
    // changeVal就是子组件暴露给父组件的方法
    childRef.current?.setCount(childRef.current?.count + 1);
  };
  return (
    <div>
      <Child ref={childRef}></Child>
      <button onClick={updateChildState}>按钮</button>
    </div>
  );
}
createRef
子组件(Child.tsx)
import React, { useState } from "react";
interface ChildInterface {
  count: number;
}

class Child extends React.Component<unknown, ChildInterface> {
  constructor(props: React.FC) {
    super(props);
    this.state = {
      count: 0,
    };
  }
  render() {
    return (
      <div>
        <p>{this.state.count}</p>
      </div>
    );
  }

  setCount = (params: number) => {
    this.setState({
      count: params,
    });
  };
}

export default Child;
父组件(Parent.tsx)
import Child from "./Child";

class Parent extends React.Component {
  childRef: RefObject<Child>;
  // childRef: LegacyRef<Child> | undefined;
  constructor(props: React.FC) {
    super(props);
    this.childRef = createRef();
  }

  render() {
    return (
      <div>
        <Child ref={this.childRef}></Child>
        <button onClick={this.updateChildCount}>按钮</button>
      </div>
    );
  }
  updateChildCount = () => {
    let { setCount, state } = this.childRef.current as Child;
    setCount(state.count + 1);
  };
}

export default Parent;

Vue3

父组件兼容二个写法

父组件(Parent.vue)

# Parent.vue
<template>
  <Child ref="childRef"></Child>
  <button @click="onClick">按钮</button>
</template>

<script setup lang="ts">
import { ref } from "vue";
import Child from "./Child.vue";

const childRef = ref<InstanceType<typeof Child>>();
const onClick = () => {
  console.log(childRef.value);
  childRef.value?.setCount(childRef.value?.count + 1);
  childRef.value?.setCount2(childRef.value?.count2 + 1);
};
</script>

常规写法

子组件(Child.vue)
# Child.vue
<template>
  <div>
    <p>count: {{ count }}</p>
    <p>count2: {{ count2 }}</p>
  </div>
</template>

<script lang="ts">
import { ref, defineComponent, Ref } from "vue";

export default defineComponent({
  data() {
    return {
      count2: 2,
    };
  },
  methods: {
    setCount2(param: number) {
      this.count2 = param;
    },
  },
  setup() {
    let count = ref(0);
    function setCount(param: number) {
      count.value = param;
    }
    return {
      count,
      setCount,
    };
  },
});
</script>

单文件写法(setup)

<template>
  <div>
    <p>{{ count }}</p>
  </div>
</template>

<script setup lang="ts">
import { ref } from "vue";

const count = ref(0);
function setCount(param: number) {
  count.value = param;
}

defineExpose({
  count,
  setCount,
});
</script>

<style scoped></style>