react

yarn

和npm一样都是包管理工具

如果要使用默认情况下 必须先下载 才能正常用 npm install -g yarn

设置yarn的镜像源为淘宝镜像: npm config set registry http://registry.npm.taobao.org/

本地模式

react 是什么

React 起源于 Facebook

React 是一个用于构建用户界面的 javascript 库。

什么是虚拟Dom

虚拟dom相当于在js和真实dom中间加了一个缓存。基于React进行开发时所有的DOM构造都是通过虚拟DOM进行,每当数据变化时,React都首先重新构建整个DOM树(减少页面更新次数),然后React将当前整个DOM树和上一次的DOM树进行对比(DOM Diff算法-最小化页面重绘),得到DOM结构的区别,然后仅仅将需要变化的部分进行实际的浏览器DOM更新。

虚拟 dom 相当于在 js 和真实 dom 中间加了一个缓存,利用 dom diff 算法避免了没有必要的 dom 操作,从而提高性能。

什么是调和?
将Virtual(虚拟)DOM树转换成actual(真实)DOM树的最少操作的过程称为调和 。

什么是React diff算法?
diff算法是调和的具体实现。

react 特点

声明式设计 −React采用声明范式,可以轻松描述应用。(开发者只需要声明显示内容,react就会自动完成)

高效 −React通过对DOM的模拟,最大限度地减少与DOM的交互。

灵活 −React可以与已知的库或框架很好地配合。

组件 − 通过 React 构建组件,使得代码更加容易得到复用,能够很好的应用在大项目的开发中。(把页面的功能拆分成小模块–每个小模块就是组件)

单向数据流-- React是单向数据流,数据主要从父节点传递到子节点(通过props)。如果顶层(父级)的某个props改变了,React会重渲染所有的子节点

组件的特点

强 内 聚
弱 耦 合

**提高代码复用率:**组件将数据和逻辑进行封装。

**降低测试难度:**组件高内聚低耦合(各个元素高集成度低关联性),很容易对单个组件进行测试。

**代码的复杂程度:**直观的语法,可以极大提高可读性。

搭建环境

react.js文件是创建React元素和组件的核心文件,

react-dom.js文件用来把React组件渲染为DOM,此文件依赖于react.js文件,需在其后被引入。

Babel的主要用途是将ES6转成ES5 同时可以把JSX 语法转换新标准的JavaScript代码让现今浏览器兼容的代码

下载 cnpm install --save react babel-standalone react-dom

在html文件中引用相关依赖包(注意顺序千万不能错)


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    

    <script src="node_modules/react/umd/react.development.js">script>
    <script src="node_modules/react-dom/umd/react-dom.development.js">script>
    <script src="node_modules/babel-standalone/babel.js">script>
head>
<body>
    
    <div id="demodiv">

    div>
    
    <script type="text/babel">

        let com=<h1>你好么么哒</h1>
        // 注意大小写
        ReactDOM.render(com,document.querySelector("#demodiv"))

    script>

body>
html>

jsx

JSX=javascript xml就是Javascript和XML结合的一种格式。是JavaScript 的语法扩展。 React推荐在 React 中使用 JSX 来描述用户界面。当遇到<,JSX就当HTML解析,遇到{就当JavaScript解析。

jsx优点:

JSX 执行更快,因为它在编译为 JavaScript 代码后进行了优化。

它是类型安全的,在编译过程中就能发现错误。

使用 JSX 编写模板更加简单快速。

jsx 插入变量

直接在你想插入的地方 使用{变量}

   <script type="text/babel">
        // 遇到< 当html解析  遇见{当js解析

        let text="123321"    

        let com=<h1>你好么{
     text}么哒</h1>
    
        ReactDOM.render(com,document.querySelector("#demodiv"))

    </script>

坑1 必须按照w3c规范

  // Jsx中的HTML标签必须按照w3c规范来写 标签必须闭合
        let com=

坑2 jsx中多行标签必须用父容器包裹

   let com=(
            

你好

你坏

)

坑3 注释

在注释的时候使用 {/ * 注释内容 */}

    let com=(
            
{ /*我是注释*/} 我是内容
)

坑4 外部js文件

   

react中属性插入变量


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    

    <script src="node_modules/react/umd/react.development.js">script>
    <script src="node_modules/react-dom/umd/react-dom.development.js">script>
    <script src="node_modules/babel-standalone/babel.js">script>
head>
<body>

    <div id="demodiv">
        <h1>属性插变量h1>
    div>

    <script type="text/babel">
        let text="点我去百度"
        let ahref="http://www.baidu.com"
        let com=(
            <div>
                {
      
                /*
                    html的属性语法是属性="属性值"
                    jsx中也说了 必须严格验证w3c规范来写
                */
                }
                <a href={
      ahref}>{
      text}</a>
            </div>
           
        )
        ReactDOM.render(com,document.querySelector("#demodiv"))

    script>

body>
html>

设置样式

行内样式

贼恶心 但是必须要知道

类样式

必须要用className


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    

    <script src="node_modules/react/umd/react.development.js">script>
    <script src="node_modules/react-dom/umd/react-dom.development.js">script>
    <script src="node_modules/babel-standalone/babel.js">script>
    <style>
        .demoh{
      
            color:pink;
        }
    style>
head>
<body>

    <div id="demodiv">
        
     
    
    div>

    <script type="text/babel">

        let com=(
            <div>
                <h1>行内样式</h1>
                {
      /*
               在jsx中设置样式必须是一个对象对象对象对象对象
                外面的{}是jsx解析js   里面的{}是对象的语法
                多个样式单词  需要把-去掉并且把之后的单词首字母大写
                */}
                <h1 style={
      {
      color:"red",backgroundColor:"yellow"}}>修改我的样式啊!!!!</h1>
        
                <h1>class类样式</h1>
                {
      /*
                    传统的html+css+js或者是vue中设置类样式都是class属性
                    但是但是
                    在react中引用class是js的关键字
                    所以在react中如果要设置class  那么必须必须必须必须必须  使用className来替代
                */}
                <h1 className="demoh">我是class类样式的例子</h1>    
            </div>
           
        )
        ReactDOM.render(com,document.querySelector("#demodiv"))

    script>

body>
html>

便利列表

使用map()进行便利


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    

    <script src="node_modules/react/umd/react.development.js">script>
    <script src="node_modules/react-dom/umd/react-dom.development.js">script>
    <script src="node_modules/babel-standalone/babel.js">script>
    <style>
        .demoh{
      
            color:pink;
        }
    style>
head>
<body>

    <div id="demodiv">div>

    <script type="text/babel">

        let arr=["ez",'NOC','MF',"vn"]
        let obj=[
            {
      name:"xixi1",age:181},
            {
      name:"xixi2",age:182},
            {
      name:"xixi3",age:183},
            {
      name:"xixi4",age:184},
            {
      name:"xixi5",age:185},
            {
      name:"xixi6",age:186}
        ]
        let com=(
            <div>
                <h1>便利基本数组</h1>
                <ul>
                    {
      
                        arr.map((v,i)=>{
      
                            return (
                                <li key={
      i}>{
      v}</li>
                            )
                        })
                    }
                    
                </ul>

                <h1>便利数组对象</h1>
                <table border="1">
                    <tbody>
                    {
      
                        obj.map((v,i)=>{
      
                            return (
                                <tr>
                                    <td>{
      v.name}</td>    
                                    <td>{
      v.age}</td>    
                                </tr>
                            )
                        })
                    }    
                 </tbody>
                </table>
            </div>
           
        )
        ReactDOM.render(com,document.querySelector("#demodiv"))

    script>

body>
html>

便利对象


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    

    <script src="node_modules/react/umd/react.development.js">script>
    <script src="node_modules/react-dom/umd/react-dom.development.js">script>
    <script src="node_modules/babel-standalone/babel.js">script>
    <style>
        .demoh{
      
            color:pink;
        }
    style>
head>
<body>

    <div id="demodiv"> div>

    <script type="text/babel">
        let obj={
      
            name:"xixi",
            age:18,
            sex:"男",
            love:"女"
        }
        // [name,age,sex,love]
        // 因为我们便利出来的v是一个变量但是在对象取值的方式中打点不能取变量所以要用另外一种取值方式[]
        let com=(
            <div>
                {
      
                    Object.keys(obj).map((v,i)=>{
      
                        return (
                            <h1>{
      obj[v]}</h1>
                        )
                    })
                }
            </div>
           
        )
        ReactDOM.render(com,document.querySelector("#demodiv"))

    script>

body>
html>

扩展小知识—render重新渲染


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    <script src="node_modules/react/umd/react.development.js">script>
    <script src="node_modules/react-dom/umd/react-dom.development.js">script>
    <script src="node_modules/babel-standalone/babel.js">script>
head>
<body>
    <div id="demodiv">div>
    <script type="text/babel">

        let arr=[111,2222,33333,44444,555555,66666]
        // 创建一个变量用来保存你点了谁
        let num=-1

        // 进行便利
        function list(){
      

           let newhtml= arr.map((v,i)=>{
      
                return (
                    // 在便利出来的内容上添加事件  但是要注意要用驼峰写法i
                    <h1 key={
      i} onClick={
      ()=>{
      num=i;render()}} style={
      {
      color:i==num?'red':''}}>{
      v}</h1>
                )
            })
            // 千万不要忘了return  引用调用这个函数的时候需要返回便利出来的jsx
            return newhtml
        }


      function render(){
      
        ReactDOM.render(list(),document.getElementById("demodiv"))
      }
      render()

        
    script>
body>
html>

组件—面向组件编程

react创建组件的方式有两种 两种都很重要工作的时候 可能都会用

组件的本质 ---- 自定义标签

无状态组件/函数组件/工厂方式组件

组件 首字母大写 首字母大写 首字母大写

基本创建


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    <script src="node_modules/react/umd/react.development.js">script>
    <script src="node_modules/react-dom/umd/react-dom.development.js">script>
    <script src="node_modules/babel-standalone/babel.js">script>
head>
<body>
    <div id="demodiv">div>
    <script type="text/babel">
        // 创建无状态组件
        // 首字母大写
        function Com(){
      
            // 必须return你想要的jsx
            return (
                <div>
                    我是一个组件    
                    
                </div>
            )
        }
        ReactDOM.render(<Com/>,document.getElementById("demodiv"))       
    script>
body>
html>

父子组件

父子组件就是在一个父组件中调用子组件


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    <script src="node_modules/react/umd/react.development.js">script>
    <script src="node_modules/react-dom/umd/react-dom.development.js">script>
    <script src="node_modules/babel-standalone/babel.js">script>
head>
<body>
    <div id="demodiv">div>
    <script type="text/babel">
        // 创建无状态组件
        // 首字母大写
        function Zi(){
      
            // 必须return你想要的jsx
            return (
                <div>
                    我是一个组件    
                    
                </div>
            )
        }
        function Fu(){
      
            return (
                <div>
                    fufufufuffufufufufuf    
                    <Zi/>
                    <Zi/>
                    <Zi/>
                    <Zi/>
                    <Zi/>
                    <Zi/>
                </div>
            )
        }
        
        ReactDOM.render(<Fu/>,document.getElementById("demodiv"))
    script>
body>
html>

类组件

创建一个class 并起名字 继承(extends)React.Component 在其中render一个方法 return你的jsx

class 你的类名(组件名) extends React.Component{
     
	render(){
     
		return (
			你的jsx
		)
	}
}

实例:


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    <script src="node_modules/react/umd/react.development.js">script>
    <script src="node_modules/react-dom/umd/react-dom.development.js">script>
    <script src="node_modules/babel-standalone/babel.js">script>
head>
<body>
    <div id="demodiv">div>
    <script type="text/babel">
        class Mycom extends React.Component{
      
            render(){
      
                return (
                    <div>我是一个组件</div>
                )
            }
        }
        ReactDOM.render(<Mycom/>,document.getElementById("demodiv"))

    script>
body>
html>
父子组件
父子组件
父子组件
父子组件
父子组件



<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    <script src="node_modules/react/umd/react.development.js">script>
    <script src="node_modules/react-dom/umd/react-dom.development.js">script>
    <script src="node_modules/babel-standalone/babel.js">script>
head>
<body>
    <div id="demodiv">div>
    <script type="text/babel">
        class Mycom extends React.Component{
      
            render(){
      
                return (
                    <div>我是一个组件</div>
                )
            }
        }

        class Myfu extends React.Component{
      
            render(){
      
                return (
                    <div>
                        fufuffufufufufufufu    
                        <Mycom/><Mycom/><Mycom/><Mycom/><Mycom/>
                    </div>
                )
            }
        }
        ReactDOM.render(<Myfu/>,document.getElementById("demodiv"))

    script>
body>
html>

props

使用props就可以从外部向组件内部进行数据传递 完成父组件传值给子组件
注意:Props对于使用它的组件来说,是只读的。一旦赋值不能修改。也就是说props的值是不可变的只能在渲染的时候传入无法动态赋值。

props基本语法

函数组件

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    <script src="node_modules/react/umd/react.development.js">script>
    <script src="node_modules/react-dom/umd/react-dom.development.js">script>
    <script src="node_modules/babel-standalone/babel.js">script>
head>
<body>
    <div id="demodiv">div>
    <script type="text/babel">
    // 函数组件使用props   就需要把props当成形参传入即可
        function Zi(props){
      
            return (
                <div>
                    我是一个组件-----{
      props.name}    
                </div>
            )
        }
        function Fu(){
      
            return (
                <div>
                   fufuffufufufufufufu 
                   {
      /* 在子组件被调用的地方  把props传递的值当成一个属性进行传递*/}
                  
                   <Zi name="你好我是传递的数据"/>
                </div>
            )
        }
        
        ReactDOM.render(<Fu/>,document.getElementById("demodiv"))
    script>
body>
html>
类组件

他的props使用是 直接使用this.props.xxx来进行创建


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    <script src="node_modules/react/umd/react.development.js">script>
    <script src="node_modules/react-dom/umd/react-dom.development.js">script>
    <script src="node_modules/babel-standalone/babel.js">script>
head>
<body>
    <div id="demodiv">div>
    <script type="text/babel">
        class Mycom extends React.Component{
      
            render(){
      
                return (
                    <div>
                        我是一个组件
                        {
      /*类组件创建props*/}
                        <h1>{
      this.props.name}</h1>
                    </div>
                )
            }
        }

        class Myfu extends React.Component{
      
            render(){
      
                return (
                    <div>
                        fufuffufufufufufufu    
                        <Mycom name="我是传递的数据么么哒!!!!!"/>
                    </div>
                )
            }
        }
        ReactDOM.render(<Myfu/>,document.getElementById("demodiv"))

    script>
body>
html>

小扩展


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    <script src="node_modules/react/umd/react.development.js">script>
    <script src="node_modules/react-dom/umd/react-dom.development.js">script>
    <script src="node_modules/babel-standalone/babel.js">script>
head>
<body>
    <div id="demodiv">div>
    <script type="text/babel">
        class Mycom extends React.Component{
      
            render(){
      
                // 因为如果由多个props那么我就会写很多变this.props  很麻烦
                // 所以我可以直接在组件中进行结构方便页面使用
               let {
      name,age,sex,love} =this.props
                return (
                    <div>
                        我是一个组件
                        {
      /*类组件创建props*/}
                        <h1>{
      name}</h1>
                        <h1>{
      age}</h1>
                        <h1>{
      sex}</h1>
                        <h1>{
      love}</h1>
                    </div>
                )
            }
        }

        class Myfu extends React.Component{
      
            render(){
      
                return (
                    <div>
                        fufuffufufufufufufu    
                        <Mycom name="我是传递的数据么么哒!!!!!" age="18" sex="男" love="女"/>
                    </div>
                )
            }
        }
        ReactDOM.render(<Myfu/>,document.getElementById("demodiv"))

    script>
body>
html>

props默认值

函数组件

组件名.defaultProps={

​ 你要设置默认值的props:默认值

}


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    <script src="node_modules/react/umd/react.development.js">script>
    <script src="node_modules/react-dom/umd/react-dom.development.js">script>
    <script src="node_modules/babel-standalone/babel.js">script>
head>
<body>
    <div id="demodiv">div>
    <script type="text/babel">
    // 函数组件使用props   就需要把props当成形参传入即可
        function Zi(props){
      
            return (
                <div>
                    我是一个组件-----{
      props.name}    
                </div>
            )
        }
        // props默认值
        Zi.defaultProps={
      
            name:"我是name的默认值"
        }
        function Fu(){
      
            return (
                <div>
                   fufuffufufufufufufu 
                   <Zi/>
                </div>
            )
        }
        
        ReactDOM.render(<Fu/>,document.getElementById("demodiv"))
    script>
body>
html>
类组件

与函数组件一样使用defaultProps


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    <script src="node_modules/react/umd/react.development.js">script>
    <script src="node_modules/react-dom/umd/react-dom.development.js">script>
    <script src="node_modules/babel-standalone/babel.js">script>
head>
<body>
    <div id="demodiv">

    div>
    <script type="text/babel">
        class Mycom extends React.Component{
      
            render(){
      
                let {
      name}=this.props
                return (
                    <div>
                        我是类组件---{
      name}    
                    </div>
                )
            }
        }
        // 类组件也是使用defaultProps 来进行默认值的设置
        Mycom.defaultProps={
      
            name:"你好我是默认值*_!"
        }

        ReactDOM.render(<Mycom name="1111111"/>,document.getElementById("demodiv"))
    script>
body>
html>

props验证

在react15.5版本之后 props验证已经在核心包中移除了所以要使用 需要但需下载prop-types(单词不要错了)

下载: npm install --save prop-types

官网:https://react.docschina.org/docs/typechecking-with-proptypes.html

函数组件props验证

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    <script src="node_modules/react/umd/react.development.js">script>
    <script src="node_modules/react-dom/umd/react-dom.development.js">script>
    <script src="node_modules/babel-standalone/babel.js">script>
    <script src="node_modules/prop-types/prop-types.js">script>
head>
<body>
    <div id="demodiv">div>
    <script type="text/babel">
    // 函数组件使用props   就需要把props当成形参传入即可
        function Zi(props){
      
            return (
                <div>
                    我是一个组件-----{
      props.name}    
                </div>
            )
        }
     
        let num=123;
        // props验证
        Zi.propTypes={
      
            name:PropTypes.number
        }
        function Fu(){
      
            return (
                <div>
                   fufuffufufufufufufu 
                   <Zi name={
      num}/>
                </div>
            )
        }
        
        ReactDOM.render(<Fu/>,document.getElementById("demodiv"))
    script>
body>
html>
类组件验证

同函数组件

扩展

刚才在类组件中我们多次调用了this.props 解决方式是 我们使用解构来进行快速赋值

但是有个问题 就是在传递参数的时候也很麻烦

那么可以使用扩展运算符进行一次传递多个数据


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    <script src="node_modules/react/umd/react.development.js">script>
    <script src="node_modules/react-dom/umd/react-dom.development.js">script>
    <script src="node_modules/babel-standalone/babel.js">script>
head>
<body>
    <div id="demodiv">div>
    <script type="text/babel">
        class Mycom extends React.Component{
      
            render(){
      
               let {
      name,age,sex,love} =this.props
                return (
                    <div>
                        我是一个组件
                        {
      /*类组件创建props*/}
                        <h1>{
      name}</h1>
                        <h1>{
      age}</h1>
                        <h1>{
      sex}</h1>
                        <h1>{
      love}</h1>
                    </div>
                )
            }
        }

        let obj={
      
            name:"xixi",
            age:99,
            sex:"nan",
            love:"nv"
        }
        class Myfu extends React.Component{
      
            render(){
      
                return (
                    <div>
                        fufuffufufufufufufu   
                        {
      /*一次传递多个props可以使用扩展运算符*/} 
                        <Mycom {
      ...obj}/>
                    </div>
                )
            }
        }
        ReactDOM.render(<Myfu/>,document.getElementById("demodiv"))

    script>
body>
html>

state–状态机制

在react中开发者只需要关心数据。数据改变页面就会发生改变
数据等同于状态。状态改变-页面绑定的数据就由react进行改变

组件被称之为“状态机”,视图与状态一一对应

基本语法


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    <script src="node_modules/react/umd/react.development.js">script>
    <script src="node_modules/react-dom/umd/react-dom.development.js">script>
    <script src="node_modules/babel-standalone/babel.js">script>
head>
<body>
    <div id="demodiv">div>
    <script type="text/babel">
        // state状态机制
        class Mycom extends React.Component{
      
            constructor(props){
      
                super(props)
                // 创建变量数据
                this.state={
      
                    name:"xixi",
                    arr:[111,222,333],
                    obj:{
      
                        sex:"男"
                    }
                }

            }
            render(){
      
                return (
                    <div>
                        {
      /*使用state数据*/}
                        <h1>我是数据是----{
      this.state.name}</h1>
                        {
      /*react状态的修改必须使用this.setState()进行修改*/}
                        <button onClick={
      ()=>{
      this.setState({
      name:"我变了"})}}>点我改变</button>
                    </div>
                )
            }
        }

  
        ReactDOM.render(<Mycom/>,document.getElementById("demodiv"))

    script>
body>
html>

setState()深入讨论

异步的


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    <script src="node_modules/react/umd/react.development.js">script>
    <script src="node_modules/react-dom/umd/react-dom.development.js">script>
    <script src="node_modules/babel-standalone/babel.js">script>
head>
<body>
    <div id="demodiv">div>
    <script type="text/babel">

    //  状态-----setState---是异步的
    class Com extends React.Component{
      
        constructor(props){
      
            super(props)
            this.state={
      
                text:"你好"
            }
        }

        fun=()=>{
      
        //    this.setState({
      
        //        text:"你坏!!!!!!"
        //    })
        //    为了证明setState是异步的  那么我们可以在修改之后console一下修改的数据
        //    如果这个打印的数据是修改之后的  那么也就能证明他是同步的  反之他就是异步的
        // console.log(this.state.text)


            // 分割线分割线分割线分割线分割线分割线分割线分割线分割线分割线分割线

            // 我就是想当数据改变之后在打印出改变之后的结果  怎么办?
           this.setState({
      
               text:"你坏!!!!!!22222"
           },()=>{
      
               console.log(this.state.text)
           })
        }

        render(){
      
            return (
                <div>
                    <h1>{
      this.state.text}</h1>
                    <button onClick={
      this.fun}>点我修改</button>
                    
                </div>
            )
        }
    }
      ReactDOM.render(<Com/>,document.getElementById("demodiv"))
 
    script>
body>
html>

自动调用render重新渲染

在没有学过state之前 我们如果想修改数据并且让页面改变 我们需要手工让render重新渲染

因为当我们调用了setState之后他就会自动的触发render渲染从而让页面的数据根据状态的改变而随之发生改变

总结

当调用了setState之后发生了什么?

当调用了setState之后首先他是进行state状态修改的 但是它在修改的过程中是一个异步操作 他会把所有的修改任务方一个执行缓冲区中进行等待 等待着统一数据修改 修改之后也会自动调用render方法进行页面重新渲染(自动调用render进行了一个调和的过程)

小扩展—插入字符串标签

dangerouslySetInnerHTML = { { __html:你要插入的字符串 }}


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    <script src="node_modules/react/umd/react.development.js">script>
    <script src="node_modules/react-dom/umd/react-dom.development.js">script>
    <script src="node_modules/babel-standalone/babel.js">script>
head>
<body>
    <div id="demodiv">div>
    <script type="text/babel">

   
    class Com extends React.Component{
      
        constructor(props){
      
            super(props)
            // this.state={
      
            //     demohtml:"

我是字符串标签

"
// } this.demohtml="

我是字符串标签

"
} render(){ return ( <div> <div> { this.demohtml} </div> { /* 上面的写法直接把一个字符串标签展示是会原样输出的 dangerouslySetInnerHTML = { { __(双底杠)html:你要插入的字符串 }} */} <div dangerouslySetInnerHTML={ { __html:this.demohtml}}></div> </div> ) } } ReactDOM.render(<Com/>,document.getElementById("demodiv"))
script> body> html>

ref

React提供的这个ref属性(不能在无状态组件上使用 ref 属性,因为它们没有实例)表示为对组件真正实例的引用其实就是ReactDOM.render()返回的组件实例

ReactDOM.render()渲染组件时返回的是组件实例;而渲染dom元素时,返回是具体的dom节点。

一句话总结:
标识组件内部的元素

使用

字符串

回调函数

createRef


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    <script src="node_modules/react/umd/react.development.js">script>
    <script src="node_modules/react-dom/umd/react-dom.development.js">script>
    <script src="node_modules/babel-standalone/babel.js">script>
head>
<body>
    <div id="demodiv">div>
    <script type="text/babel">

 
    class Com extends React.Component{
      
        constructor(props){
      
            super(props)
            // 1.创建createref
           this.myRef=React.createRef()
        }
        funa=()=>{
      
            // 字符串方式
            this.refs.demoref.style.color="red";
        }
        funb=()=>{
      
            // 回调函数方式ref
            this.demoh.style.backgroundColor="pink";
          
        }
        func=()=>{
      
            // createref方式ref
            console.log(this.myRef.current);
            this.myRef.current.style.fontSize="100px";
        }
        render(){
      
            return (
                <div>
                  <h1 ref="demoref">字符串方式使用ref</h1>
                  <button onClick={
      this.funa}>点我修改上面的颜色</button>
                  <hr/>

                  {
      /* 

{this.你创建个变量=形参}}>回调函数方式创建ref

*/
} <h1 ref={ (xiaoming)=>{ this.demoh=xiaoming}}>回调函数方式创建ref</h1> <button onClick={ this.funb}>点我修改上面的背景颜色</button> <hr/> { /*2挂载*/} <h1 ref={ this.myRef}>createRer的方式</h1> <button onClick={ this.func}>点我修改上面的字体大写</button> </div> ) } } ReactDOM.render(<Com/>,document.getElementById("demodiv"))
script> body> html>

React受控组件

React负责渲染表单的组件。同时仍然控制用户后续输入时所发生的变化。值是来自于state控制的 输入表单元素称为“受控组件”。

React事件处理

React事件绑定属性的命名采用小驼峰式写法。

绑定函数的过程中不加() 否则函数会立即执行

阻止事件默认行为与阻止冒泡

同js原生方式 例如:React中阻止默认行为使用preventDefault();

this修改


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    <script src="node_modules/react/umd/react.development.js">script>
    <script src="node_modules/react-dom/umd/react-dom.development.js">script>
    <script src="node_modules/babel-standalone/babel.js">script>
head>
<body>
    <div id="demodiv">div>
    <script type="text/babel">
    class Com extends React.Component{
      
        constructor(props){
      
            super(props)
            this.state={
      
                text:"你好"
            }
            // 提前绑定
            this.fund=this.fund.bind(this)
        }
        // 错误的写法
        
        funa(){
      
            this.setState({
      
                text:"你好么么哒"
            })
        }
        // 方式1:通过bind方法进行原地绑定,从而改变this指向
        funb(){
      
            this.setState({
      
                text:"你好么么哒bbbb"
            })
        }
        // 方式2:通过创建箭头函数
        func=()=>{
      
            this.setState({
      
                text:"你好么么哒cccc"
            })
        }
        // 方式3:在constructor中提前对事件进行绑定
        fund(){
      
            this.setState({
      
                text:"你好么么哒ddddd"
            })
        }
        // 方式4-1:将事件调用的写法改为箭头函数的形式
        // 方式4-2:将事件调用的写法改为箭头函数调用函数
        funf(){
      
            this.setState({
      
                text:"你好么么哒fffff"
            })
        }

        render(){
      
            return (
                <div>
                  <div>
                    <h1>错误的写法 ----- {
      this.state.text}</h1>
                    <button onClick={
      this.funa}>点我修改数据</button>  
                  </div>
                  <div>
                        <h1>方式1:通过bind方法进行原地绑定,从而改变this指向 ----- {
      this.state.text}</h1>
                        <button onClick={
      this.funb.bind(this)}>点我修改数据</button>  
                  </div>
                  <div>
                        <h1>方式2:通过创建箭头函数 ----- {
      this.state.text}</h1>
                        <button onClick={
      this.func}>点我修改数据</button>  
                  </div>
                  <div>
                        <h1>方式3:在constructor中提前对事件进行绑定 ----- {
      this.state.text}</h1>
                        <button onClick={
      this.fund}>点我修改数据</button>  
                  </div>
                  <div>
                        <h1>方式4-1:将事件调用的写法改为箭头函数的形式 ----- {
      this.state.text}</h1>
                        <button onClick={
      ()=>{
      this.setState({
      text:"你好么么哒eeeee"})}}>点我修改数据</button>  
                  </div>
                  <div>
                        <h1>方式4-2:将事件调用的写法改为箭头函数调用函数 ----- {
      this.state.text}</h1>
                        <button onClick={
      ()=>{
      this.funf()}}>点我修改数据</button>  
                  </div>
                    
                </div>
            )
        }
    }

      ReactDOM.render(<Com/>,document.getElementById("demodiv"))
    
      
        
    script>
body>
html>

函数参数传递


<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    <script src="node_modules/react/umd/react.development.js">script>
    <script src="node_modules/react-dom/umd/react-dom.development.js">script>
    <script src="node_modules/babel-standalone/babel.js">script>
head>
<body>
    <div id="demodiv">div>
    <script type="text/babel">


    class Com extends React.Component{
      
        fun=(val)=>{
      
            console.log(val)
        }
        render(){
      
            return (
                <div>
                    {
      /*事件参数传递方式1   使用bind方式*/}
                    
                   <button onClick={
      this.fun.bind(this,"我是参数1")}>点我打印内容</button>
                    
                   <hr/>
                    {
      /*事件参数传递方式1   使用箭头函数的方式调用函数*/}
                    <button onClick={
      ()=>{
      this.fun("哈哈")}}>点我打印内容</button>
                </div>
            )
        }
    }

      ReactDOM.render(<Com/>,document.getElementById("demodiv"))
    
      
        
    script>
body>
html>

脚手架 create-react-app

创建

npm install -g create-react-app 安装脚手架

create-react-app --version 查看版本

create-react-app 项目名 创建项目

cd 项目名 切换到创建好的项目中

npm start 启动运行(所有命令中 只有start可以不加run)

组件

基本使用—组件的创建

新建一个components的文件夹用来容纳组件

在其中创建以.jsx结尾的文件 并写入组件代码

类组件

import React, { Component } from 'react'

export default class home extends Component {
    render() {
        return (
            
你好么么哒 我是一个组件
) } }

函数组件

后面学到hook在说

基本使用—组件的使用

1.引用

2.使用

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
// 引用
import Home from './components/home.jsx';
import reportWebVitals from './reportWebVitals';

ReactDOM.render(
  
    {/* 使用 */}
    
  ,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

扩展小知识–空标签

1.就是空标签(了解就好 不要用)

 				return (
                            <>
                                

下标:{i}

值: {v}

)

2.Fragment 用来包裹代码 但是不参与页面渲染的

先引用

import React, { Component,Fragment } from ‘react’

在使用

 			{
                    this.state.arr.map((v,i)=>{
                        return (
                            
                                

下标:{i}

值: {v}

) }) }

props

与本地模式一模一样

import React, { Component } from 'react'

export default class zi extends Component {
    render() {
       let {name}=this.props
        return (
            
zizizziziziziziz---{name}
) } }

props 验证

还是使用propTypes

state 的使用

他的使用和本地模式一样

创建

this.state={

}

使用

this.state.xxxx

修改

this.setState({})

事件

从事件的创建 到this的指向 再到参数的传递 和本地模式一模一样

列表渲染

循环数据和本地模式一模一样

this.props.children

默认情况下组件的开标签和关标签之间的内容能显示吗?

不能显示

this.props.children 表示当前组件所有的子节点

this.props.children的值有三种可能:
1.如果当前组件没有子节点,它就是undefined;
2.如果有一个子节点,数据类型是Object;
3.如果有多个子节点,数据类型就是array

扩展—强制渲染

如果数据没由在state中 而且我还想让数据变了页面也随之发生更新怎么办?

本地模式中 我们可以使用 冲新触发render的写法

在脚手架中不能 不能向本地一样

forceUpdate()就是重新调用render渲染。有些变量不在state上,当时你又想达到这个变量更新的时候,刷新render;

import React, { Component } from 'react'

export default class zib extends Component {
    constructor(props){
        super(props)

        this.text="我是一个不在状态中的变量!!!"
    }
    render() {
        return (
            
zib---{this.text}
) } }

组件传值

正传

props

逆传

在react中没有单独的语法来实现逆向传值 他是借由props来实现的

1.通过事件调用一个props接收父组件传递过来的一个函数

import React, { Component } from 'react'

export default class zic extends Component {

    render() {
        return (
            

组件逆向传值

{/* 1。逆向传值必须通过事件来触发 */}
) } }

2.父组件创建传递给子组件的函数并且加入形参

import React, { Component } from 'react'
import Zic from "./zic.jsx"
export default class fu extends Component {
    emit=(text)=>{
        console.log(text)
    }
    render() {
        return (
            
fufufufufufufufu
) } }

同胞传值 pubsub-js

下载 : npm install --save pubsub-js

抛出一个自定义事件publish(“事件名”,“数据”)

import React, { Component } from 'react'
// 1.引用pubsub-js
import PubSub from "pubsub-js"
export default class zid extends Component {
    fun(){
        // 2.抛出一个自定义事件
        // PubSub.publish("自定义事件名","数据")
        PubSub.publish("xiongpao","我是zid的数据")
    }
    render() {
        return (
            
zid
) } }

接收自定义事件

import React, { Component } from 'react'
// 1.引用
import PubSub from "pubsub-js"
export default class zie extends Component {

    componentDidMount() {
        // 2.监听自定义事件  PubSub.subscribe("监听的事件",(事件,数据)=>{})

        PubSub.subscribe("xiongpao",(a,b)=>{
            console.log(a)
            console.log(b)
        })
    }
    render() {
        return (
            
zie
) } }

跨组件传值–context 上下文对象

context 上下文对象来实现

context:上下文对象

context很好的解决了跨组件传值的复杂度。可以快速的进行跨组件数据的传递。

想要使用context进行跨组件传值那么就要使用createContext()方法同时方法中给我们提供了两个对象:

Provider对象 生产者---->用来生产数据
Consumer对象 消费者---->用来使用数据

1.创建一个上下问对象的文件 并且设置this.props.children

// 容纳上下文对象
import React, { Component } from 'react'

export default class index extends Component {
    render() {
        return (
            
{/* 1.添加this.props.children */} {this.props.children}
) } }

2.在根里面引用相关的上下文对象组件 并使用

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import Home from './components/contextcon/ye.jsx';
// 引用上下文对象
import Index from "./context/index.js"
import reportWebVitals from './reportWebVitals';

ReactDOM.render(
  
    {/* 使用 */}
    
  ,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

3.创建上下文对象

// 容纳上下文对象
import React, { Component, createContext } from 'react'

// 创建上下文对象数据
let context=createContext()
let {Provider,Consumer}=context
class Index extends Component {
    render() {
        return (
            
{/* 1.添加this.props.children */} {this.props.children}
) } } export {Index,Consumer}

4 修改根中的组件引用

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import Home from './components/contextcon/ye.jsx';
// 引用上下文对象
import {Index} from "./context/index.js"
import reportWebVitals from './reportWebVitals';

ReactDOM.render(
  
    {/* 使用 */}
    
  ,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

5 在组件中使用

import React, { Component } from 'react'
import Fu from "./fu.jsx"
import {Consumer} from "../../context/index.js"
export default class ye extends Component {
    render() {
        return (
            
我是爷爷组件 { (value)=>{ return ( {value} ) } }
) } }

如果要有多个生产者的数据应该 在创建Provider的时候传递进去一个对象

    
                    {this.props.children}
    
               

跨层级传值还有一个技术叫redux(后面会由专门的课来上)

HOC 高阶组件

高阶组件就是一类功能需要被不同的组件公用。可以复用在react组件中的代码与逻辑

HOC–参数是组件同时返回值也是组件

1.创建高阶组件

import React, {
      Component } from 'react'

// HOC---参数是一个组件   返回值还是一个组件
// 因为参数是一个组件所以形参必须大写
let Hocdemo=(Com)=>{
     
    return class index extends Component {
     
        render() {
     
            return (
                <div>
                    <h1>2102HOC</h1>
                    <Com/>
                </div>
            )
        }
    }
}
export default Hocdemo

2.调用

引用高阶组件 并且修改暴露到最下面 使用高阶组件(当前组件)

import React, { Component } from 'react'
import Hocdemo from "../hoc/index.js"
class hoccom extends Component {
    render() {
        return (
            

我是测试HOC的一个组件

) } } export default Hocdemo(hoccom)

高阶组件传递props

默认情况下 如果一旦当前组件使用了HOC那么在进行props正向传值的时候就没有办法接收到数据

所以我们需要在高阶组件中进行数据的传递

import React, { Component } from 'react'

// HOC---参数是一个组件   返回值还是一个组件
// 因为参数是一个组件所以形参必须大写
let Hocdemo=(Com)=>{
    return class index extends Component {
        render() {
            return (
                

2102HOC

{/* 传递props给组件 */}
) } } } export default Hocdemo

HOC–反向继承

反向继承最核心作用,是渲染劫持(拦截了渲染可以让我们进行条件渲染)。
反向继承就是高阶组件的条件渲染

反向继承就是高阶组件的条件渲染

// import React, { Component } from 'react'

// // HOC---参数是一个组件   返回值还是一个组件
// // 因为参数是一个组件所以形参必须大写
// let Hocdemo=(Com)=>{
//     return class index extends Component {
//         render() {
//             return (
//                 
//

2102HOC

// {/* 传递props给组件 */} // //
// ) // } // } // } // export default Hocdemo // 反向继承 import React, { Component } from 'react' let Hocdemo=(Com,tj)=>{ return class index extends Com { render() { if(tj>=18){ return (
你一年满可以正常进入
) }else{ return (
已经进入青少年模式
) } } } } export default Hocdemo

路由

自动创建路由 就不要想了

根据不同的url 来切换对应的组件

实现spa(单页面应用)应用:
整个项目只有一个完整页面
页面切换不会刷新页面(不会感觉页面的闪烁 更加贴近原声应用的体验)

分类

React-Router:提供了一些router的核心API,包括Router, Route, Switch等,但是它没有提供 DOM 操作进行跳转的API。

**React-Router-DOM:**提供了 BrowserRouter, Route, Link等 API,我们可以通过 DOM 的事件控制路由。例如点击一个按钮进行跳转,大多数情况下我们是这种情况,所以在开发过程中,我们更多是使用React-Router-DOM。

路由模式

HashRouter (hash模式)
url中会有个#,例如localhost:3000/#,HashRouter就会出现这种情况,它是通过hash值来对路由进行控制。如果你使用HashRouter,你的路由就会默认有这个#。刷新不会丢失

BrowserRouter(历史记录模式 )
是通过历史记录api来进行路由的切换的很多情况下我们则不是这种情况,我们不需要这个#,因为它看起来很怪,这时我们就需要用到BrowserRouter。刷新会丢失404(上线中会出现问题 本地开发中不会)

基本路由实现

1.下载对应的路由库 react-router-dom

2.引用路由模式在全局中 进行配置

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
// 1.引用路由模式
import {BrowserRouter} from "react-router-dom"
ReactDOM.render(
  // 2.使用
  
    
  ,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

3.创建路由页面组件(在src下新建一个views/pages/随便的名字 在其中创建。jsx结尾的组件)

4.配置路由规则与出口 (在src下创建一个router的文件夹里面创建index。js用来容纳路由出口与规则)

使用Route来进行配置 里面两个属性 path路径 component引用的组件

import React, { Component } from 'react'
// 1.引用
import {Route} from "react-router-dom"
// 3.引用路由页面组件
import Home from "../views/home.jsx"
import Phone from "../views/phone.jsx"
import Shop from "../views/shop.jsx"
import User from "../views/user.jsx"

export default class index extends Component {
    render() {
        return (
            
{/* 2.使用 */}
) } }

5.在全局配置文件中引用路由规则页面

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
// 引用路由规则页面
import App from './router/index.js';
import reportWebVitals from './reportWebVitals';
// 1.引用路由模式
import {BrowserRouter} from "react-router-dom"
ReactDOM.render(
  // 2.使用
  
    
  ,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

路由导航

声明式

Link: 仅仅是最基础的导航

NavLink : 在基础的导航功能之上添加了动态类名 方便我们设置后续的样式

如果在vscode的终端中启动项目可能会无效 在外部cmd中启动

navlink默认添加的类名: active 如果想修改这个类名

import React, { Component } from 'react' // 1.引用 import {Route,Link,NavLink} from "react-router-dom" // 3.引用路由页面组件 import Home from "../views/home.jsx" import Phone from "../views/phone.jsx" import Shop from "../views/shop.jsx" import User from "../views/user.jsx" export default class index extends Component { render() { return (

点我去home    点我去phone    点我去shop    点我去user    {/* 2.使用 */}
) } }

编程式

this.props.history.push("/xxxx")进行页面跳转

在这里一定一定要注意 在react中使用路由的编程式导航 一定要记住 默认只能在被路由所管理的页面中使用因为不在路由所管理的页面就没有路由切换属性

一下就是不在路由所管理的页面使用编程式导航

import React, { Component } from 'react'
// 1.引用
import {Route,Link,NavLink} from "react-router-dom"
// 3.引用路由页面组件
import Home from "../views/home.jsx"
import Phone from "../views/phone.jsx"
import Shop from "../views/shop.jsx"
import User from "../views/user.jsx"

export default class index extends Component {
    fun=()=>{
        // 编程式导航
        this.props.history.push("/user")
    }
    render() {
        return (
            
点我去home    点我去phone    点我去shop    点我去user    {/* 2.使用 */}
) } }
解决react编程式路由push报错

如果我就是想在不是被路由所管理的页面使用路由的编程式导航怎么办?

使用withRouter这个高阶组件

1.引用withRouter 这个高阶组件

2.修改暴露到最下面 然后使用他

import React, { Component } from 'react'
// 1.引用
import {Route,Link,NavLink,withRouter} from "react-router-dom"
// 3.引用路由页面组件
import Home from "../views/home.jsx"
import Phone from "../views/phone.jsx"
import Shop from "../views/shop.jsx"
import User from "../views/user.jsx"


class index extends Component {
    fun=()=>{
        // 编程式导航
        this.props.history.push("/user")
    }
    render() {
        return (
            
点我去home    点我去phone    点我去shop    点我去user    {/* 2.使用 */}
) } } export default withRouter(index)
更多编程式导航

replace() 替换当前路径

goBack()后退

goForward()前进

exact 精准匹配

另外需要注意一点的是嵌套路由不要加exact属性

  render() {
        return (
            
点我去home    点我去phone    点我去shop    点我去user    {/* 2.使用 */} {/* 精准匹配--严格按照路径进行匹配 */}
) }

404

在路由规则的最下面 使用

Switch 唯一渲染

只渲染当前范围内的一项

redirect 重定向

    			 {/* 2.使用 */}
                {/* Switch 唯一渲染 */}
                
                 
                    
                    
                    
                    
                    {/* 重定向 */}
                       {/* 精准匹配--严格按照路径进行匹配 */}
                    
                    {/* 配置404页面  千万记住放在最下面 */}
                    
                 

路由传参

params

优势 : 刷新地址栏,参数依然存在

缺点 : 只能传字符串,并且,如果传的值太多的话,url会变得长而丑陋。

使用

1.在路由规则中进行接收变量的设置

 			  
                    
                    
                    
                    {/* 设置路径接收参数 */}
                    
                    
                    {/* 404页面 */}
                    
                

2.发送



this.props.history.push(“/user/我是params方式传递的数据”)

3.接收

this.props.match.params.xxxx

import React, { Component } from 'react'

export default class user extends Component {
    render() {
        return (
            
user--{this.props.match.params.num}
) } }

state

优势:传参优雅地址栏不显示传递的数据,传递参数可传对象;

缺点:刷新地址栏,参数丢失

使用:

1.发送



this.props.history.push({pathname:"/路径",state:{text:"我是state的路由传参"}})

2.接收

this.props.location. state.xxxx

import React, {
      Component } from 'react'

export default class shop extends Component {
     
    render() {
     
        return (
            <div>
                shop---{
     this.props.location.state.text}
            </div>
        )
    }
}

二级路由/嵌套路由/多级路由

1.创建路由页面组件

2.创建路由规则

​ 就是在你对应的一级路由页面中使用Route来进行创建

import React, { Component } from 'react'
import {Route,NavLink} from "react-router-dom"

import Era from "./er/era.jsx"
import Erc from "./er/erc.jsx"
export default class phone extends Component {
    render() {
        return (
            
phone era   erc  
) } }

路由render渲染写法

就是给路由在渲染加载之前 有一个可以写逻辑的地方(可以进行一些业务操作 根据指定的结果有选择性的显示或者不显示当前这个路由页面)

     {/* 路由的render渲染写法 */}
    {return true?: }}/>

redux

redux是专门作状态管理的js库(不是react插件库可以用在其他js框架中例如vue,但是基本用在react中)

Redux是为javascript应用程序提供一个状态管理工具

集中的管理react中多个组件的状态

redux三大原则

单一数据源:整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中

State 是只读的:唯一改变 state 的方法就是触发 action,action 是一个用于描述已发生事件的普通对象。

使用纯函数来执行修改:为了描述 action 如何改变 state tree ,你需要编写 reducers(一些纯函数,它接收先前的 state 和 action,)

基本使用

1.下载redux npm install --save redux

2.创建文件夹 store 在创建文件 index.js 用来容纳相关redux代码

3.开始创建store对象

// 1.引用redux   并且解构出 createStore方法来进行store对象
import {
     createStore} from "redux"

// 6创建数据
let data={
     
    name:"xixi",
    age:18
}

// 5创建一个纯函数里面包含数据与修改动作  7 把上面创建的数据用es6函数形参默认值的方式传递给state
let reducer=(state=data,action)=>{
     
        return state
}

// 2.开始创建store对象  4.给store传入数据与修改动作reducer
let store=createStore(reducer)

// 3.暴露store对象
export default store

4。测试一下看看创建的对不对

在src下的index.js全局配置文件中测试

// 测试下store配置是否正确
import store from "./store/index.js"
//getState()是获取数据
console.log(store.getState().name);

5.在组件中使用

import React, { Component } from 'react'
// 1.引用
import store from "../store/index.js"
export default class home extends Component {
    constructor(props){
        super(props)
        this.state={
            // 从store中获取并且赋值给state
            storeText:store.getState().name
        }
    }
    render() {
        return (
            
home----{this.state.storeText}
) } }

修改

1.通过dispatch调用修改操作

  add=()=>{
        // 通过dispatch()来调用触发修改
        store.dispatch({type:"ADD_LIST_NUM"})//type是修改的动作名
    }
    del=()=>{
        store.dispatch({type:"DEL_LIST_NUM"})
    }

2.开始创建这些修改的动作


import {createStore} from "redux"

let data={
    name:"xixi",
    age:18
}

let reducer=(state=data,action)=>{
        switch (action.type) {//判断任务名 从而执行各种修改操作
            case "ADD_LIST_NUM":
          
                return {...state,age:state.age+1}
                break;
            case "DEL_LIST_NUM":
            
                return {...state,age:state.age-1}
                break;
        
            default:
                // 既没有添加页面删除那么就是读取初始化数据
                return state
              
        }

       
}

let store=createStore(reducer)

export default store

问题 大家都发现数据变了 但是页面的展示没有变 怎么办?

因为数据是在store里面变了 但是页面中并没有重新render所以页面不要更新

3.使用subscribe()来监听store中的数据变化

   constructor(props){
        super(props)
        this.state={
            // 从store中获取并且赋值给state
            storeText:store.getState().age
        }

        // 监听store的数据   当数据改变就会触发执行setState 当调用setState 
        // render就会 重新渲染 那么页面就更新了
        store.subscribe(()=>{
            this.setState({
                storeText:store.getState().age
            })
        })
    }

参数传递

在使用dispatch的时候可以向redux中传递参数

store.dispatch({
     type:"ADD_LIST_NUM",num:10})//传递一个num的数据

在action中进行使用

let reducer=(state=data,action)=>{
     
        switch (action.type) {
     
            case "ADD_LIST_NUM":
          
                return {
     ...state,age:state.age+action.num}//使用数据
                break;
            case "DEL_LIST_NUM":
            
                return {
     ...state,age:state.age-1}
                break;
        
            default:
                return state
              
        }

       
}

redux封装

封装派发动作

今后会有很多个动作 那么我们就把这些派发动作放在一起 好管理

1.在store文件夹下创建一个文件名字随便起(actionCreator.js)

2.在当前文件中封装任务名

// 封装派发动作
export let up=()=>{
    return {type:"UP_DATA"}
}

3.在想使用这个派发动作的组件中引用使用

引用的时候 如果是 当前要使用多个模块中的东西要引很多次非常麻烦 所以我们可以使用

import * as 随便起个名字 from 引用文件路径     //来进行统一全部引用
import React, { Component } from 'react'
import store from "../store/index.js"
import * as ac from "../store/actionCreator.js"//引用封装的任务
export default class home extends Component {
    constructor(props){
        super(props)
        this.state={
            age:store.getState().age
        }
      
    }

    componentDidMount() {
        store.subscribe(()=>{
            this.setState({
                age:store.getState().age
            })
        })
    }
    
    fun(){
        // 调用redux的修改
        store.dispatch(ac.up())  //使用封装的任务
    }
    render() {
        return (
            

redux的基本操作--{this.state.age}

) } }

我们也可以给redux中传递payload

在封装动作的时候也可以给当前函数添加形参来接收传递的数据

export let up=(text)=>{
    return {type:"UP_DATA",text}
}

封装派发动作名

方便后期统一进行名字的修改

1.在store下创建actionType.js

2.在其中进行名字的封装

export const UP_DATA="UP_DATA"

// let typename="WL"
// let obj={
//     UP_DATA:typename+"_DATA",//UP_DATA
//     UP_DEL:typename+"_DEL"//UP_DEL
// }

// export default obj

3.在调用的时候引用使用

reducer 模块封装于合并

  1. 新建一个module的文件夹用来存放单独组件的模块

  2. 把原来写在一起的reducer内容单独放到一个模块文件中

    // 就是单独组件的数据与修改
    import * as at from "../actionTypes.js"
    
    let data={
           
        name:"xixi",
        age:19
    }
    
    let homereducer=(state=data,action)=>{
           
        
        switch (action.type) {
           
            case at.UP_DATA:
                return {
           ...state,age:action.text}
                break;
        
            default:
                return state
                break;
        }
        
    }
    export default homereducer
    

    3.创建一个reducer.js进行和并

    // 我需要把所有的render模块在当前文件合并成一个
    // 1.引用所有你要合并的模块
    import homereducer from "./module/homem.js"
    import shopreducer from "./module/shopm.js"
    // 2.引用合并的工具方法 combineReducers合并模块
    import {
           combineReducers} from "redux"
    // 3.开始合并
    let reducer=combineReducers({
           
        homem:homereducer,
        shopm:shopreducer
    })
    
    export default reducer
    

    4.在store对象种引用这个合并的文件 并且传入最终合并成功的reducer

    import {
           createStore} from "redux"
    import reducer from "./reducer.js"
    
    let store=createStore(reducer)
    
    export default store
    

    5.因为使用了模块所以在使用数据的时候需要是 store.getState().模块名.数据

    react-redux

react-redux是专门为reacr开发的状态管理工具

下载:cnpm install --save react-redux

使用:

1.设置provider 在全局配置文件中引用使用

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './components/reactreduxcom.jsx';
import reportWebVitals from './reportWebVitals';
// 1.引用react-redux  并且结构出Provider
import {Provider} from "react-redux"
// 2.引用store
import store from "./store/index.js"
ReactDOM.render(
  // 3.把store传递给所有的子组件
  
    
  ,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

2.在组件中引用connect用来关联当前组件与store

​````
import React, { Component } from 'react'
// 1.引用连接的高阶组件
import {connect} from "react-redux"
class reactreduxcom extends Component {
    render() {
        return (
            

react-redux的使用

) } } // 因为connect是一个方法 当这个方法被调用之后才是一个高阶组件HOC export default connect()(reactreduxcom)

3.把redux的数据传递给组件来接收

export default connect(state=>({
     state}))(reactreduxcom)

4.读取 this.props.state.模块名.xxxx

  

react-redux的使用---{this.props.state.homem.name}

5.修改

 fun=()=>{
     
        this.props.dispatch(updata("我是使用react-redux修改的"))
    }

axios 使用

与vue相同

跨域

要解决跨域 使用正向代理
1.找到/node_modules/react-scripts/config/webpackDevServer.config.js 当前文件

2.在文件中找到proxy 使用下面代码替换

proxy:{
        "/api(可以随便写)":{
             target:"请求地址",
             changeOrigin:true,
             "pathRewrite":{
               "^/api(和上面一样)":"/"
             }
        }
    },

3.修改请求为/api

4.重启项目

弹射

刚才在解决跨域的时候配置文件隐藏过深非常麻烦。

使用弹射(把配置文件设置根目录中来)eject

注意注意注意:去公司请不要随便弹射(出问题概不负责)

eject 操作是不可逆的,执行之后会把所有细节都暴露在我们面前,让项目目录变得很庞大。所以不要一上项目就弹射

使用: npm run eject

fetch VS ajax VS axios

传统 Ajax 指的是 XMLHttpRequest(XHR), 最早出现的发送后端请求技术,隶属于原始js中,核心使用XMLHttpRequest对象,多个请求之间如果有先后关系的话,就会出现回调地狱。JQuery ajax 是对原生XHR的封装

axios 是一个基于Promise ,本质上也是对原生XHR的封装,只不过它是Promise的实现版本,符合最新的ES规范,

fetch不是ajax的进一步封装,而是原生js,没有使用XMLHttpRequest对象。

umijs

Umi 是蚂蚁金服的底层前端框架 中文可发音为乌米,是可扩展的企业级前端应用框架。Umi 以路由为基础的,同时支持配置式路由和约定式路由,保证路由的功能完备。同时有强大的插件扩展各种功能

什么时候不能使用umi

需要支持 IE 8 或更低版本的浏览器
需要支持 React 16.8.0 以下的 React
需要跑在 Node 10 以下的环境中
有很强的 webpack 自定义需求和主观意愿
需要选择不同的路由方案

umi与create-react-app的区别

cra就相当于一个毛坯房 在这个脚手架中 仅仅只是帮助我们搭建了react的开发环境与依赖 但是其他相关的内容没有帮助我们创建 要使用路由等技术还需要我们自己去向内部搭建

umi相当于一个精装修 装修了路由部分 我们今后在写react的时候路由部分就不要自己配置了

创建

npm install -g umi / yarn global add umi 全局安装

查看版本 umi -v

新建一个文件夹用来容纳项目

cd到你新建的文件夹下

安装项目 npm或yarn create @umijs/umi-app

安装依赖 cnpm install 或 yarn

启动项目 npm 或 yarn start

运行 http://localhost:8000

dva

dva 是体验技术部开发的 React 应用框架,将上面三个 React 工具库包装在一起,简化了 API,让开发 React 应用更加方便和快捷。
dva = React-Router + Redux + Redux-saga(redux进行异步请求的技术)

你可能感兴趣的:(笔记,react)