React入门2

Posted 临风而眠

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React入门2相关的知识,希望对你有一定的参考价值。

React入门2

文章目录

一.JSX

概念

  • 语法糖
    • 是对javascript的语法的扩展
    • 可在JS中编写html
    • HTML中可嵌套JS

对比

  • 用ES5的语法来创建一个标签,并添加属性

    <!DOCTYPE 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>React Demo:Hello World</title>
    
        <script src="node_modules/react/umd/react.development.js"></script>
        <script src="node_modules/react-dom/umd/react-dom.development.js"></script>
        <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
    </head> 
    <body>
        <div id="app"></div>
        <script type="text/babel">
    
            var hello = React.createElement(
                'h1',
                    className:'red',
                    name:'elysa',
                ,"Hello,World"
            );
            ReactDOM.render(
                hello,document.getElementById('app')
            );
       
        </script>
    </body>
    </html>
    
    • 效果

  • 用语法糖

        <script type="text/babel">
    
            ReactDOM.render(
                <h1 className="red" name="elysa" >Hello,World</h1>    
            ,document.getElementById('app')
            );
    
       
        </script>
    

    因为class是js的关键字,所以用className来区分,但是生成的属性还是class

    注意,在添加属性时, class 属性需要写成 className ,for 属性需要写成 htmlFor ,这是因为 class 和 for 是 JavaScript 的保留字。

    效果一样:

    • 加点样式

      CSS选择器都差点忘了…

      <!DOCTYPE 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>React Demo:Hello World</title>
      
          <script src="node_modules/react/umd/react.development.js"></script>
          <script src="node_modules/react-dom/umd/react-dom.development.js"></script>
          <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
      </head> 
      <style>
          .red
              color:red;
          
      </style>
      <body>
          <div id="app"></div>
          <script type="text/babel">
      
              ReactDOM.render(
                  <h1 className="red" name="elysa" >Hello,World</h1>    
              ,document.getElementById('app')
              );
          
         
          </script>
      </body>
      </html>
      

      底层还是用了createElement,不过语法糖已经封装好了

      • 效果

HTML中穿插js

       var name = 'jack';
        var ele = <h1 className="red" name="jack">Hello,name</h1>;
        ReactDOM.render(
         ele  
        ,document.getElementById('app')
        );
    

Hello,name是在HTML中穿插JS

原则:怎么简洁就怎么写

二.元素渲染

  • 元素发生变化时,会与之前的状态对比,把差异部分的变化渲染上去,而不会将整个标签插入渲染

以定时器为例

<!DOCTYPE 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>React Demo:Hello World</title>

    <script src="node_modules/react/umd/react.development.js"></script>
    <script src="node_modules/react-dom/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
  </head>

  <body>
    <div id="app"></div>
    <script type="text/babel">
      function tick() 
        var time = new Date().toLocaleTimeString();
        var ele = (
          <div>
            <h1 className="red" name="jack">
              hello
            </h1>
            <h2>time</h2>
          </div>
        );
        ReactDOM.render(ele, document.getElementById("app"));
        
      
      setInterval(tick,1000); //每隔一秒执行一次
    </script>
  </body>
</html>

  • 控制台查看发现

    每次更新的仅仅是那个节点,而不是更新整个标签

三.组件和Props

  • 页面多的时候需要使用组件

  • 每个页面相似的功能抽取出来作为组件,如公共UI

    • 公共的修改一次,就能把每个页面的都修改了,这样就能提高开发效率

基本语法

  • React.createClass()
    • 已经不用这个了
  • 函数式组件
    • 无状态组件
  • React.Component

函数式组件
  <body>
    <div id="app"></div>
    <script type="text/babel">
      function Hello()
          return <div>
            <h1>Hello,Jack</h1>
            <p> 年龄:30</p>
            <p> 发量:秃头</p>
            </div>
          
          
      

      ReactDOM.render(<Hello/>, document.getElementById("app"));
        
    </script>
  </body>
  • Hello是一个组件

    • 效果

    • 这种通用函数式组件可以在任意一个页面进行加载

  • 可以向组件传一些参数

    <!DOCTYPE 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>React Demo:Hello World</title>
     
        <script src="node_modules/react/umd/react.development.js"></script>
        <script src="node_modules/react-dom/umd/react-dom.development.js"></script>
        <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
      </head>
      
    
      <body>
        <div id="app"></div>
        <script type="text/babel">
          function Hello(props)
              return <div>
                <h1>Hello,props.name</h1>
                <p> 年龄:props.age</p>
                <p> 发量:秃头</p>
                </div>
              
              
          
    
          ReactDOM.render(<Hello name="jack" age="30"/>, document.getElementById("app"));
            
        </script>
      </body>
    </html>
    
    
  • 此形式无状态

React.Component(带状态组件)
<!DOCTYPE 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>React Demo:Hello World</title>
 
    <script src="node_modules/react/umd/react.development.js"></script>
    <script src="node_modules/react-dom/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
  </head>
  

  <body>
    <div id="app"></div>
    <script type="text/babel">


      class HelloJack extends React.Component
        render()
          return <h1>Hello,Jack</h1>
        
      

      ReactDOM.render(<HelloJack name="jack" age="30"/>, document.getElementById("app"));
        
    </script>
  </body>
</html>

<!DOCTYPE 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>React Demo:Hello World</title>

    <script src="node_modules/react/umd/react.development.js"></script>
    <script src="node_modules/react-dom/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
  </head>

  <body>
    <div id="app"></div>
    <script type="text/babel">


      class HelloJack extends React.Component 
        render() 
          return <div>
            <h1>Hello,this.props.name</h1>
            <p> 年龄:this.props.age</p>
            <p> 发量:秃头</p>
          </div>
        
      

      ReactDOM.render(
        <HelloJack name="jack" age="30" />,
        document.getElementById("app")
      );
    </script>
  </body>
</html>

  • this是React.Component的对象的实例

四.react生命周期

  • 通过生命周期可以看清代码执行流程

  • 看这段代码

    <!DOCTYPE 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>React Demo:Hello World</title>
    
        <script src="node_modules/react/umd/react.development.js"></script>
        <script src="node_modules/react-dom/umd/react-dom.development.js"></script>
        <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
      </head>
    
      <body>
        <div id="app"></div>
        <script type="text/babel">
          class Hello extends React.Component 
            constructor(props) 
              //构造函数
              console.log("初始化阶段");
              //初始化props
              super(props);
              //初始化状态
              //状态即属性内部用到的变量值
              this.state = 
                name: "tom",
                age: 30,
              ;
            
    
            //组件加载前的阶段
            //发起Ajax请求等
            //WillMount执行完之后会调用render
            componentWillMount() 
              console.log("组件加载前");
            
    
            componentDidMount() 
              console.log("组件加载后");
            
    
            //状态发生变化,一定会执行render
            render() 
              console.log("组件加载或者数据更新");
              return (
                <div>
                  <h1>Hello,this.state.name</h1>
                  <p> 年龄:this.state.age</p>
                  <p> 发量:秃头</p>
                </div>
              );
            
          
    
          ReactDOM.render(
            <Hello name="jack" age="30" />,
            document.getElementById("app")
          );
        </script>
      </body>
    </html>
    
    
    • 控制台显示

  • 修改:

    componentWillMount()componentDidMount()前面都加上UNSAFE_

    参考:react新的生命周期

    但奇怪的是此时没有显示组件加载后…

  • 增加button添加交互

     <script type="text/babel">
          class Hello extends React.Component 
            constructor(props) 
              //构造函数
              console.log("初始化阶段");
              //初始化props
              super(props);
              //初始化状态
              //状态即属性内部用到的变量值
              this.state = 
                name: "tom",
                age: 30,
              ;
            
    
            //组件加载前的阶段
            //发起Ajax请求等
            //WillMount执行完之后会调用render
            UNSAFE_componentWillMount() 
              console.log("组件加载前");
            
    
            UNSAFE_componentDidMount() 
              console.log("组件加载后");
            
    
            updateUser = () => 
              //更新数据
              this.setState(
                name: "Tim",
                age: 32,
              );
            ;
    
            shouldComponentUpdate() 
              console.log("数据是否需要更新");
              return true;
            
            componentWillUpdate() 
              console.log("数据将要更新");
            
            componentDidUpdate() 
              console.log("数据已经更新");
            
    
            //状态发生变化,一定会执行render
            render() 
              console.log("组件加载或者数据更新");
              return (
                <div>
                  <h1>Hello,this.state.name</h1>
                  <p> 年龄:this.state.age</p>
                  <p> 发量:秃头</p>
                  <button onClick=this.updateUser>更新数据</button>
                </div>
              );
            
          
    
          ReactDOM.render(
            <Hello name="jack" age="30" />,
            document.getElementById("app")
          );
        </script>
    
    • 当按下button之后:

五.事件处理

  • 在react生命周期那个代码里面

    <button onClick=this.updateUser>更新数据</button>
    

    button设置了onClick事件,绑定了updateUser函数

    需要注意的是,在onClick=this.updateUser这种形式下

    updateUser不能写成

           updateUser()
                  //更新数据
                  this.setState(
                    name: "Tim",
                    age: 32,
                  );
                ;
    

    若写成这样,会找不到this指针

    可以试验一下,写成那样,然后点击button,在控制台中看到报错:

    因为普通函数并没有默认绑定this指针

    只能写成updateUser=function()或者=箭头函数的形式进行动态指定

    updateUser=()=> 
              console.log(this);
              //更新数据
              this.setState(
                name: "Tim",
                age: 32,
              );
            
    
  • 若写成那样:

       updateUser()
              //更新数据
              this.setState(
                name: "Tim",
                age: 32,
              );
            ;
    

    则需要修改为
    <button onClick=() => this.updateUser()>更新数据

    这样也能做到把作用域指向当前实例

  • 还有使用bind的方法,暂时不整理了

  • 无论哪种方法,目的就是把对象挂载到this指针上,才能找到this指针的实例对象

六.条件处理

通过一个登录的形式来学习
共登录、登出、APP三个组件

组件命名开头要大写

  • App为根组件,在App组件里面去控制属性状态的变化来去显示不同的组件

    • 设置初始化状态:

      state = 
      	isLogin : false
      
      

      或者

      constructor(props)
      	this.state = 
      	 isLogin : false
      	
      
      

      此处使用前者

    • 用函数式组件定义登录登出组件

      • 登陆组件

        function Login()
        
        	return <button>Login</button>;
        
        
      • 登出组件

        function Logout()
        
        	return <button>Logout<button>
        
        
    • 在render中获取状态

      render()
      	const isLogin = this.state.isLogin;
      	let button;
      
      	if(isLogin)
      	//加载登录组件
      		button=<Login/>
      	else
      	//加载登出组件
      		button=<Logout/>
      	
      
      
    • 修改App组件的updateUser方法

              upDateUser = () => 
                this.setState(
                  isLogin: true,
                );
              ;
      
  • 目前完整代码

    <!DOCTYPE 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>React Demo:Hello World</title>
    
        <script src="node_modules/react/umd/react.development.js"></script>
        <script src="node_modules/react-dom/umd/react-dom.development.js"></script>
        <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
      </head>
    
      <body>
        <div id="app"></div>
        <script type="text/babel">
          function Login() 
            return <button>Login</button>;
          
          function Logout() 
            return <button>Logout</button>;
          
          class App extends React.Component 
            state = 
              isLogin: false,
            ;
            upDateUser = () => 
              this.setState(
                isLogin: true,
              );
            ;
            render() 
              const isLogin = this.state.isLogin;
              let button;
              if (isLogin) 
                button = <Login />;
               else 
                button = <Logout />;
              
              return (
                <div>
                  <h1>Hello</h1>
                  button
                  <button onClick=this.upDateUser>更新数据</button>
                </div>
              );
            
          
    
          ReactDOM.render(<App />, document.getElementById("app"));
        </script>
      </body>
    </html>
    
    • 目前效果

      点击更新数据按钮之后的效果:

  • 使用JSX语法糖:解构

    还可用三元表达式:

    render() 
              const  isLogin  = this.state;
              let button;
              if (isLogin) 
                button = <Login />;
               else 
                button = <Logout />;
              
              return (
                <div>
                  <h1>Hello</h1>
                  isLogin ? <Login /> : <Logout />
                  <button onClick=this.upDateUser>更新数据</button>
                </div>
              );
            
    
  • 前面是用父组件来控制状态

    也可以用子组件去触发父组件的方法

    把方法传给子组件

      <body>
        <div id="app"></div>
        <script type="text/babel">
          function Login(props) 
            return <button onClick=props.upDate>Login</button>;
          
          function Logout(props) 
            return <button onClick=props.upDate>Logout</button>;
          
          class App extends React.Component 
            state = 
              isLogin: false,
            ;
            upDateUser = () => 
              this.setState(
                isLogin: !this.state.isLogin,
              );
            ;
            render() 
              const  isLogin  = this.state;
              let button;
              if (isLogin) 
                button = <Login />;
               else 
                button = <Logout />;
              
              return (
                <div>
                  <h1>Hello</h1>
                  isLogin ? (
                    <Login upDate=this.upDateUser />
                  ) : (
                    <Logout upDate=this.upDateUser />
                  )
                  <button onClick=this.upDateUser>更新数据</button>
                </div>
              );
            
          
    
          ReactDOM.render(<App />, document.getElementById("app"));
        </script>
      </body>
    

    现在点击更新数据就可以在login和logout之间互换

七.列表渲染

  • 先演示一个一维数组

    利用数组原生方法和JSX语法糖来循环、渲染

    class List extends React.Component 
            state = 
              list: [1, 2, 3, 4, 5],
            ;
            render() 
              const arr = this.state.list; //获取数组
              //循环遍历数组
              //可以用map
              //map()常用于遍历数据
              //map()的作用是映射,即原数组被映射为对应新数组
              //返回的新数组由原数组中的每个元素调用一个指定方法后的返回值组成
              //map()不会改变原始数组
              const listItem = [];
              arr.map((item) => 
                let li = <li>item</li>;
                listItem.push(li);
              );
              for (var i = 0; i < arr.length; i++) 
                let lii = <li>arr[i]</li>;
                //html中要用js变量需要用大括号来引用
                //然后lii最后整体是一个js变量
    
                listItem.push(lii);
              
    
              return (
                <div>
                  <ul>listItem</ul>
                </div>
              );
            
          
    
  • 上面用了map方法和for循环,效果一样

  • 复杂一些的数组

    <body>
        <div id="app"></div>
        <script type="text/babel">
          class List extends React.Component 
            state = 
              list: [
                 id: 1, text: "C" ,
                 id: 2, text: "C++" ,
                 id: 3, text: "Python" ,
                 id: 4, text: "Dart" ,
              ],
            ;
            render() 
              const arr = this.state.list; //获取数组
              const listItem = [];
              for (var i = 0; i < arr.length; i++) 
                //react 建议每个标签添加key用于缓存
                let lii = <li key=arr[i].id>arr[i].text</li>;
    
                listItem.push(lii);
              
    
              return (
                <div>
                  <ul>listItem</ul>
                </div>
              );
            
          
    
          ReactDOM.render(<List />, document.getElementById("app"));
        </script>
      </body>
    
    • 效果

八.表单应用

  • 做一个TodoList

  • 代码

     <body>
        <div id="app"></div>
        <script type="text/babel">
          class TodoList extends React.Component 
            state = 
              val: "",
              list: [],
            ;
            //获取文本框的值
            handleInput = (event) => 
              this.setState(
                val: event.target.value,
              );
              //存值
            ;
    
            handleAdd = () => 
              //ES6解构语法简写
              const  val, list  = this.state;
              //上面这句等效于下面这两句
              // const val = this.state.val;
              // const list = this.state.list;
              list.push(val);
              //在React中只要数据发生变化,就要用setState方法
              this.setState(
                list: list,
                //ES6中key和value一样的时候可以省略value
                //即这里可以就写一个list
              );
            ;
            //调用了setState就会执行render
            render() 
              const val = this.state.val;
              const arr = this.state.list;
              const listItem = [];
              arr.map((item, index) => 
                let li = <li key=index>item</li>;
                listItem.push(li);
              );
              return (
                <div>
                  <input type="text" value=val onChange=this.handleInput />
                  <button onClick=this.handleAdd>添加</button>
                  <ul>listItem</ul>
                </div>
              );
            
          
    
          ReactDOM.render(<TodoList />, document.getElementById("app"));
        </script>
      </body>
    
  • 效果

以上是关于React入门2的主要内容,如果未能解决你的问题,请参考以下文章

ZYNQ从入门到秃头09番外 DDS增强版实验(基于ALINX 7020 && AN108)

ZYNQ从入门到秃头10 DDS增强版实验ADDA测试(基于ALINX 7020 && AN108)

ZYNQ从入门到秃头10 DAC FIFO实验(AXI-stream FIFO IP核配置)

ZYNQ从入门到秃头[番外] Vivado VSCode现代化编辑工具配置

ZYNQ从入门到秃头08 FPGA片内异步FIFO读写测试实验

ZYNQ从入门到秃头08 FPGA片内异步FIFO读写测试实验