• React入门学习(一)



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

    React 的特点:

    1. 声明式设计
    2. 高效,采用虚拟DOM来实现dom渲染,减少DOM操作
    3. 灵活, 可以与其他库搭配使用。
    4. JSX,在js中编写html。
    5. 组件化、模块化,代码容易复用
    6. 单向数据流,没有实现数据的双向绑定。数据->视图->时间->数据

    create-react-app 创建项目:

    通过react脚手架,创建项目来开发部署。

    1. 安装脚手架Create React App yarn global add create-react-app
    2. 创建项目:create-react-app projName
    3. 目录文件解析
      在这里插入图片描述
    4. 启动npm run start或者yarn start

    React 元素渲染

    1. 定义一个元素
      注意:元素是一个组件的最小单位。一个元素或组件有且只有一个根节点。这一点和vue是一样的。
      使用JSX写法,可以创建JS元素对象。
    import App from './App';
    
    const root = ReactDOM.createRoot(document.getElementById('root'));
    // 定义一个元素,元素是一个组件的 最小单位。
    // 注意:一个元素或者组件有且只有一个根节点。这一点和VUE是一样的。
    let h1 = <h1>hello world</h1>
    // root.render(h1);
    //  JS普通对象
    root.render(<App />);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    案例1:

    function clock() {
      const root = ReactDOM.createRoot(document.getElementById('root'));
    
      let time = new Date().toLocaleTimeString()
      let ele = (<div>
                    <h1>NOW TIME IS : {time}</h1>
                  </div>)
      root.render(ele) 
    }
    setInterval(() => {
      clock()
    }, 1000);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    案例2:函数式组件

    // React 函数式组件
    function Clock(props){
      return(<div>
              <h1>NOW TIME IS : {props.date.toLocaleTimeString()}</h1>
              <h2>这是函数式组件开发</h2>
            </div>)
    }
    
    function run(){
      root.render(<Clock date={new Date()}/>)
    }
    
    setInterval(() => {
      run()
    }, 1000);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    JSX语法

    对html进行扩充。
    优点:执行更快,在编译为JS时进行优化(采用虚拟DOM)。类型更安全,在编译时发现错误。编写模板更简单快速。
    注意:JSX组件必须要有一个根节点。正常的普通html元素要小写,如果是大写,则默认为组件。

    JSX表达式

    1. 由html元素构成
    2. 中间可以使用{}来插入变量
    3. {}中间可以写表达式
    4. {}表达式中可以使用jsx对象
    5. 属性和html内容都是用{}插入

    案例:

    import React from 'react';
    import ReactDOM from 'react-dom/client';
    import './App.css'
    
    const root = ReactDOM.createRoot(document.getElementById('root'));
    
    let color = 'bgRed'
    // 三元运算
    // HTML的类名要些className。因为class是js的关键字
    let content2 = (
      <h1>1&gt;2嘛? {1>2?'是':<a className={color} href='#'></a>}</h1>
    )
    
    // 字符串拼接 与 模板引入
    let time = new Date().toLocaleDateString();
    let str = '日期:'
    let content = (<div>
      <h1>HUATHY HELLO</h1> 
      <h1>{str + time}</h1>
      {content2}
    </div>)
    
    root.render(content)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    React样式和注释

    JSX_style样式

    1. class、style中,不可以存在多个class属性
    2. style样式中,如果多个单词属性足额,第二个单词首字母大写。或者以引号包裹样式名。

    注释

    {/* */}:{/* 在元素中的注释必须以大括号包裹起来 */}
    //:js注释
    /** */:类注释
    /* */:多行注释

    案例:

    1. index.js
      import React from 'react';
      import ReactDOM from 'react-dom/client';
      import './App.css'
      
      const root = ReactDOM.createRoot(document.getElementById('root'));
      
      let egstyle = {
        // 样式
        'background-color': 'skyblue',
        borderBottom: '6px solid red'
      }
      // js注释
      let cls = ['greenBorder','high-100'].join(' ');
      let ele = (<div>
        {/* style里面必须是对象,不可以是字符串 */}
        <h1 className={cls} style={egstyle}>HELLO WORLD</h1>
      </div>)
      
      root.render(ele);
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
    2. App.css
      .greenBorder{
        border: 6px solid greenyellow;
      }
      
      .high-100{
        height: 100px;
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7

    React组件

    1. 函数式组件:静态页面
    2. 类组件(动态组件),一般会有交互和数据修改操作。
    3. 复合组件:组件中包含其他组件(包括类组件和函数式组件)。

    区别:类组件中操作事件更方便。函数组件中编写事件方法不太推荐。如果组件中有事件,建议使用类组件。静态组件可以使用函数式组件。

    示例:

    import React from 'react';
    import ReactDOM from 'react-dom/client';
    import './App.css'
    
    const root = ReactDOM.createRoot(document.getElementById('root'));
    
    // 函数式组件
    function Childcom(props){
      let title = '标题'
      // 条件判断
      let isBig = props.num > 0 ? '是':'否'
      return(<div>
        <h1>HELLO 函数式组件</h1>
        <h2>{title}</h2>
        {/* 大于小于符号可以使用{''}包裹,也可以使用实体符号 */}
        <h2> {props.num} {'>'} 0 ? {isBig}</h2>
      </div>)
    }
    
    // 类组件
    class Hello extends React.Component{
      render(){
        return(<div>
          <h1>HELLO 类组件定义</h1>
          {/* react组件可以包含组件 */}
          <Childcom num={this.props.num}/>
        </div>)
      }
    }
    
    // root.render()
    root.render(<Hello num='2'/>)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    react状态(React State)

    相当于vue中的data。但是和vue不同。

    案例一:当前时间

    import React from 'react';
    import ReactDOM from 'react-dom/client';
    import './App.css'
    
    const root = ReactDOM.createRoot(document.getElementById('root'));
    /**
     * 类注释
     */
    class Hello extends React.Component{
      // 构造函数
      constructor(props){
        // 调用父类方法,会一直传递到继承的类
        super(props)
        // 状态(数据) -- > view
        // 1. 构造函数初始化数据,将需要改变的数据初始化到state中
        this.state = {
          time: new Date().toLocaleTimeString()
        }  
        // 构造函数没有刷新
        console.log(this.state.time)
      }
    
      render(){
        console.log('这是渲染函数');
        // // 要想时间动起来,可以在这里更改
        // this.state.time = new Date().toLocaleTimeString()
        return(<div>
          <h1>当前时间:{this.state.time}</h1>
        </div>)
      }
    
      // 生命周期函数,组件渲染完成时
      componentDidMount(){
        setInterval(()=>{
          // 不推荐的改变值方式
          // this.state.time = new Date().toLocaleTimeString()
          /*
            2. 修改state数据。采用this.setState({})的方式会重新渲染内容
            不要直接this.state.dateName=XXX。这种方式不会重新渲染内容。
          */ 
          console.log(this.state.time)
          this.setState({
            time: new Date().toLocaleTimeString()
          })
          /* 这里打印的时间和调用this.setState前是一样的,并没有立即修改dom内容。
            原因:由于很多地方都会修改state,react会对虚拟DOM和DOM之间进行比较。
            当该函数所有设置状态都的修改完成之后,统一对比虚拟dom对象,然后统一修改,提升性能。
          */
          console.log(this.state.time)
        },1000)
      }
    }
    
    // // 这种写法不推荐,因为定时函数与渲染函数相耦合。解耦
    // setInterval(() => {
    //   // 虽然定时任务一直在跑,但是加载相同组件,react是不会重新初始化的。这也是时间没有更新的原因。
    //   root.render()
    // }, 1000);
    root.render(<Hello />)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    案例二:tab切换

    1. index.js
      import React from 'react';
      import ReactDOM from 'react-dom/client';
      import './App.css' 
      
      const root = ReactDOM.createRoot(document.getElementById('root'));
      
      class Tab extends React.Component{
        constructor(props){
          super(props)
           // 设置状态、数据
          this.state = {
            c1:'content-active',
            c2:'content'
          }
          this.clickEvent = this.clickEvent.bind(this)
        }
        clickEvent(e){
          console.log(e)
          console.log(e.target)
          let index = e.target.dataset.index
          console.log(index)
          // 这里必须在构造函数中对this进行绑定。否则这里的this是undefined
          console.log(this)
          this.setState({
            // 强等于
            c1: index === '1' ? 'content-active' : 'content',
            c2: index === '2' ? 'content-active' : 'content'
          })
        }
        render(){
          return(<div>
            <button data-index='1' onClick={this.clickEvent}>内容1</button>&nbsp;
            <button data-index='2' onClick={this.clickEvent}>内容2</button>
            <h1 className={this.state.c1}>内容1</h1>
            <h1 className={this.state.c2}>内容2</h1>
          </div>)
        }
      }
      
      root.render(<Tab />)
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
    2. App.css
      .content{
        display: none;
      }
      .content-active{
        display: block;
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6

    React 数据传递

    父传子

    props:父组件给传子组件数据,单向流动,不能子组件传给父组件。
    props的传值可以是任意的类型。
    props可以设置默认值。语法:ComponentName.defaultProps = { param:value }
    可以传递函数,从而修改父组件的state,从而实现子传父。

    案例:

    1. index.js
      import React from 'react';
      import ReactDOM from 'react-dom/client';
      import './index.css'
      
      // 在父元素中使用state去控制子元素props的从而实现父传子。
      const root = ReactDOM.createRoot(document.getElementById('root'));
      
      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 strCls = this.props.isActive ? ' active' : '';
          return(<div className={'content' + strCls}>
            <h1>这是子组件</h1>
          </div>)
        }
      }
      
      root.render(<ParentCom />);
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
    2. index.css
      .content{
        display: none;
      }
      .content.active{
        display: block;
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6

    子传父

    调用父类传入的方法,给父类的方法传值,来实现子传父。

    案例

    import React from 'react';
    import ReactDOM from 'react-dom/client';
    import './index.css'
    
    // 子传父
    const root = ReactDOM.createRoot(document.getElementById('root'));
    
    
    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 : 'HELLO WORLD'
        }
      }
      render(){
        return(<div>
          <h1>这是子组件</h1>
          <button onClick={this.sendMsg}>传入数据</button>
          {/* 这里可以直接调用父元素的方法。但是要注意使用箭头函数 */}
          <button onClick={()=>{this.props.setChildData('')}}>重置</button>
        </div>)
      }
      sendMsg = ()=>{
        // 使用箭头函数,可以不用绑定。
        this.props.setChildData(this.state.msg)
      }
    }
    
    root.render(<ParentCom/>)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    react 事件

    1. 特点:
      1. 驼峰命名,首字母小写,后续单词首字母大写。
      2. {}大括号括起来,传入一个函数。
    2. 事件对象:React返回的事件ui想是代理的原生的事件对象。如果需要查看事件对象的具体值,必须直接输出事件对象的属性。
    3. 事件默认行为:原生,组织默认行为的时候,可以直接return false。但是在react中阻止事件默认行为必须调用e.preventDefault()函数。
    4. react事件传参:需要使用箭头函数。
      <button onClick={(e)=>{this.envet2(123,e)}}>函数传参</button>
      
      • 1

    案例:

    import React from 'react';
    import ReactDOM from 'react-dom/client';
    import './index.css'
    
    // 子传父
    const root = ReactDOM.createRoot(document.getElementById('root'));
    
    class ParentCom extends React.Component{
      constructor(props){
        super(props)
      }
      render(){
        return(<div>
          <form action='http://www.baidu.com'>
            <a className='child'>HELLO WROLD</a>
            <button onClick={this.parentEvent}>submit</button>
          </form>
          <button onClick={(e)=>{this.envet2(123,e)}}>函数传参</button>
        </div>)
      }
      parentEvent=(e)=>{
        console.log(e)
        // 阻止事件默认行为。
        e.preventDefault()
      }
      envet2(param,e){
        console.log(param)
      }
    }
    
    root.render(<ParentCom />)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    React 条件渲染

    React中的条件渲染即和JS中,条件运算,eg:if...eles...(三元运算)boolean?res1:res2

    1. 通过条件运算返回要渲染的JSX对象
    2. 通过条件运算得出jsx对象,再将jsx对象渲染到模板中
    3. 通过修改样式active的方式。(这个案例在上面的例子中已经存在)

    案例:

    import React from 'react';
    import ReactDOM from 'react-dom/client';
    import './index.css'
    
    // 子传父
    const root = ReactDOM.createRoot(document.getElementById('root'));
    
    function Welcom(props){
      return (<div>
        <h1>欢迎登录</h1>
      </div>)
    }
    function Login(props){
      return (<div>
        <h1>PLESE LOGIN</h1>
      </div>)
    }
    
    class Demo extends React.Component{
      constructor(props){
        super(props)
          this.state = {
            isLogin: false
        }
      }
      render(){
        return this.state.isLogin ? <Welcom/> : <Login />
      }
    }
    
    class Demo2 extends React.Component{
      constructor(props){
        super(props)
          this.state = {
            isLogin: false
        }
      }
      render(){
        let element = this.state.isLogin ? <Welcom/> : <Login />
        return(<div>
          <h1>----- HEAD -----</h1>
          {element}
          {this.state.isLogin ? <Welcom/> : <Login />}
          <h1>-----  END -----</h1>
        </div>)
      }
    }
    
    // root.render()
    root.render(<Demo2 />)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    React 列表渲染

    将列表数据接成数组的JSX放置到模板中。
    使用数组的map方法,对每一项数据按照JSX的形式进行加工,最终得到一个每一项都是JSX对象的数组,再将数组渲染到模板中,并将key值放置到数组中。

    案例

    import React from 'react';
    import ReactDOM from 'react-dom/client';
    import './index.css'
    
    // 子传父
    const root = ReactDOM.createRoot(document.getElementById('root'));
    
    function List1(props){
      let item = props.item
      console.log(item)
      return (<li>
        <strong>{item.name}</strong>-<span>{item.age}</span>
      </li>)
    }
    
    class List2 extends React.Component{
      constructor(props){
        super(props)
      }
      render(){
        let item = this.props.item
        return(<li onClick={(e)=>{this.clickEvent(this.props.index,item.name,e)}}>
            <strong><a>{item.name}</a></strong>
            -<span>{item.age}</span>
        </li>)
      }
      clickEvent=(index,name,event)=>{
        alert(index+"-"+name)
      }
    }
    
    class Demo extends React.Component{
      constructor(props){
        super(props)
        this.state = {
          list:[
            {
              name: 'Huathy',
              age: '22'
            },
            {
              name: '小花',
              age: '18'
            },
            {
              name: '嘻嘻',
              age: '20'
            }
          ]
        }
      }
      render(){
        let arr = this.state.list.map((item,index) => {
          return(
            // 
  • // {index}:{item.name}-{item.age} //
  • <List1 key={index} item={item} index={index}/> ) }) return(<div> <h1>利用组件1的方式</h1> <ul> <li> <strong>name</strong>-<span>age</span> </li> {arr} </ul> <h1>利用组件2的方式</h1> <ul> { this.state.list.map((item,index)=><List2 key={index} item={item} index={index}/>) } </ul> <h1>不利用组件的方式</h1> <ul> { this.state.list.map((item,index)=>(<li onClick={(e)=>{this.clickFn(index,item.name,e)}} key={index}> <strong>{item.name}</strong>-<span>{item.age}</span> </li>)) } </ul> </div>) } clickFn = (index,name,event) => { alert(index+"-clickFN-"+name) } } root.render(<Demo/>)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91

    For循环方法

    1. forEach:没有返回值
    arr.forEach( ( item,index ) => { } )
    
    • 1
    1. map:对数组每一项进行加工后返回一个新数组
    let arr = [1,2,3,4,5,6]
    let res = arr.map((item,index)=>{
    	let str = item+index
    	return str
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    1. filter:过滤,将想要的内容进行筛选,返回筛选后的内容
    let arr = [1,2,3,4,5,6]
    let res = arr.filter((item,index)=>{
    	return item%2 == 0	//返回偶数,过滤奇数
    })
    
    • 1
    • 2
    • 3
    • 4
    1. reduce:对数组进行整合
    let arr = [1,2,3,4,5,6]
    let res = arr.reduce((pre,next)=>{
    	return pre + next
    })
    
    • 1
    • 2
    • 3
    • 4
    1. for...in...主要用来遍历对象,不适合遍历数组
    let obj = {name:'Huathy',age:18}
    for (key in obj){	//key是无序随机的
    	console.log(key+'-'+obj[key])
    }
    
    • 1
    • 2
    • 3
    • 4
    1. for...of...可以用来遍历数组、类数组的对象、字符串、set、map
    let arr = [1,2,3,4,5,6]
    // 与for...in...的区别是of的item是元素值,而in的key是键名
    for(let item of arr){
    	console.log(item)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    说明:个人学习笔记,对视频内容有所调整删减。以使得文章更简洁。
    致谢:B站UP主[老陈打码] BV1T7411W72T
  • 相关阅读:
    C语言之网络编程(一)域名解析
    response响应,常用方法,分发器重定向,错误提示
    golang学习笔记——使用结构
    SpringBoot日志框架选型——Log4j2的配置与使用
    JavaScript作用域链与预解析
    学会preload和prefetch
    优思学院|新版ISO9001:2015质量体系的优势(一)高阶结构
    处理机调度
    DRF视图类、认证组件、权限、限流、过滤、排序、分页、异常处理、自动生成接口文档、Xadmin
    【强化学习】day1 强化学习基础、马尔可夫决策过程、表格型方法
  • 原文地址:https://blog.csdn.net/qq_40366738/article/details/110209674