React学习笔记(基础篇)

React学习笔记(基础)

  本文主要依据react官网的学习脉络,记录自己的学习过程,同时添加了个人见解,如有理解不妥的地方欢迎评论

1.React介绍

​ react由facebook公司推出,因为该公司不满足于市面上现有的前端框架,他们认为MVC只会让前端越来越复杂,因此react就诞生了,react只关注与视图层,官方对react的定位是:一个快速构建前端视图的javaScript库。

2.React的特点

  1. 虚拟DOM

    ​ 如果没有虚拟DOM,每次DOM改变的时候,都需要在浏览器中进行渲染。每一次DOM改变的时候,浏览器都需要重新计算CSS,进行布局处理,然后重新渲染页面,这都需要时间。而虚拟DOM完成的事情是最小化DOM改变,然后批处理DOM变化,在必要的时候才重新渲染页面。

    ​ 例如:当前页面显示的

    张三

    李四

    ,当我添加

    王五

    时,DOM会重新渲染3个标签,虚拟DOM则可以直接在后面加上新增加的

    王五

  2. 组件化

    • 什么是组件化

      return <>
          <Modal visible={modalVisible} title={editId ? `修改` : `新增`} onCancel={handleModalClose}
                 onOk={handleSubmit}>
              <RfidTagForm ref={formRef} editId={editId}/>
          </Modal>
      </>
      
      ......
      const RfidTagForm = forwardRef<RfidTagFormHandle,RfidTagFormProps>(({editId}, componentRef) => {
          const [form] = Form.useForm()
          const { resetFields, setFieldsValue, validateFields } = form;
      
      ......
      
          return <Form form={form} layout={'vertical'}>
              <Form.Item label={`罐号`} name={`potNum`}>
                  <Input/>
              </Form.Item>
              <Form.Item label={`标签卡ID`}>
                  <Row gutter={8}>
                      <Col span={12}>
                          <Form.Item name={`tagId`}>
                              <Input/>
                          </Form.Item>
                      </Col>
                      <Col span={12}>
                          <Button type={"primary"} onClick={handleReadTag}>读取卡号</Button>
                      </Col>
                  </Row>
              </Form.Item>
          </Form>
      })
      export default RfidTagForm
      

      代码中RfidTagForm即为组件,它接受任意的入参(即 “props”),并返回用于描述页面展示内容的 React 元素。

    • 组件化有两个显著的特点:

      封装:一个组件所需的数据封装于组件内部;

      组合:一个组件可以与其他组件通过组合的方式实现更加复杂的业务逻辑;

  3. 声明式代码

    声明式代码指的是:让开发者按照“我要做什么”,而不是“我要让计算机做什么”去思考如何实现业务需求。

    感受到天气太热,编写代码为例:

    • 命令式代码:

      1.拿起空调遥控器; 2.打开空调;3. 设置温度为 27 摄氏度;

    • 声明式代码:

      1. 调用“开空调(27)”函数;

  4. 纯粹的JavaScript语法

    ​ 在 React 中,没有任何特殊的专有的 React 语法需要理解和记忆,所有的组件,数据操作,业务逻辑都是通过使用 JavaScript 语法实现的。

    ​ 这意味着你想要使用 React 只需理解 React 的思想和几个关键的 API 就可以立即开始使用 React 进行复杂应用的开发。并且 React 还鼓励你使用函数式编程思想进行开发,你可以在 React 开发中,使用你的任何函数式编程技巧。

3.环境搭建

比较简单,网上有很多。

React环境搭建链接

这里建议在github上下载一个nvm,node的版本管理工具,亲测好用。

4.核心概念

4.1JSX

个人理解:用js写html的内容,其格式比较像是html语言,但事实上是编译后会变成js函数被调用

示例:

function formatName(user) {
  return user.firstName + ' ' + user.lastName;
}

const user = {
  firstName: 'Harper',
  lastName: 'Perez'
};

const element = (
  <h1>	Hello, {formatName(user)}!  </h1>
);

ReactDOM.render(
  element,
  document.getElementById('root')
);

Babel 会把 JSX 转译成一个名为 React.createElement() 函数调用。

以下三种代码完全相同

const element = (
  <h1 className="greeting">
    Hello, world!
  </h1>
);
const element = React.createElement(
  'h1',
  {className: 'greeting'},
  'Hello, world!'
);
const element = {
  type: 'h1',
  props: {
    className: 'greeting',
    children: 'Hello, world!'
  }
};

4.2 元素&组件

元素是构成 React 应用的最小砖块,它描述了你在屏幕上想看到的内容,与浏览器的 DOM 元素不同,React 元素是创建开销极小的普通对象。React DOM 会负责更新 DOM 来与 React 元素保持一致。

示例:

const element = <h1>Hello, world</h1>;

此处区分一下元素组件:

元素:

const element = React.createElement(
  'h1',
  {className: 'greeting'},
  'Hello, world!'
);

组件分为两种:函数式组件&&class组件

函数式:const Element= () => React.createElement(...)

class组件:

import React from 'react'
import ReactDOM from 'react-dom'

class App extends React.Component {
render () {
  return (
    // 注意这里得用this.props.name, 必须用this.props
    <h1>欢迎进入{this.props.name}的世界</h1>
	)
}
}
export default App;

无论是函数式组件还是class组件,目的都是为了返回一个元素.由此可以看出元素和组件的区别。

组件可以接收任何入参,即Props.例如 我们刚刚定义的App组件做里使用到了this.props.name,那么我们在使用此组件的时候就可以给他传一个 name参数供其使用.具体如下:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

ReactDOM.render(
  <React.StrictMode>
    <App name="Sara" />
  </React.StrictMode>,
  document.getElementById('root')
);

注意:为了让react可以区分dom原有标签和自己定义的组件,在定义组件时首字母要大写.

Props具有只读性,在组件中对拿到的props不可进行修改操作,

正确:

function sum(a, b) {  return a + b;}

错误:

function withdraw(account, amount) {  account.total -= amount;}

4.3 State&生命周期

首先介绍State,state与props类似,不过state是私有的,只在当前组件使用,与props用于传参不同

每次组件更新时 render 方法都会被调用,但只要在相同的 DOM 节点中渲染 <Clock /> ,就仅有一个 Clock 组件的 class 实例被创建使用。这就使得我们可以使用如 state 或生命周期方法等很多其他特性。(啥意思)

挂载&卸载

​ 当 Clock组件第一次被渲染到 DOM 中的时候,就为其设置一个计时器。这在 React 中被称为“挂载(mount)”。

同时,当 DOM 中 Clock 组件被删除的时候,应该清除计时器。这在 React 中被称为“卸载(unmount)”。

生命周期函数:

  • componentDidMount() 方法会在组件已经被渲染到 DOM 中后运行,组件挂载完成时触发的函数
  • 组件将要挂载时触发的函数:componentWillMount
  • 是否要更新数据时触发的函数:shouldComponentUpdate
  • 将要更新数据时触发的函数:componentWillUpdate
  • 数据更新完成时触发的函数:componentDidUpdate
  • 组件将要销毁时触发的函数:componentWillUnmount
  • 父组件中改变了props传值时触发的函数:componentWillReceiveProps

正确地使用state

不要直接修改 State

例如,此代码不会重新渲染组件:

// Wrongthis.state.comment = 'Hello';

而是应该使用 setState():

// Correctthis.setState({comment: 'Hello'});

4.4 事件处理

使用:

  • React 事件的命名采用小驼峰式(camelCase),而不是纯小写。
  • 使用 JSX 语法时你需要传入一个函数作为事件处理函数,而不是一个字符串。

react中如果需要使标签的默认事件不生效的方法:

import React, {Component} from 'react';

class Button extends React.Component{
    doClick(e){
        //阻止标签的默认事件
        e.preventDefault();
        alert("do click");

    }
    render(){
        return (
            <a href="https://www.baidu.com/" onClick={this.doClick}>
                事件处理测试
            </a>
        )
    }
}
export default Button

重点:

你必须谨慎对待 JSX 回调函数中的 this,在 JavaScript 中,class 的方法默认不会绑定 this。如果你忘记绑this.handleClick并把它传入了 onClick,当你调用这个函数的时候 this 的值为 undefined

关于为组件添加事件时,要注意this的绑定问题.(个人理解:组件在渲染时已经不在当前组件内,此时的this指向的不是我们所需要的组件),所以要加一个this绑定:

绑定方法一:

class Toggle extends React.Component {
  constructor(props) {
    super(props);
    this.state = {isToggleOn: true};
    // 为了在回调中使用 `this`,这个绑定是必不可少的    
    this.handleClick = this.handleClick.bind(this);  }

  handleClick() {
      this.setState(state => ({
          isToggleOn: !state.isToggleOn    
      }));  
  }
  render() {
    return (
      <button onClick={this.handleClick}>        
            {this.state.isToggleOn ? 'ON' : 'OFF'}
      </button>
    );
  }
}
export default Toggle

绑定方法二(和一类似):

import React, {Component} from 'react';

class Toggle extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            isToggeleOn: true
        }
        console.log("constructor()"+this)
        // 把this绑定给handleclick事件
        // this.handleClick = this.handleClick.bind(this);
    }

    handleClick(title) {
        alert(title)//输出abc
        console.log("handleClick()"+this)
        this.setState(state => ({
            isToggeleOn: !state.isToggeleOn
        }))
    }

    render() {
        return(
            // 把this绑定给handleclick事件
            <button onClick={this.handleClick.bind(this,"abc")}>
                {this.state.isToggeleOn ? 'ON':'OFF'}
            </button>
        )
    }
}
export  default Toggle;

绑定方法三(ES6的箭头函数)

import React, {Component} from 'react';

class Toggle extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            isToggeleOn: true
        }
        console.log("constructor()"+this)
        // 把this绑定给handleclick事件
        // this.handleClick = this.handleClick.bind(this);
    }

    // es6的箭头函数自动绑定上下文
    handleClick=()=> {
        console.log("handleClick()"+this)
        this.setState(state => ({
            isToggeleOn: !state.isToggeleOn
        }))
    }

    render() {
        return(
            // 把this绑定给handleclick事件
            <button onClick={this.handleClick.bind(this)}>
                {this.state.isToggeleOn ? 'ON':'OFF'}
            </button>
        )
    }
}
export  default Toggle;

向事件处理程序传递参数

<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>

4.5 条件渲染

4.6 列表&Key

function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>
    <li key={number.toString()}>      {number}
    </li>
  );
  return (
    <ul>{listItems}</ul>
  );
}

const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
  <NumberList numbers={numbers} />,
  document.getElementById('root')
);

如果 不定义key,会报警告:a key should be provided for list items.

深入解析为什么 key 是必须的

4.7表单

相对于html表单元素定义了固有的参数而言,react组件可以使用state来起任何名字的参数进行操作,没什么可说的,照着官网示例操作即可.

官网表单示例

4.8 组合

4.9 包含关系

我们遇到组件引用组件时,可以使用特殊的 children prop 来将他们的子组件传递到渲染结果中:

function FancyBorder(props) {
  return (
    <div className={'FancyBorder FancyBorder-' + props.color}>
      {props.children}    
    </div>
  );
}

这使得别的组件可以通过 JSX 嵌套,将任意组件作为子组件传递给它们。

function WelcomeDialog() {
  return (
    <FancyBorder color="blue">
      <h1 className="Dialog-title">
          Welcome      
      </h1>
      <p className="Dialog-message">
              Thank you for visiting our spacecraft!
      </p>
    </FancyBorder>
  );
}

可以看出,我们把

两个元素的内容 以 {props.children}为参数进行传递
4.10特例关系

实际就是我们对目标组件做一些个性化定制,在原组件的基础上产生一个个性化定制的新组件

function Dialog(props) {
  return (
    <FancyBorder color="blue">
      <h1 className="Dialog-title">
        {props.title}      
      </h1>
      <p className="Dialog-message">
        {props.message}  
      </p>
    </FancyBorder>
  );
}

function WelcomeDialog() {
  return (
    <Dialog
        title="Welcome"
        message="Thank you for visiting our spacecraft!" />
  );
}

我们可以说 WelcomeDialogDialog的特殊实例.

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值