前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >react修仙笔记,请问仙溪几级了?

react修仙笔记,请问仙溪几级了?

作者头像
Maic
发布2022-12-21 19:15:01
4150
发布2022-12-21 19:15:01
举报
文章被收录于专栏:Web技术学苑Web技术学苑

react在企业项目中已经变成了一个必不可少的UI框架,从过去早期有jquery,后面有bootstrap兴起,jquery可以说二次封装的原生jsbootstarp可以快速搭建一个精美网页,现在基本很少用bootstrapjquery了,基本上vuejs,reactangular三分天下,国内vuejsreact居多,angular很少用,本文是一篇笔者关于react相关的笔记,希望看完在项目中有所思考和帮助。

在开始本文之前,主要会从以下几个方面去认识学习react

1、没有概念,用实际例子感受react核心思想

2、react数据流是怎么样,父子通信,react是如何更新数据

3、class组件与纯函数组件

4、react的状态提升

5、react组合概念

6、react设计哲学

正文开始...

class组件

react的理念就是构建UI的一个库,很大一个特征就是申明式组件化跨平台

  • 申明式
代码语言:javascript
复制

import React from "react";
import ReactDOM from 'react-dom/client';
class HelloMessage extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    }
  }
  render() {
    return (
      <div>
        Hello {this.props.name}
      </div>
    );
  }
}
const root = ReactDOM.createRoot(document.getElementById('hello-example'))
root.render(<HelloMessage name="Web技术学苑" />);

从以上我们知道就是用class申明了一个HelloMessage的组件,继承了React.Component组件,然后通过root.render(<HelloMessage />)挂载到dom上,我们也会发现HelloMessage这个class组件中的render中返回的就是一个jsx,这就是挂载在dom上的具体内容

纯函数组件

以上是class方式写的一个组件,但是从react16.8 版本后就出现了hook,也就是过去纯函数组件没有自己的状态,但是有了hook后,纯函数组件就可以有自己的状态了。我们完全可以用函数组件hook替代class组件,上面一段代码,如果用函数组件就是下面这样的

代码语言:javascript
复制

import React, { useState } from "react";
import ReactDOM from 'react-dom/client';
const HelloMessage = (props) => {
 const [count, setCount] = useState(0);
  return (
      <div>
        Hello {props.name}
      </div>
    );
}
const root = ReactDOM.createRoot(document.getElementById('hello-example'))
root.render(<HelloMessage name="Web技术学苑" />);

状态提升

我们知道每个组件有自己的state,如果同一个组件内部都是自己的state,那么组件之间就是互相独立,但是此时我想让一个组件输入值,也会影响另一个组件,那么此时就需要两个组件的数据依赖来源就必须提升到父组件里去,所以这就是状态提升。

我们以人民币换算美元汇率的例子加深对状态提升概念的理解

代码语言:javascript
复制

import React from "react";
class List extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            count: 0,
            price: 0,
            type: 0, // 0 人民币 1 代表美元
        }
    }
    handleAdd = () => {
        // this.setState({
        //     count: ++this.state.count
        // })
        this.setState(state => {
            return {
                ...state,
                count: state.count + 1
            }
        })
    }
    handleReduce = () => {
        this.setState(state => {
            return {
                count: state.count - 1
            }
        })
    }
    handleRmbInput = (e) => {
        const val = e.target.value;
        console.log(e)
        this.setState({
            price: val,
            type: 0
        })
    }
    handleDollInput = (e) => {
        const val = e.target.value;
        this.setState({
            price: val,
            type: 1
        })
    }


    render() {
        const { count, price, type } = this.state;
        const RmbInput = ({ price, handleChange }) => {
            return (<fieldset>
                <legend>人民币</legend>
                <input value={price}
                    onChange={handleChange} />
            </fieldset>)
        };
        const DollarInput = ({ price, handleChange }) => {
            return (<fieldset>
                <legend>美元</legend>
                <input value={price}
                    onChange={handleChange} />
            </fieldset>)
        };
        const rmbVal = type === 0 ? price : price * 7.34;
        const dollVal = type === 1 ? price : 0.14 * price;
        return (<div className="list-app" style={{ padding: '10px' }}>
            <hr />
            <button onClick={this.handleAdd}>+</button>
            <span>{count}</span>
            <button onClick={this.handleReduce}>-</button>
            <hr />
            <RmbInput handleChange={this.handleRmbInput} price={rmbVal} />
            <hr></hr>
            <DollarInput handleChange={this.handleDollInput} price={dollVal} />
        </div>)
    }
}
export default List

我们看到List这个组件返回的有RmbInputDollarInput组件,你会发现实际上这两个组件的共同特征就是都传入了两个props到子组件中,注意其中一个是传入的是方法handleChange,通常在react中数据流是单向的,所以修改传入的子组件的props,通常是通过父组件的传入子组件的回调方法去修改传入子组件的props

比如说下面这样一段伪代码

代码语言:javascript
复制

// Parant
function Parent() {
  const { name, setName} = useState("Web技术学苑");
  return (<div>
    <h1>{name}</h1>
    <Child name={name} onChangeName={val => setName(val)}/>
  </div>)
}


// Child
function Child(props) {
  return (<div>
    <input value={props.name} onChange={e => props.onChangeName(e.target.value)}/>
  </div>)
}

最后我们看下最终的效果

因此一个计算汇率的功能就OK了

但是我们发现实际上RmbInputDollarInput做的事情都是非常类似的,只有名称不一样,因此我们可以将这两个组件合并成一个组件,只需传入一个参数来判断名称即可。

代码语言:javascript
复制

import React from "react";
class List extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            count: 0,
            price: 0,
            type: 0, // 0 人民币 1 代表美元
        }
    }
   ...
   render() {
        const { count, price, type } = this.state;
        // 合并成一个组件了
        const ExchangeInput = ({ price, handleChange, type }) => {
            return (<fieldset>
                <legend>{type === "RmbInput" ? '人民币' : '美元'}</legend>
                <input value={price}
                    onChange={handleChange} />
            </fieldset>)
        }
        const rmbVal = type === 0 ? price : price * 7.34;
        const dollVal = type === 1 ? price : 0.14 * price;
        return (<div className="list-app" style={{ padding: '10px' }}>
            <hr />
            <button onClick={this.handleAdd}>+</button>
            <span>{count}</span>
            <button onClick={this.handleReduce}>-</button>
            <hr />
            <ExchangeInput handleChange={this.handleRmbInput} price={rmbVal} type="RmbInput"></ExchangeInput>
            <hr/>
            <ExchangeInput handleChange={this.handleDollInput} price={dollVal} type="DollarInput"></ExchangeInput>
        </div>)
    }
}
export default List

因此从状态提升来看,react组件的state本该相互独立,但是如果想实现一个组件修改关联另一个组件修改,那么数据来源必须依赖父组件,所以也就只能把当前组件的state提升到父组件里去,从而实现了状态提升。

这里我们也发现,react提供给子组件的通信就是props,修改当前组件的state就是依赖setState,要想修改父组件数据就是通过props传入子组件的回调去修改的。

react组合

在react组合类似vue的插槽一样的概念,不过有些区别

props.children就是默认渲染所有父组件的插槽内容

代码语言:javascript
复制

import React from "react";
const Title = (props) => {
    return (<div className="title" style={{ display: 'flex' }}>
        {props.children}
    </div>)
}
const About = () => <div>
    <Title>
        <h1>Web技术学苑</h1>
        <div>Maic</div>
    </Title>
</div>


export default About;

这样你看到的结果就是下面这样的

你也可以通过props做类似的vue具名插槽的功能

代码语言:javascript
复制

import React from "react";
const Title = (props) => {
    return (<div className="title" style={{ display: 'flex' }}>
        {props.children}
    </div>)
}
const Content = (props) => {
    return (<div className="content" style={{ ...props.style }}>
        {props.left}
        {props.children}
        {props.right}
    </div>)
}
const About = () => {
    const Left = () => (<div>left</div>);
    const Right = () => (<div>right</div>);
    return (<div>
        <Title>
            <h1>Web技术学苑</h1>
            <div>Maic</div>
        </Title>
        <Content 
          style={{ padding: '10px' }} 
          left={<Left />} 
          right={<Right />}
        >
          <div>center</div>
        </Content>
    </div>)
}
export default About;

我们发现Content这个组件的props可以是对象,可以是jsx,也可以是函数,当子组件用父组件的props时,我们就当它变量一样在子组件中使用,因此react中的props是相当灵活的。

react哲学

react哲学[1]官方已经用了一篇文章来阐述,通篇下来,官网已经用了一个实际例子来解释react的哲学思想,总结下来,其实就是以下几点。

1、如何将复杂的UI模块拆分成更细粒度的组件,我们将一个页面拆分成组件,组件依赖数据更清晰,组件之间的耦合度更低。

2、组件的接口propsstate,要明确知道当前组件的state是应该放在顶层父组件中,还是当前自身组件

3、因为react数据流是单向的,在实现父子组件数据流双向过程中,通常用回调来传递子组件向父组件传递的数据

官方把react哲学分成了五步走概念,关于组件的拆分,其实我们心里在写代码之前就应该明白哪些组件适合独立拆分,哪些组件不用拆分,当一个页面过于复杂时,此时我们考虑拆分组件的同时,也需要考虑是否组件过度拆分带来的负担,这个因具体情况而定

总结

  • 理解react构建UI的两种方式,一种是class方式,一种纯函数组件方式
  • react数据通信,父子组件如何通信
  • 当多个组件存在互相影响时,此时得考虑状态提升,每个独立的组件状态数据依赖来源必须从顶层组件中传入,并且当需要更新props时,考虑回调函数修改
  • react中实现vue插槽的功能,也就是react的组合,props.children会默认渲染父组件插槽功能,通过props指定jsx可以可以实现具名插槽功能
  • 理解react哲学思想,让我们更灵活的运用react构建一个完整,维护性很强的web应用
  • code example[2]

参考资料

[1]react哲学: https://react.docschina.org/docs/thinking-in-react.html

[2]code example: https://github.com/maicFir/lessonNote/tree/master/react/01-react-demo

最后,看完觉得有收获的,点个赞,在看,转发,收藏等于学会,欢迎关注Web技术学苑,好好学习,天天向上!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-11-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Web技术学苑 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • class组件
  • 纯函数组件
  • 状态提升
  • react组合
  • react哲学
  • 总结
  • 参考资料
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档