项目开发-前端-React框架基础学习

React框架基础学习

  • 前言
  • 1 第一章
    • 1.1 认识React
    • 1.2 React元素渲染
    • 1.3 React_JSX
    • 1.4 React样式和注释
    • 1.5React组件
    • 1.6React State
  • 第二章
    • 2.1 React父传子数据传递
    • 2.2 React子传父数据传递
    • 2.3 React事件处理
    • 2.4 React条件渲染
    • 2.5React列表渲染
    • 2.6 React组件API
  • 第三章
    • 3.1 组件生命周期
    • 3.2 表单和图表
  • 第四章
    • 4.1 React插槽
    • 4.2 React路由react-router
    • 4.3 react-redux

前言

前端React框架学习,以此篇博客记录所学,如有误载,感谢您的指正。
视频教程地址:https://www.bilibili.com/video/BV1T7411W72T?p=1

1 第一章

1.1 认识React

功能和特性:
React功能:构建用户界面的JavaScript库,主要用于构建UI界面。特性:

  • 声明式的设计。
  • 高效,采用虚拟DOM来实现DOM的渲染,最大限度的减少DOM的操作。
  • 灵活,跟其他库灵活搭配使用。
  • JSX,俗称JS里面写HTML,JavaScript语法的扩展。
  • 组件化,模块化,代码易复用。
  • 单向数据流,没有实现数据的双向绑定,数据->视图->事件->数据。

创建第一个项目:
1、通过script引入使用,仅用于学习调试使用:

<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

2、进入工作目录,打开控制台终端,通过react的脚手架,创建项目进行开发,部署。

npm install -g create-react-app
create-react-app <项目名称>

注:npm为nodejs的包管理命令。
Windows安装nodejs和换源教程链接:https://www.cnblogs.com/mlzdev/p/11520325.html

1.2 React元素渲染

JSX创建JS元素对象:

let h1 = <h1>helloworld</h1>;

注:JSX元素对象,或者组件对象,必须只有1个根元素(根节点)
Demo:

function clock(){
    let time = new Date().toLocaleTimeString()
    let element = (
        <div>
            <h1>现在的时间是{time} </h1>
            <h2>这是副标题</h2>
        </div>
    )
    let root = document.querySelector('#root');
    ReactDOM.render(element,root)
}
clock()
setInterval(clock,1000)

函数式组件渲染:

function Clock(props){
    return (
                <div>
                    <h1>现在的时间是{props.date.toLocaleTimeString()} </h1>
                    <h2>这是函数式组件开发</h2>
                </div>
    )
}
function run(){
    ReactDOM.render(
        <Clock date={new Date()} />,
        document.querySelector('#root')
    )
}
setInterval(run,1000)

1.3 React_JSX

表达式:

  • 由HTML元素构成
  • 中间如果需要插入变量用{}
  • {}中间可以使用表达式
  • {}中间表达式中可以使用JSX对象
  • 属性和html内容一样都是用{}来插入内容
    注意:
    1、JSX必须要有根节点。
    2、正常的普通HTML元素要小写。如果是大写,默认认为是组件。
    Demo:
import React from 'react';
import ReactDOM from 'react-dom';
import './App.css'

let time = new Date().toLocaleTimeString()
let str = '当前时间是:'
let element = (
    <div>
        <h1>helloworld</h1>
        <h2>{str+time}</h2>
    </div>
)
console.log(element)
let man = '发热';
let element2 = (
    <div>
        <h1>今天是否隔离</h1>
        <h2>{man=="发热"?<button>隔离</button>:"躺床上"}</h2>
    </div>
)
//let man = '发热';
let element4 = (
    <div>
        <span>横着躺</span>
        <span>竖着躺</span>
    </div>
)
man = '正常'
let element3 = (
    <div>
        <h1>今天是否隔离</h1>
        <h2>{man=="发热"?<button>隔离</button>:element4}</h2>
    </div>
)
let color = 'bgRed'
let logo = 'https://www.baidu.com/img/pc_1c6e30772d5e4103103bd460913332f9.png'
//HTML的样式类名要写className,因为class在js当中是关键词
let element5 = (
    <div className={color}>
        <img src={logo} />
        红色的背景颜色
    </div>
)
ReactDOM.render(
    element5,
    document.getElementById('root')
)

1.4 React样式和注释

1、Class,style中,不可以存在多个class属性,错误的表示如下:

<div class=’abc’  class={‘active’}> 

2、style样式中,如果存在多个单词的属性组合,第二个单词开始,首字母大写。或者用引号引起来,否则会报错。

let exampleStyle = {
    background:"skyblue",
    borderBottom:"4px solid red",
    'background-image':"url(https://www.baidu.com/img/pc_1c6e30772d5e4103103bd460913332f9.png)"
}

3、多个类共存的操作

let element2 = (
    <div>
        <h1 className={"abc "+classStr}>helloworld</h1>
    </div>
)
let classStr2 = ['abc2','redBg2'].join(" ")
let element3 = (
    <div>
        {/* 这里写注释 */}
        <h1 className={classStr2} style={exampleStyle}>helloworld</h1>
    </div>
)

4、注释
必须在括号的表达式{/* 这里写注释 */}内书写,否则报错。

1.5React组件

函数式组件与一般用于静态没有交互事件内容的组件页面,类组件一般会有交互或者数据修改的操作,复合式组件两者均包含。

函数式组件Demo:

function Childcom(props){
    console.log(props)
    let title = <h2>我是副标题</h2>
    let weather = props.weather
    //条件判断 
    let isGo = weather=='下雨' ?"不出门":"出门"
    return (
        <div>
            <h1>函数式组件helloworld</h1>
            {title}
            <div>
                是否出门?
                <span>{isGo}</span>
            </div>
        </div>
    )
}

类组件Demo:

class HelloWorld extends React.Component{
    render(){
        console.log(this)
        return (
            <div>
                <h1>类组件定义HELLOWORLD</h1>
                <h1>hello:{this.props.name}</h1>
                <Childcom weather={this.props.weather} />
            </div>
        )
    }
}

复合组件Demo:

import React from 'react';
import ReactDOM from 'react-dom';
import './04style.css';
//函数式组件
function (props){
    console.log(props)
    let title = <h2>我是副标题</h2>
    let weather = props.weather
    //条件判断 
    let isGo = weather=='下雨' ?"不出门":"出门"
    return (
        <div>
            <h1>函数式组件helloworld</h1>
            {title}
            <div>
                是否出门?
                <span>{isGo}</span>
            </div>
        </div>
    )
}
//类组件定义
class HelloWorld extends React.Component{
    render(){
        console.log(this)
//返回的都是JSX对象
        return (
            <div>
                <h1>类组件定义HELLOWORLD</h1>
                <h1>hello:{this.props.name}</h1>
                <Childcom weather={this.props.weather} />
            </div>
        )
    }
}
ReactDOM.render(
    <HelloWorld name="老陈" weather="下雨" />,
    document.querySelector('#root')
)

1.6React State

React 里,只需更新组件的 state,然后根据新的 state 重新渲染用户界面(不要操作 DOM)。
Demo:

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }
  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>现在是 {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}
 
ReactDOM.render(
  <Clock />,
  document.getElementById('example')
);

第二章

2.1 React父传子数据传递

React使用props父传子:
props传递给子组件数据,单向流动,可以是任意的类型,不能直接子传递给父。但props可以传递父元素的函数,就可以去修改父元素的state,从而达到传递数据给父元素。Props可以设置默认值

HelloMessage.defaultProps = {  name:”老陈”,msg:“helloworld”  }

Demo:

//在父元素中使用state去控制子元素props的从而达到父元素数据传递给子元素
class ParentCom extends React.Component{
    constructor(props){
        super(props)
        this.state = {
            isActive:true
        }
        this.changeShow = this.changeShow.bind(this)
    }
    render(){
        return (
            <div>
                <button onClick={this.changeShow}>控制子元素显示</button>
                <ChildCom isActive={this.state.isActive} />
            </div>
        )
    }
    changeShow(){
        this.setState({
            isActive:!this.state.isActive
        })
    }
}

class ChildCom extends React.Component{
    constructor(props){
        super(props)
    }
    render(){
        let strClass = null;
        // if(this.props.isActive){
        //     strClass = ' active'
        // }else{
        //     strClass = ""
        // }
        strClass = this.props.isActive?" active":"";

        return (
            <div className={"content"+strClass}>
                <h1>我是子元素</h1>
            </div>
        )
    }
}

ReactDOM.render(
    <ParentCom />,
    document.querySelector("#root")
)

props和state的区别:
区别在于 props 是不可变的,而 state 可以根据与用户交互来改变。这就是为什么有些容器组件需要定义 state 来更新和修改数据。 而子组件只能通过 props 来传递数据。

2.2 React子传父数据传递

调用父元素的函数从而操作父元素的数据,从而实现数据从子元素传递至父元素
Demo:

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

//子传父
class ParentCom extends React.Component{
    constructor(props){
        super(props)
        this.state = {
            childData:null
        }
    }
    render(){
       return (
           <div>
                <h1>子元素传递给父元素的数据:{this.state.childData}</h1>
               <ChildCom setChildData={this.setChildData} />
           </div>
       ) 
    }
    setChildData=(data)=>{
        this.setState({
            childData:data
        })
    }
}
class ChildCom extends React.Component{
    constructor(props){
        super(props)
        this.state = {
            msg:"helloworld"
        }
    }
    render(){
        return (
            <div>
                <button onClick={this.sendData}>传递helloworld给父元素</button>
                <button onClick={()=>{this.props.setChildData('直接调用props的函数')}}>传递helloworld给父元素</button>
            
            </div>
        )
    }
    sendData=()=>{
        //console.log(this.state.msg)
        //将子元素传递给到父元素,实际就是调用父元素传递进来的父元素函数
        this.props.setChildData(this.state.msg)
    }
}
ReactDOM.render(
    <ParentCom />,
    document.querySelector('#root')
)

2.3 React事件处理

语法:
1、React 事件绑定属性的命名采用驼峰式写法,而不是小写。
2、如果采用 JSX 的语法你需要传入一个函数作为事件处理函数,而不是一个字符串(DOM 元素的写法)

无参Demo:

class Toggle extends React.Component {
  constructor(props) {
    super(props);
    this.state = {isToggleOn: true};
    // 这边绑定是必要的,这样 `this` 才能在回调函数中使用
    this.handleClick = this.handleClick.bind(this);
  }
  handleClick() {
    this.setState(prevState => ({
      isToggleOn: !prevState.isToggleOn
    }));
  }
  render() {
    return (
      <button onClick={this.handleClick}>
        {this.state.isToggleOn ? 'ON' : 'OFF'}
      </button>
    );
  }
}
ReactDOM.render(
  <Toggle />,
  document.getElementById('example')
);

事件传参:

{/* 使用ES6箭头函数传递多个参数 */}
<button  onClick={(e)=>{this.parentEvent1('msg:helloworld',e)}}>提交</button>
{/* //不使用ES6箭头函数传递多个参数的方式 */}
<button  onClick={function(e){this.parentEvent1('不使用es6,msg:helloworld',e)}.bind(this)}>提交</button>

事件对象:React返回的事件对象是代理的原生的事件对象,如果想要查看事件对象的具体值,必须直接输出事件对象的属性。
注意: 原生阻止默认行为时,可以直接返回return false;React中,阻止默认必须e.preventDefault();

2.4 React条件渲染

React中条件渲染和JavaScript中的一致,条件运算,如if…else…三元运算符等。
条件运算Demo:

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

function UserGreet(props){
    return (<h1>欢迎登陆</h1>)
}
function UserLogin(props){
    return (<h1>请先登录</h1>)
}
class ParentCom extends React.Component{
    constructor(props){
        super(props)
        this.state = {
            isLogin:true
        }
    }
    render(){
        if(this.state.isLogin){
            return (<UserGreet></UserGreet>)
        }else{
            return (<UserLogin></UserLogin>)
        }
    }
}
ReactDOM.render(
    <ParentCom></ParentCom>,
    document.querySelector('#root')
)

三目运算Demo:

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

function UserGreet(props){
    return (<h1>欢迎登陆</h1>)
}
function UserLogin(props){
    return (<h1>请先登录</h1>)
}

class ParentCom extends React.Component{
    constructor(props){
        super(props)
        this.state = {
            isLogin:false
        }
    }
    render(){
        let element = null;
        if(this.state.isLogin){
            element = <UserGreet></UserGreet>;
        }else{
            element = (<UserLogin></UserLogin>);
        }
        return (
            <div>
                <h1>这是头部</h1>
                {element}
                <h1>这是三元运算符的操作</h1>
                {this.state.isLogin?<UserGreet></UserGreet>:<UserLogin></UserLogin>}
                <h1>这是尾部</h1>
            </div>
        )
    }
}

ReactDOM.render(
    <ParentCom></ParentCom>,
    document.querySelector('#root')
)

2.5React列表渲染

  • 将列表内容拼装成数组放置到模板中。将数据拼装成数组的JSX对象。
  • 使用数组的map方法,对每一项数据按照JSX的形式进行加工,最终得到1个每一项都是JSX对象的数组,在将数组渲染到模板中。
  • Key值需要放置到每一项中。

Demo:

function ListItem(props) {
  return <li>{props.value}</li>;
}

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

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

2.6 React组件API

  • 设置状态:setState
  • 替换状态:replaceState
  • 设置属性:setProps
  • 替换属性:replaceProps
  • 强制更新:forceUpdate
  • 获取DOM节点:findDOMNode
  • 判断组件挂载状态:isMounted

第三章

3.1 组件生命周期

组件的生命周期可分成三个状态:

  • Mounting:已插入真实 DOM
  • Updating:正在被重新渲染
  • Unmounting:已移出真实 DOM

生命周期的方法有:

  • compontWillMount:组件将要渲染,AJAX,添加动画前的类
  • compontDidMount:组件渲染完毕,添加动画
  • compontWillReceiveProps:组件将要接受props数据,查看接收props的数据什么
  • shouldComponentUpdate:组件接收到新的state或者props,判断是否更新。返回布尔值
  • compontWillUpdate:组件将要更新
  • componentDidUpdate:组件已经更新
  • componentwillUnmount:组件将要卸载
    这些方法的详细说明,可以参考官方文档https://reactjs.org/docs/react-component.html#lifecycle-methods。

3.2 表单和图表

HTML 表单元素与 React 中的其他 DOM 元素有所不同,因为表单元素生来就保留一些内部状态。在 HTML 当中,像 ,