Bootstrap

React之2天入门,1天练习

一、react基本了解

1.组件定义

React 组件是一段可以使用标签进行扩展 的 JavaScript 函数。每个 React 组件都是一个 JavaScript 函数,它会返回一些标签,React 会将这些标签渲染到浏览器上。React 组件使用一种被称为 JSX 的语法扩展来描述这些标签。JSX 看起来和 HTML 很像,但它的语法更加严格并且可以动态展示信息。了解这些区别最好的方式就是将一些 HTML 标签转化为 JSX 标签。

  • 函数组件

    export default function Demo(){
        return (
        <div>hello,react</div>
        )
    }
    
  • 类组件

    import React from 'react'
    export default class Demo extends React.Component{
        render(){
        	return (
        		<div>hello,react</div>
        		)
        }
    }
    

使用html的cdn练习,后面使用脚手架

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>reactDemo</title>
   <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
	<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/babel-standalone/7.24.8/babel.js"></script>
</head>
<body>
    <div id="test"></div>
    
    <script type="text/babel">
        class Demo extends React.Component{
            render(){
                return (
                    <div>hello,react</div>
                )
            }
        }
    
        // 2.渲染虚拟DOM到页面
        ReactDOM.render(<Demo/>, document.getElementById('test'))
    
      </script>
</body>
</html>

2.组件创建

  • 组件命名规范(jsx规范)

    1. 组件必须以大写字母开头,而 HTML 标签则必须是小写字母。

    2. 虚拟DOM元素只能有一个根元素 比如 <div>...</div> 或使用空的 <>...</> 包裹

    3. 虚拟DOM元素必须有结束标签

    function MyDemo(){
        return (
          <div>
            里面写html内容
          </div>
        )
    }
    

3.组件样式

  • 使用class样式 使用className代替class名称

    import React, { Component } from 'react'
    import './index.css'
    export default class extends Component {
      render() {
         return (
           <div className='title'>hello react</div>
         )
      }
    }
    
    <!-- index.css -->
    .title{
        width:300px;
        height:30px;
        background-color:'red'
    }
    
  • 使用style样式

    • style={{}},第一个{}表示接受的是一个对象,第二个{}表示读取引入的变量内容
    import React, { Component } from 'react'
    
    export default class extends Component {
      render() {
         return (
           <div style={{width:'200px',height:'30px',backgroundColor:'red'}}>hello react</div>
         )
      }
    }
    

4.数据渲染

  • 变量渲染 通过{}引用变量或者函数

    return (
      <h1>
        {user.name}
      </h1>
    );
    
  • 条件渲染

    import React, { Component } from 'react'
    
    export default class extends Component {
      isLogin=false
      render() {
        if(this.isLogin){
            return (
                <div>已经登录了</div>
            )
        }else{
            return (
                <div>未登录,将返回登录页面</div>
            )
        }
    
      }
    }
    
  • 列表渲染 使用数组的map方法

    • key 帮助 React 识别哪些元素改变了,比如被添加或删除。因此你应当给数组中的每一个元素赋予一个确定的标识。
    • key必须唯一
    import React, { Component } from 'react'
    
    export default class extends Component {
      fruitArr=['西瓜','苹果','草莓']
      render() {
         return (
            <ul>
                {this.fruitArr.map((n,index)=>{
                    return <li key={index}>{n}</li>
                })}
            </ul>
         )
      }
    }
    

5.事件绑定

import React, { Component } from 'react'

export default class extends Component {
  handleClick=(e)=>{
    e.preventDefault(); //阻止事件默认效果
    alert('hello,world')
  }
  render() {
    return (
      <div>
        <button onClick={this.handleClick}>点我弹框</button>
      </div>
    )
  }
}

6.数据存储

state 状态记录器

组件内部重要的属性,取值是一个对象,存储组件的信息,案例如下:

  • state:组件内部的属性,用于记录组件状态,取值是一个object
  • setState:用于修改state的值,页面才会对应变化
//当前天气默认炎热  点击改变按钮   变成凉爽
import React, { Component } from 'react'
export default class Weather extends Component {
  //创建默认天气
  state={isHot:true}
  //改变天气
  changeTq=()=>{
    //只能通过setState来改变值,页面才会渲染变化的值
    this.setState({isHot:false})
  }
  render() {
    return (
      <div>
        <p>当前天气:{this.state.isHot?'炎热':'凉爽'}</p>
        <button onClick={this.changeTq}>改变天气</button>
      </div>
    )
  }
}
props 属性收集器

记录每个组件标签属性对象,通常用于父组件给子组件传递数据。如下:App给Student传递数据

import Student from "./components/Student";
function App() {
  return (
    <div>
        <Student name="夫子" age="96"/>
    </div>
  );
}


export default App;

import React, { Component } from 'react'
export default class Student extends Component {
  render() {
    return (
      <div>
        <ul>
            <li>姓名:{this.props.name}</li>
            <li>年龄:{this.props.age}</li>
        </ul>
      </div>
    )
  }
}

props中的属性值进行类型限制和必要性限制:

安装prop-types

import PropTypes from 'prop-types';

使用PropTypes:

import React, { Component } from 'react'
import PropTypes from 'prop-types';
export default class Student extends Component {
  static propTypes={
    name:PropTypes.string.isRequired, //必须传入
    age:PropTypes.string
  }
 
  render() {
    return (
      <div>
        <ul>
            <li>姓名:{this.props.name}</li>
            <li>年龄:{this.props.age}</li>
        </ul>
      </div>
    )
  }
}

refs 身份定义器

组件通过refs值来定义自己,相当于原生documen.getElementByxxx

  • 字符串定义

    //定义
    <input ref="myInput"></input>
    //使用
    this.refs.myInput.value
    
  • 回调函数定义

    //定义
    <input ref={c=>this.myInput=c}></input>
    //使用
    this.myInput.value
    
  • createRef方法定义

    //定义
    myInput=React.createRef()
    <input ref={this.myInput}></input>
    
    //使用
    this.myInput.current.value
    

案例:点击按钮,显示输入框内容

import React, { Component } from 'react'

export default class extends Component {
myInput=React.createRef()
  render() {
    return (
      <div>
        <input ref={this.myInput}></input>
        <button onClick={()=>alert(this.myInput.current.value)}>点我弹框</button>
      </div>
    )
  }
}

7.生命周期

7.1 旧版本生命周期
  • 初始化阶段
    1. constructor
    2. componentWillMount (将废弃)
    3. componentDidMount 比较常用: 一般在这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息
  • 更新阶段
    1. shouldComponentUpdate 组件是否应该被更新(默认返回true
    2. componentWillUpdate (将废弃)
    3. render
    4. componentDidUpdate
  • 卸载阶段
    1. componentWillUnmount 关闭定时器
class LifeDemo extends React.Componet(){ 
    //构造器  默认实例后就执行   【出生】
    constructor(){
        
    }
    //组件将要挂载前执行
    componentWillMount(){
        
    }
    //组件完成挂载执行(只执行一次)
    componentDidMount(){
        
    }
    
    //每次组件内容变了则会执行   1+n次
    render(){
        
    }
    //通常是父组件给子组件传递属性值,引发此函数顺序一系列执行
    //第一次传递的无效,后面的有效
    componentWillReceiveProps(){
        
    }
    
    
    //组件是否更新 默认为返回true 【组件的更新阀门(state状态变了,则执行)】
    // 如果写了,则必须返回true ,如果返回false,则state变了不会引入组件内容变化
    shouldComponentUpdate(){
        return true;
    }
    //组件将要更新前执行     forceUPdate也能导致此函数顺序一系列执行  
    componentWillUpdate(){
        
    }
    //组件完成更新后执行
    componentDidUpdate(){
        
    }
    //组件将要销毁执行     【死亡】
    componentWillUnmount(){
        
    }
}

在这里插入图片描述

  • 更新说明:
    在这里插入图片描述在这里插入图片描述
7.2 新版本生命周期
  • 初始化
    1. constructor
    2. getDerivedStateFromProps
    3. render :初始渲染dom数据
    4. componentDidMount :组件挂载dom执行一次 通常开启监听、发生请求
  • 更新阶段 由组件this.setState或者组件重新render出发
    1. getSnapshotBeforeUpdate
    2. render
    3. componentDidUpdate
  • 卸载阶段
    1. componentWillUnmount
      在这里插入图片描述
class Life extends React.Component(){
    // 此方法适用于罕见的用例,即 state 的值在任何时候都取决于 props。
    //从Props获取一个派生的state  返回的值会更改已有的state
    static getDerivedStateFromProps(props,state){
        return props
    }
    render(){}
    compoentDidMount(){}
   // 组件能在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置)。此生命周期方法的任何返回值将作为参数传递给      componentDidUpdate()。
    getSnapshotBeforeUPdate(preProps,preState){
        return snapshotValue
    }
    componentDidUpdate(preProps,preState,snapshotValue){
        
    }
    
}

getSnapshotBeforeUPdate的使用案例:

每次添加新闻,保持滑动的那条新闻不随滚动条移动。
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>reactDemo</title>
   <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
	<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/babel-standalone/7.24.8/babel.js"></script>
    <style>
        .list{
            width: 200px;
            height: 150px;
            background-color: aqua;
            overflow:auto;
        }
        .news{
            height: 30px;
        }
    </style>
</head>
<body>
    <div id="test"></div>
    
    <script type="text/babel">
        class MyLife extends React.Component{
            //初始化数据
            state={newArr:[]}
            componentDidMount(){
                console.log('dfdfd');
                this.timer=setInterval(()=>{
                    let {newArr}=this.state
                    //每次创建一条新闻
                    let news="新闻"+(newArr.length+1)
                    this.setState({newArr:[news,...newArr]})
                },1000)
            }
            stop=()=>{
                console.log("停了吗");
                clearInterval(this.timer)
            }
            getSnapshotBeforeUpdate(){
                console.log("getSnapshotBeforeUpdate....");
                return this.dd.scrollHeight
            }
            render(){
                return (
                  <>
                  <div className="list" ref={c=>this.dd=c}>
                    {
                    this.state.newArr.map((n,index)=>{
                        return <div key={index} className="news">{n}</div>
            
                    })
                   }
                    </div>
                    <button onClick={this.stop}>stop</button>
                  </>
                );
            }
            componentDidUpdate(preProps,preState,height){
                console.log("componentDidUpdate...");
                console.log(this.dd,height);
                this.dd.scrollTop+=this.dd.scrollHeight-height
            }
            
        }
    
        // 2.渲染虚拟DOM到页面
        ReactDOM.render(<MyLife/>, document.getElementById('test'))
    
      </script>
</body>
</html>

8.快速demo(脚手架)

  • 模块化,组件化:react+webpack+eslint+es6

  • 快速构建一个简单的react项目

    npx create-react-app react_demo
    
  • 启动react项目

    cd react_demo
    npm start
    Starting the development server...
    

在这里插入图片描述
在这里插入图片描述

9. 快速创建Hello组件

创建Hello组件
在这里插入图片描述

使用Hello组件
在这里插入图片描述

10 样式模块化

创建Welcome组件,设置class,但是Welcome组件没有css文件

import { render } from '@testing-library/react'
import react,{Component} from 'react'
export default class WelCome extends Component{
    render(){
        return (
            <div className='title'>hello welcome</div>
        )
    }
}

Hello组件的内容

import { render } from '@testing-library/react'
import react,{Component} from 'react'
//【引入目录下的css样式】
import './index.css'
export default class Hello extends Component{
    render(){
        return (
            <div className='title'>hello react</div>
        )
    }
}

App引入Welcome组件,这个时候Welcome被渲染的时候使用了Hello组件下的样式了。

import logo from './logo.svg';
//直接引入
import Hello from './components/Hello'
import Welcome from './components/Welcome'
function App() {
  return (
    <div>
      <Hello/>
      <Welcome/>
    </div>
  );
}
export default App;

效果:
在这里插入图片描述

解决办法:

  1. xxx.css------>xxx.module.css
  2. 通过import xxx from './xxx.module.css'
  3. className={xxx.title}
<!--正常引入的css -->
.title{
    width: 300px;
    height: 30px;
    color: rgb(78, 78, 53);
    background-color: rgb(157, 110, 49);
    border: 2px solid #ccc;
}
<!-- 样式模块化后的css-->
.Hello_title__OTB7- {
    width: 300px;
    height: 30px;
    color: rgb(78, 78, 53);
    background-color: rgb(157, 110, 49);
    border: 2px solid #ccc;
}

在这里插入图片描述
在这里插入图片描述

11.插件安装

在这里插入图片描述
通过命令快速生成组件模式,如class模式组件,function模式组件

// 输入【rcc】(react class create)
import React, { Component } from 'react'

export default class index extends Component {
  render() {
    return (
      <div>index</div>
    )
  }
}

// 输入【rfc】(react function create)
import React from 'react'

export default function index() {
  return (
    <div>index</div>
  )
}

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;