From vue2.0 to react17 – getting started with react development

Time:2022-6-21

preface

When looking for a job, I found that some companies use react as a technology stack, and the salary is good. In order to increase the chips for survival, I still have to learn react and add a survival skill. Because I have been developing projects with vue2.0 for four years, I use the idea of vue2.0 development projects to learn react.

Front end projects are composed of pages. For Vue, a page is composed of multiple components, and the page itself is also a routing component. The same is true for react. Vue will provide a series of technical support to complete the development of a component. Starting from this series of technical support, you can find the corresponding technical support in react to get started with react, such as how to develop the UI of components in react, how to use components in react, how to define component data in react, etc.

This column will follow this idea to lead you from vue2.0 to react17.

1. Scaffolding

First, select a scaffold to build a react project. React has many scaffolds. Why choose umijs? Why not? This scaffold is similar to Vue cli. At least the routing configuration is similar to Vue router.

Before learning, build a react project with umijs. The steps are very simple:

  • First, find a place to create an empty directory, open the command line tool, and execute the commandmkdir myapp && cd myapp
  • Execute commandnpm create @umijs/umi-appCreate a react project;
  • Execute commandnpm installInstallation dependency;
  • After the dependency is successfully installed, execute the commandnpm run startStart the project and open it in the browserhttp://localhost:8000Access the project.

You can see the directory structure of the react project myapp as follows:

.
├── package.json
├── .umirc.ts
├── .env
├── dist
├── mock
├── public
└── src
    ├── .umi
    ├── layouts/index.tsx
    ├── pages
        ├── index.less
        └── index.tsx
    └── app.ts
Copy code

Open umirc. TS file, the contents of which are as follows

import { defineConfig } from 'umi';

export default defineConfig({
  nodeModulesTransform: {
    type: 'none',
  },
  routes: [
    { path: '/', component: '@/pages/index' },
  ],
  fastRefresh: {},
});
Copy code

Its route is inroutesThe configuration in the options is very similar to that of Vue router. The specific configuration will be described later in route jump and parameter transmission.

Next insrc/pages/index.tsxWrite a demo in the file to learn react.

2. How to develop component UI in react

What is developed in Vue and react is a component, and its page is also a routing component. In Vue, components are defined in the suffix.vueIn react, the components are defined with the suffix.jsIf typescript is used to develop react, its components are defined in the.tsxIn the file.

How to develop the UI part of a component, such as developing a HelloWorld component to display on the browser pagehello world, the UI of a component includes HTML part and CSS part.

2.1 HTML part

For the HTML part of the component, Vue recommends using the template template, and react recommends using the JSX syntax.

In the projectsrc/pagesCreate a folderHelloWorld.jsFile to develop the HelloWorld component.

In addition, react components can be defined in two ways, one in function form and the other in ES6 class form.

Function form, called function component:

export default function HelloWorld() {
  return (
    <div>hello world</div>
  );
}
Copy code

The class form of ES6 is called class component:

import React from 'react';
export default class HelloWorld extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (
      <div>hello world</div>
    );
  }
}
Copy code

Note that the first letter of the function name should be capitalized。 In functionreturnLater, JSX syntax is used to develop the UI part of the component.

Also note that thereturnUse the outermost part of the following content()Enclose, otherwisereturnAt least one following the same line<Yes, as follows:

export default function HelloWorld() {
  return <
    div>hello world</div>
}
Copy code

Isn’t that weird, so you’d better add one()

2.2 binding class and style

For the CSS part of the component, the most important thing is to bind class and style to add styles to the HTML of the component.

First, let’s take a look at how class and style are fixed and bound in react.

export default function HelloWorld() {
  return (
    <div 
      className="title head"
      style={{color:'red',fontSize:'16px'}}
    >
      hello world
    </div>
  );
}
Copy code

Yes in reactclassNameTo bind class, usestyleTo bind style. amongstyleThe accepted value is an object, and{}Brackets are passed in, and the attribute name of an object can only be named in camelCase.

Let’s take a look at how class and style are bound in react.

  • Writing method of class component:
import React from 'react';
export default class HelloWorld extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      styleData: { color: 'red', 'fontSize': "16px" },
      isHead: true,
      className: 'title'
    };
  }

  render() {
    return (
      <div
        className={`${this.state.className} ${this.state.isHead ? 'head' : ''}`}
        style={this.state.styleData}
      >
        hello world
      </div>
    );
  }
}
Copy code
  • Writing method of function component:
import { useState } from 'react';
export default function HelloWorld() {
  const [styleData] = useState({ color: 'red', 'fontSize': "16px" });
  const [isHead] = useState(true);
  const [className] = useState('title');
  return (
    <div
      className={`${className} ${isHead ? 'head' : ''}`}
      style={styleData}
    >
      hello world
    </div>
  );
}
Copy code

Used in react{}Assign variables to attributes, andclassNameIt only accepts strings, not arrays or objects. You can use the template string function of ES6 to splice variables to generate strings.

In the writing of function componentsuseStateThis react hook defines some variables,useStateThe role of is described later.

3. How to use components in react

The HelloWorld component is written. How do you use it? First, review how components are used in Vue. Before using components, you must register them as global components or local components.

In react, there is no concept of registered component, because component is a function. There is only the concept of imported component, and there is no concept of global component. Must be used before using componentsimportFirst, introduce and name the components.

import HelloWorld from './HelloWorld.js'

export default function Index(){
  return (
    <HelloWorld/>
  )
}
Copy code

In react, component names must start with upper case letters, because react will treat components that start with lower case letters as native DOM Tags

4. How to define component data in react

From the experience of developing Vue components, the data of a component can be divided into internal data and parameter data. The same is true for react. In react, the internal data is called state and the parameter data is called props.

4.1 define internal data state

The process of how to bind class and style in variable form in react has been definedstyleDataisHeadclassNameThese internal data.

  • In a class component, thethis.stateData defined in this object:
this.state = {
  styleData: { color: 'red', 'fontSize': "16px" },
  isHead: true,
  className: 'title'
};
Copy code
  • Used in the writing of function componentsuseStateThis react hook defines the data:
const [styleData] = useState({ color: 'red', 'fontSize': "16px" });
const [isHead] = useState(true);
const [className] = useState('title');
Copy code

I personally recommend using the function form to develop react components. You can use react hook to avoid learning the class syntax in ES6 and annoyingthisPoint to problems to reduce the difficulty of getting started.

About react hookhere

4.2 define parameter data props

Props is used to receive external data passed to components. For example, defined in the HelloWorld componenttitleA parameter data.

  • Writing method of class component:
import React from 'react';
class HelloWorld extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (
      <div>{this.props.title}</div>
    );
  }
}
HelloWorld.defaultProps = {
  title: 'hello world'
};
export default HelloWorld;
Copy code

Constructor in class componentconstructoracceptpropsAs the parameter data collection of the incoming component, and callsuper(props)holdpropsPass toReact.ComponentConstructor so that class components can accept parameter data setsprops, reusethis.props.titleTo readtitleThe value of parameter data. In addition, you can usedefaultPropsTo definetitleDefault value for parameter data.

  • Writing method of function component:
import { useState } from 'react';
export default function HelloWorld(props) {
  const {title = 'hello world'} = props;
  return (
    <div>{title}</div>
  );
}
Copy code

Function component receives apropsAs a collection of parameter data of the incoming component, the function of ES6 deconstruction assignment is used to obtain the parameter data of the component, and the default value can be set for the parameter data.

You should pay attention hereIn Vue’s template, the{{}}(double brace) to use data, which is used uniformly in react{}(single brace) to use data.

The parameter data props is used to receive the external data transferred to the component. How to transfer the data to the component in react?

5. How to transfer data to components in react

Vue specifies how to transfer dynamic data and static data of string, number, Boolean value, array and object type to components. We look for how to transfer them in react one by one.

  • Transfer dynamic data
import { useState } from 'react';
import HelloWorld from './HelloWorld.js';
export default function Index(){
  const [styleData] = useState({ color: 'red', 'fontSize': "16px" });
  const [isHead] = useState(true);
  const [className] = useState('title');
  return (
    <HelloWorld 
       styleData={styleData} 
       isHead={isHead} 
       className={className}
    />
  )
}
Copy code
  • Passing static data of string type
<HelloWorld></HelloWorld>
Copy code
  • Passing static data of numeric type
<HelloWorld num={1}></HelloWorld>
Copy code
  • Passing static data of boolean type
<HelloWorld isHead={false}></HelloWorld>
Copy code
  • Passing static data of array type
<HelloWorld className={['title','head']}></HelloWorld>
Copy code
  • Passing static data of object type
<HelloWorld styleData={{color:'red','fontSize':"16px"}}></HelloWorld>
Copy code

It can be seen that in react, in addition to passing static data of string type, the{}The package data is then assigned to the attribute on the component label to pass the data to the component.

6. How to listen for DOM events in react

6.1 listening for DOM events of DOM elements

  • Writing method of class component:
import React from 'react';
export default class HelloWorld extends React.Component {
  constructor(props) {
    super(props);
    //This binding is necessary to use 'this' in callbacks
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    console. Log ('click event ');
  }

  render() {
    return (
      <div onClick={this.handleClick}>hello world</div>
    );
  }
}
Copy code
  • Writing method of function component:
export default function HelloWorld() {
  const handleClick = ()=>{
     console. Log ('click event ');
  }
  return (
    <div onClick={handleClick}>hello world</div>
  );
}
Copy code

Used in reactonClickTo monitor click events, use the{}The function executed when the package click event is triggered, and then assigned toonClick

amongonClickIs a composite event in Vue@Followed by the DOM native event, while in reacton后面跟着并不是DOM的原生事件。例如Vue中监听双击事件 @dblclick,而React中监听双击事件 onDoubleClick

React中的合成事件具体可以看这里

6.2 监听React组件的DOM事件

在Vue中用.native修饰符来监听组件上的DOM事件,而在React中监听组件上的DOM事件要这样实现。

例如在组件上监听click事件,先要把click事件触发时要执行的函数当作Props给组件传递进去,在组件的根元素上监听click事件,click事件触发时执行该Props,这样来间接监听组件上的click事件。具体实现如下所示:

  • 类组件的写法:
import React from 'react';
export default class HelloWorld extends React.Component {
  constructor(props:any) {
    super(props);
    console.log(this.props)
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.props.onClick();
  }

  render() {
    return (
      <div onClick={this.handleClick}>hello world</div>
    );
  }
}
复制代码
import React from 'react';
import HelloWorld from './HelloWorld';
export default class Grandfather extends React.Component {
  handleClick() {
    console.log('点击事件');
  }
  render() {
    return (
      <HelloWorld onClick={() => { this.handleClick() }}>
      </HelloWorld>
    )
  }
}
复制代码
  • 函数组件的写法:
export default function HelloWorld(props) {
  const { onClick } = props
  const handleClick = () => {
    onClick();
  }
  return (
    <div onClick={handleClick}>hello world</div>
  );
}
复制代码
import HelloWorld from './HelloWorld';
export default function Index(){
  const handleClick = ()=>{
    console.log('点击事件');
  }
  return (
    <HelloWorld onClick={() => { handleClick() }}>
    </HelloWorld>
  )
}
复制代码

7、React中组件如何改变数据

上面介绍了,React组件的数据分为内部数据state和参数数据props,对应的改变方法也不一样。

7.1 改变内部数据state

比如要改变组件中定义的内部数据title

  • 类组件的写法:
import React from 'react';
export default class HelloWorld extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      title: 'hello world',
      className: 'title'
    };
    // 为了在回调中使用 `this`,这个绑定是必不可少的
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.setState(state => ({
      title: 'hello react',
      className: 'title active'
    }));
  }

  render() {
    return (
      <div 
        className={className}
        onClick={this.handleClick}
      >{title}</div>
    );
  }
}
复制代码

this.setState()中可以传递一个函数或一个对象,建议传递一个函数(state,props) =>{},函数可以接受内部数据state和参数数据props作为参数,而且stateprops只读无法修改,每次调用this.setState时读取到的state和Props都是最新,特别适用多次调用this.setState修改同一个state的场景。最后函数放回一个对象,对象的内容为要修改的state。

  • 函数组件的写法:
import { useState } from 'react';
export default function HelloWorld() {
  const [title,setTitle] = useState('hello world');
  const [className,setClassName] = useState('title');
  const handleClick = () =>{
    setTitle('hello react');
    setClassName('title active')
  }
  return (
    <div 
      className={className} 
      onClick={handleClick}
    >
      {title}
    </div>
  );
}
复制代码

在React中称内部数据为state,使用useState(param)定义一个state时,可以通过参数param设置state的默认值,其返回一个数组,数组的第一个值是state,数组的第二个值是改变state的函数,可以调用该函数来改变state。

另外用useState定义的数据是响应式的,若页面有使用该数据,该数据改变后页面会重新渲染。

7.2 改变参数数据props

跟Vue一样,在组件中是不能直接改变props,假如要改变props,只能通过在父组件中改变传递给子组件的数据来间接改变props,那在子组件中怎么让父组件改变传递给子组件的数据呢,将在React中父子组件如何通讯介绍。

8、React中父子组件如何通讯

用一个例子来介绍,假如 HelloWorld 组件的 “hello world” 是用参数数据props中的title展示,点击组件中的改变标题按钮时变成 “hello React” 。

  • 类组件的写法:
import React from 'react';
class HelloWorld extends React.Component {
  constructor(props) {
    super(props);
    this.handleChangeTitle=this.handleChangeTitle.bind(this);
  }
  handleChangeTitle(){
    this.props.changeTitle('hello React');
  }
  render() {
    return (
      <div>
        {this.props.title}
        <button 
          onClick={this.handleChangeTitle.bind(this)}>
          改变标题
        </button>
      </div>
    );
  }
}
HelloWorld.defaultProps = {
  title: 'hello world'
};
export default HelloWorld;
复制代码
import HelloWorld from './HelloWorld.js'
import React from 'react'
class Index extends React.Component {
  constructor(props) {
    super(props);
    this.state={
      info:'hello world'
    };
    this.handleChangeTitle=this.handleChangeTitle.bind(this);
  }
  handleChangeTitle(data){
    this.setState(state =>{
      return {
        info:data
      }
    })
  }
  render() {
    return (
      <HelloWorld 
        title={this.state.info} 
        changeTitle={this.handleChangeTitle}>
      </HelloWorld>
    );
  }
}
export default Index;
复制代码
  • 函数组件的写法:
export default function HelloWorld(props: any) {
  const { title = 'hello world', changeTitle } = props;
  const handleChangeTitle = () => {
    changeTitle('hello React')
  }
  return (
    <div>
      {title}
      <button onClick={handleChangeTitle}>改变标题</button>
    </div>
  );
}
复制代码
import { useState } from 'react'
import HelloWorld from './HelloWorld.js'

export default function Index(){
  const [info,setInfo] = useState('hello world');
  const handleChangeTitle = (data)=>{
    setInfo(data);
  }
  return (
    <HelloWorld title={info} changeTitle={handleChangeTitle}/>
  )
}
复制代码

在父组件中定义一个info数据传递给子组件的title参数数据,同时也定义了一个回调函数handleChangeTitle来改变info数据,并把回调函数也传递给子组件的changeTitle参数数据。

这样子组件的changeTitle参数数据可以作为一个函数来调用,调用changeTitle时相当调用handleChangeTitle回调函数,可以把要改变的值通过data函数参数传递出来,再执行setInfo(data)改变info数据,再传递给子组件的title参数数据,间接改变了title参数数据,实现了React中组件如何改变参数数据。

在父组件中也可以调用setInfo改变传递给子组件的title参数数据的info数据,以上就是React中父子组件通讯的一个方法。

9、React中如何监听组件数据的变化

在Vue中可以用简单地用watch来监听数据的变化,而在React中比较复杂,子组件的类型不同实现方法也不同。

  • 类组件的写法:

在类组件中用componentDidUpdate这个生命周期方法来实现,该方法首次渲染时componentDidUpdate不会执行,在后续props和state改变时会触发componentDidUpdate,其接受的第一个参数prevProps代表改变前的props,第二参数prevState代表改变前的state。

componentDidUpdate(prevProps, prevState){
  if(prevProps.title !== this.props.title){
     console.log('props中的title数据改变了');
  }
  if(prevState.info !== this.state.info){
     console.log('state中的info数据改变了');
  }
}
复制代码
  • 函数组件的写法

在函数组件中,可以useEffect这个React Hook监听数据的变化,但是无法像Vue的watch能够获取改变前的旧数据。所以要自定义一个Hook来实现类似Vue的watch的功能。自定义Hook是一个函数,其名称以 “use” 开头,函数内部可以调用其他的 Hook。故把这个自定义Hook称为useWatch

如何获取改变前的旧数据,可以在第一次数据改变时触发useWatch时用一个容器把旧数据存储起来,下次再触发useWatch时通过读取容器中的值就可以获取改变前的旧数据。容器可以用useRef这个 Hook 来创建。

useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数(initialValue)。返回的 ref 对象在组件的整个生命周期内保持不变。

import {useEffect,useRef} from 'react';
export function useWatch(value,callback){
  const oldValue = useRef();
  useEffect(() =>{
    callback(value,oldValue.current);
    oldValue.current=value;
  },[value])
}
复制代码

但是useEffect会在组件初次渲染后就会调用一次,导致callback回调函数会被执行一次,另外在Vue的watch是用immediate配置来控制在组件初次渲染后马上执行callback回调函数,且默认不会在组件初次渲染后执行callback回调函数,接着在hook.js中定义一个useWatch

首先实现一下组件初次渲染不执行callback回调函数。

import {useEffect,useRef} from 'react';
export function useWatch(value,callback){
  const oldValue = useRef();
  const isInit = useRef(false);
  useEffect(() =>{
    if(!isInit.current){
      isInit.current = true;
    }else{
      callback(value,oldValue.current);
    }
    oldValue.current=value;
  },[value])
}
复制代码

再添加immediate配置来控制在组件初次渲染后是否马上执行callback回调函数。

import {useEffect,useRef} from 'react';
export function useWatch(value,callback,config={immediate: false}){
  const oldValue = useRef();
  const isInit = useRef(false);
  useEffect(() =>{
    if(!isInit.current){
      isInit.current = true;
      if(config.immediate){
        callback(value,oldValue.current);
      }
    }else{
      callback(value,oldValue.current);
    }
    oldValue.current=value;
  },[value])
}
复制代码

另外Vue的watch还返回一个unwatch函数,调用unwatch函数可以停止监听该数据。

import { useEffect, useRef } from 'react';
export function useWatch(value, callback, config = { immediate: false }) {
  const oldValue = useRef();
  const isInit = useRef(false);
  const isWatch = useRef(true);
  useEffect(() => {
    if (isWatch.current) {
      if (!isInit.current) {
        isInit.current = true;
        if (config.immediate) {
          callback(value, oldValue.current);
        }
      } else {
        callback(value, oldValue.current);
      }
      oldValue.current = value;
    }
  }, [value])

  const unwatch =  () => {
    isWatch.current = false;
  };
  return unwatch;
}
复制代码

useWatch 这个Hook 定义好后,这么使用。

export {useState} from 'react';
export {useWatch} from './hook.js';
export default function HelloWorld() {
  const [title,setTitle] = useState('hello world')
  useWatch(title, (value, oldValue) => {
    console.log(value);
    console.log(oldValue)
  })
  const handleChangeTitle = () => {
    setTitle('hello React')
  }
  return (
    <div onClick={handleChangeTitle}>{title}</div>
  );
}
复制代码

10、React中父组件如何调用子组件的方法

在Vue中是使用ref给子组件赋予一个标识 ID ,再使用this.$refs[ID]访问到这个子组件的实例对象,然后通过实例对象去调用子组件的方法。而在React中比较复杂,子组件的类型不同实现方法也不同。

  • 类子组件的写法:
import React from 'react';
export default class HelloWorld extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      title:'hello World'
    };
  }
  handleChangeTitle(){
    this.setState({
      title:'hello React'
    });
  }
  render() {
    return (
      <div>
        {this.state.title}
      </div>
    );
  }
}
复制代码
import React from 'react';
import HelloWorld from './HelloWorld.js';

class Index extends React.Component {
  constructor(props) {
    super(props)
    this.myCom = React.createRef();
    this.changeTitle = this.changeTitle.bind(this);
  }
  changeTitle() {
    this.myCom.current.handleChangeTitle();
  }
  render() {
    return (
      <div>
        <HelloWorld ref={this.myCom} />
        <button onClick={this.changeTitle}>改变标题</button>
      </div>
    )
  }
}
export default Index;
复制代码
  • 函数组件的写法:

useRef()无法使用在函数组件上使用,在函数组件中要先使用 useImperativeHandle 定义要暴露给父组件的实例值,另外要把函数组件传入forwardRef处理后再导出。

import { useState, forwardRef, useImperativeHandle } from 'react';

const HelloWorld = (props, ref) => {
  const [title, setTitle] = useState('hello World');
  useImperativeHandle(ref, () => ({
    handleChangeTitle: () => {
      setTitle('hello React')
    },
  }));
  return (
    <div>{title}</div>
  );
}
export default forwardRef(HelloWorld)
复制代码
import { useRef } from 'react'
import HelloWorld from './HelloWorld.js'

export default function Index() {
  const myCom = useRef();
  const changeTitle = () => {
    myCom.current.handleChangeTitle();
  }
  return (
    <div>
      <HelloWorld ref={myCom} />
      <button onClick={changeTitle}>改变标题</button>
    </div>
  )
}
复制代码

11、React中组件插槽怎么实现

11.1 普通插槽

其实React中是没有插槽的概念,不过可以用props.children来实现插槽的功能。

每个组件都可以获取到 props.children。它包含组件的开始标签和结束标签之间的内容。

例如开发一个 HelloWorld 组件用来展示 “ hello World ” ,也可以用插槽的形式来实现,通过props.children把 “ hello World ” 从父组件传递进去。

类组件的写法:

import React from 'react';
export default class HelloWorld extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
      <div>
        {this.props.children}
      </div>
    );
  }
}
复制代码
import React from 'react';
import HelloWorld from './HelloWorld.js';
class Index extends React.Component{
  constructor(props) {
    super(props);
  }
  render() {
    return (
      <HelloWorld>hello World</HelloWorld>
    )
  }
}
export default Index;
复制代码

函数组件的写法:

export default function HelloWorld(props){
  const {children}=props;
  return (
    <div>
      {children}
    </div>
  );
}
复制代码
import HelloWorld from './HelloWorld.js';
export default function Index(){
  return (
    <HelloWorld>hello World</HelloWorld>
  )
}
复制代码

11.2 具名插槽

可以通过props给子组件传递一个函数,如果这个函数最后返回React元素,其React元素是用JSX语法编写的,这样就间接实现具名插槽的功能。

例如开发一个 HelloWorld 组件用来展示 “ hello World ” ,用具名插槽的形式来实现。

类组件的写法:

import React from 'react';
class HelloWorld extends React.Component{
  constructor(props){
    super(props)
    this.elementSlot = "";
    if (this.props.element) {
      this.elementSlot = this.props.element();
    }
  }
  render(){
    return (
      <div>
        {this.elementSlot}
      </div>
    );
  }
}
export default HelloWorld;
复制代码
import React from 'react';
import HelloWorld from './HelloWorld.js';
class Index extends React.Component{
  constructor(props) {
    super(props);
  }
  info(){
    return(
      <span>hello World</span>
    )
  }
  render() {
    return (
      <HelloWorld element={this.info}></HelloWorld>
    )
  }
}
export default Index;
复制代码

函数组件的写法:

export default function HelloWorld(props) {
  const { children, element } = props;
  let elementSlot = "";
  if (element) {
    elementSlot = element();
  }
  return (
    <div>
      {elementSlot}
    </div>
  );
}
复制代码
import HelloWorld from './HelloWorld.js';

export default function Index(){
  const info = () =>{
    return (
      <span>hello World</span>
    )
  }
  return (
    <HelloWorld element={info}></HelloWorld>
  )
}
复制代码

11.3 作用域插槽

Vue的作用域插槽的作用是用子组件中的数据在父组件中写插槽内容。

回顾上面具名插槽的实现过程,先在父组件中定义一个函数,该函数能返回一个React元素,再通过props把该函数传递给子组件,在子组件中执行该函数,把执行结果添加到子组件的React元素中。

如果在子组件中执行该函数时,把子组件的数据当作参数传递进去,那么在父组件中就可以用该函数接收子组件的数据来写React元素(插槽的内容)。这样就实现了作用域插槽。

例如开发一个 HelloWorld 组件用来展示 “ 用子组件的数据写具名插槽 hello World ” ,用作用域插槽的形式来实现。

类组件的写法:

import React from 'react';
class HelloWorld extends React.Component{
  constructor(props){
    super(props)
    this.state = {
      info:'用子组件的数据写具名插槽 hello World'
    }
    this.elementSlot = "";
    if (this.props.element) {
      this.elementSlot = this.props.element(this.state.info);
    }
  }
  render(){
    return (
      <div>
        {this.elementSlot}
      </div>
    );
  }
}
export default HelloWorld;
复制代码
import React from 'react';
import HelloWorld from './HelloWorld.js';
class Index extends React.Component{
  constructor(props) {
    super(props);
  }
  info(data){
    return(
      <span>{data}</span>
    )
  }
  render() {
    return (
      <HelloWorld element={this.info}>
      </HelloWorld>
    )
  }
}
export default Index;
复制代码

函数组件的写法

import { useState } from "react";

export default function HelloWorld(props) {
  const { children, element } = props;
  const [info] = useState('用子组件的数据写具名插槽 hello World')
  let elementSlot = "";
  if (element) {
    elementSlot = element(info);
  }
  return (
    <div>
      {elementSlot}
      {children}
    </div>
  );
}
复制代码
import HelloWorld from './HelloWorld.js';

export default function Index(){
  const info = (data) =>{
    return (
      <span>{data}</span>
    )
  }
  return (
    <HelloWorld element={info}></HelloWorld>
  )
}
复制代码

小结

以上从Vue开发一个组件会用到的技术,在React中寻找对应的实现方案的角度来入门React,读完你应该会用React开发一些简单的页面,并能把页面分割成一个个组件,并在组件之间进行数据交互。下一篇文章将介绍开发组件时在Vue中那些常用的指令在React中是如何实现的

作者:红尘炼心
链接:https://juejin.cn/post/6975864046058733576

Recommended Today

JS generate guid method

JS generate guid method https://blog.csdn.net/Alive_tree/article/details/87942348 Globally unique identification(GUID) is an algorithm generatedBinaryCount Reg128 bitsNumber ofidentifier , GUID is mainly used in networks or systems with multiple nodes and computers. Ideally, any computational geometry computer cluster will not generate two identical guids, and the total number of guids is2^128In theory, it is difficult to make two […]