路白-react.js基础

路白-react.js基础,第1张

目录 1. 简介2. JSX3. State4. Props5. 组件类型(之前版本,之后版本会有hook)6. 条件渲染和循环 & 绑定事件7. react使用箭头函数和普通函数的区别8. 生命周期9. react生命周期的改变及原因React生命周期演变的原因: 10. hook11. 实现一个高阶组件

1. 简介

React 是一个用于构建用户界面的 JAVASCRIPT 库,主要用于构建 UI,很多人认为 React 是 MVC 中的 V,起源于 Facebook 的内部项目,用来架设 Instagram 的网站,并于 2013 年 5 月开源。
React 拥有较高的性能,代码逻辑非常简单,越来越多的人已开始关注和使用它

声明式设计 −React采用声明范式,可以轻松描述应用。高效 −React通过对DOM的模拟,最大限度地减少与DOM的交互。灵活 −React可以与已知的库或框架很好地配合。JSX − JSX 是 JavaScript 语法的扩展。React 开发不一定使用 JSX ,但我们建议使用它。组件 − 通过 React 构建组件,使得代码更加容易得到复用,能够很好的应用在大项目的开发中。单向响应的数据流 − React 实现了单向响应的数据流,从而减少了重复代码,这也是它为什么比传统数据绑定更简单。 2. JSX

React 使用 JSX 来替代常规的 JavaScript,JSX 是一个看起来很像 XML 的 JavaScript 语法扩展,其实就是将js和html结合起来书写。

const jsx = 

hello, jerry

; render() { return jsx; }
3. State

如果视图内的数据需要修改, 并且同时页面响应变化,我们需要将数据放在state中, 使用setState来修改数据。

this.state.xx = xxx修改无法使视图响应变化this.setState(obj) 该更新是异步更新,setState之后不能像Vue那种之后在后面拿到最新值this.setState(obj, callback) callback为state更新的回调this.setState((preState) => {}) 该方法中的preState能拿到最新更新完的值
import React, { Component } from 'react'

export default class Clock extends Component {
  state = {
      date: new Date()
  }

  componentDidMount(){
      this.timer = setInterval(() => {
          this.setState({
              date: new Date()
          })
      }, 1000);
  }

  componentWillUnmount(){
      clearInterval(this.timer);
  }

  render() {
    return (
      
        {this.state.date.toLocaleTimeString()}
      
    )
  }
}
4. Props

父子组件间的属性传递, 通过props进行.



{this.props.title}
5. 组件类型(之前版本,之后版本会有hook) 函数组件(没有hook之前也叫无状态组件)
export function Welcome1(props) {
  return <div>Welcome1, {props.name}</div>;
}
类组件(有状态组件)
export class Welcome2 extends React.Component {
  render() {
    return <div>Welcome2, {this.props.name}</div>;
  }
}
6. 条件渲染和循环 & 绑定事件
import React, { Component } from "react";

export default class CartSample extends Component {
  //   状态初始化一般放在构造器中
  constructor(props) {
    super(props);

    this.state = {
      goods: [
        { id: 1, text: "爪哇前端课程" },
        { id: 2, text: "路白前端课程" }
      ],
      text: "",
      cart: []
    };

    this.addGood = this.addGood.bind(this);
  }

  //   回调函数声明为箭头函数
  textChange = e => {
    this.setState({ text: e.target.value });
  };

  addGood() {
    this.setState(prevState => {
      return {
        goods: [
          ...prevState.goods,
          {
            id: prevState.goods.length + 1,
            text: prevState.text
          }
        ]
      };
    });
  }

  //   加购函数
  addToCart = good => {
    // 创建新购物车
    const newCart = [...this.state.cart];
    const item = newCart.find(c => c.id === good.id);

    if (item) {
        item.count = item.count + 1;
    } else {
        newCart.push({ ...good, count: 1 });
    }
    // 更新
    this.setState({ cart: newCart });
  };

  //   处理数量更新
  add = good => {
    // 创建新购物车
    const newCart = [...this.state.cart];
    const item = newCart.find(c => c.id === good.id);
    item.count = item.count + 1;

    // 更新
    this.setState({ cart: newCart });
  };

  minus = good => {
    // 创建新购物车
    const newCart = [...this.state.cart];
    const item = newCart.find(c => c.id === good.id);
    item.count = item.count - 1;

    // 更新
    this.setState({ cart: newCart });
  };

  render() {
    //   const title = this.props.title ? this.props.title : null;
    return (
      
        {/* 条件渲染 */}
        {this.props.title && {this.props.title}}

        {/* 列表渲染 */}
        
          
          
        
        
          {this.state.goods.map(good => (
            
              {good.text}
              
            
          ))}
        

        {/* 购物车 */}
        
      
    );
  }
}

function Cart({ data, minus, add }) {
  return (
    
        {data.map(d => (
          
        ))}
      
{d.text} {d.count}
); }
7. react使用箭头函数和普通函数的区别
export default class CartSample extends Component {
  constructor(props) {
    super(props);

    this.state = {
      goods: [
        { id: 1, text: "Java" },
        { id: 2, text: "C++" }
      ],
      text: "",
      cart: []
    };
  }
  
  addGood() {
    console.log(this.state.cart)
  }

  //   加购函数
  addToCart = good => {
    console.log(good)
  };

  render() {
    return (
      
        
        
        
        
      
    );
  }
}

上面addGood采用普通函数的写法,如果直接通过button1的这种方式赋值方法内的this是有问题的,其在button内相当于是this.props.onClick()

通过button2箭头函数的方式解决this指向的问题,但通过箭头函数的方式赋值的话每次页面更新的时候都会将箭头函数创建一次,不管其他属性有没有变化都会触发子组件的更新,造成了不必要的性能浪费通过button3的bind方法绑定this也能解决this指向的问题,且不会有任何的效率问题最常用的还是button4的这种方式,直接定义的时候就采用箭头函数的方式 8. 生命周期 组件初始化阶段 initialization, 比如constructor组件挂载阶段 mountcomponentWillMount 组件挂载到DOM前调用,只会被调用一次, 这里写setState不会引起组件重新渲染render 返回一个react元素, react根据此函数的返回值渲染DOM. 不能在这里setStatecomponentDidMount 组件挂载到DOM后调用, 且只会被调用一次组件的更新阶段 updatecomponentWillReceiveProps(nextProps) 触发于props引起的组件更新过程中shouldComponentUpdate(nextProps, nextState) 比较之前和当前的props state是否有变化,返回boolean值,判断是否需要更新componentWillUpdate(nextProps, nextState) render方法前执行rendercomponentDidUpdate(preProps, preState)组件的卸载阶段 unmountcomponentWillUnmount 卸载前调用, 在这里可以清理一些定时器 9. react生命周期的改变及原因

react v16之后的生命周期变化:

废弃了 componentWillMount 与 componentWillUpdate 及 componentWillReceiveProps新增了 getDerivedStateFromProps 与 getSnapshotBeforeUpdate新增了 getDerivedStateFromError 与 componentDidCatch 错误处理函数


getDerivedStateFromProps: 在组件创建和更新的render之前调用,应该返回一个对象来更新状态,如果不想更新,返回null
getSnapshotBeforeUpdate: 可以在更改之前获取一些信息,比如scrollTop,此生命周期的返回值都会作为参数传递到componentDidUpdate

React生命周期演变的原因: 在render之前的生命周期可能会直接通过this.setState改变状态,触发重新渲染,改成了getDeridedStateFromProps之后采用派生的方式更新state,这种方式更新state不会引起render函数的重复执行为Fiber框架铺路,采用Fiber后render过程是可以被打断、中止和重新执行的,如果在componentWillUpdate等生命周期中运行了副作用如发送请求等,那么这些副作用就有可能会被重复的执行 10. hook

useState: 传入的参数为初始值,会返回一个数组,包含了状态及修改状态的方法
useEffect: 副作用钩子,第一个参数为回调函数,第二个参数为监听的状态,如果仅打算执行一次,直接传入[]

import React, { useState, useEffect } from "react";

// 自定义hook是一个函数,名称用“use"开头,函数内部可以调用其他钩子
function hookTest() {
  const [count, setCount] = useState(0);
  const [fruit, setFruit] = useState("banana");
  const [input, setInput] = useState("");
  // 副作用钩子会在每次渲染时都执行
  useEffect(() => {
    document.title = `您点击了${count}次`;
  }, [count]);
}

hook不能用在循环遍历、条件判断中,只能用在hook组件的最顶层,因为react设计的时候考虑的是有顺序的,它在内部的存储是通过单向链表来存储的

11. 实现一个高阶组件
import React from "react";
import { Input, Button } from "antd";

// 创建一个高阶组件:扩展现有表单,事件处理、数据收集、校验
function kFormCreate(Comp) {
  return class extends React.Component {
    constructor(props) {
      super(props);

      this.options = {};
      this.state = {};
    }

    handleChange = e => {
      const { name, value } = e.target;
      console.log(name, value);

      this.setState({ [name]: value }, () => {
        //   确保值发生变化再校验
        this.validateField(name);
      });
    };

    // 单项校验
    validateField = field => {
      // 1. 获取校验规则
      const rules = this.options[field].rules;
      // 任意一项失败则返回false
      const ret = !rules.some(rule => {
        if (rule.required) {
          if (!this.state[field]) {
            //校验失败
            this.setState({
              [field + "Message"]: rule.message
            });
            return true;
          }
        }
      });

      if (ret) { // 校验成功
        this.setState({
          [field + "Message"]: ""
        });
      }
      return ret;
    };

    // 校验所有字段
    validate = cb => {
      const rets = Object.keys(this.options).map(field =>
        this.validateField(field)
      );

      const ret = rets.every(v => v == true);
      cb(ret, this.state);
    };

    // 创建input包装器
    getFieldDec = (field, option) => {
      // 保存当前输入项配置
      this.options[field] = option;
      return InputComp => (
        
          {React.cloneElement(InputComp, {
            name: field,
            value: this.state[field] || "",
            onChange: this.handleChange
          })}
          {/* 校验错误信息 */}
          {this.state[field+'Message'] && (
              

{color:'red'}}>{this.state[field+'Message']}

)} ); }; render() { return ; } }; } @kFormCreate class KForm extends React.Component { onSubmit = () => { console.log("submit"); // 校验所有项 this.props.validate((isValid, data) => { if (isValid) { //提交登录 console.log("登录:", data); // 后续登录逻辑 } else { alert("校验失败"); } }); }; render() { const { getFieldDec } = this.props; return ( {getFieldDec("uname", { rules: [{ required: true, message: "用户名必填" }] })()} {getFieldDec("pwd", { rules: [{ required: true, message: "密码必填" }] })()} ); } } export default KForm;

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1296284.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-10
下一篇 2022-06-10

发表评论

登录后才能评论

评论列表(0条)

保存