react入门

1.安装

1.安装node.js

下载node.js 长期维护版 LTS https://nodejs.org/zh-cn/download/

安装后

使用指令 node -v

显示 v18.14.2

使用指令 npm -v

显示 9.5.0

2.安装react

全局安装 npm install -g create-react-app

创建一个项目 creat-react-app helloreact1

临时安装 npx create-react-app helloreact2

npx临时安装最新版 非全局

3.运行

访问项目目录 cd helloreact1

运行 npm start

4.安装依赖

如果没有node_modules 需要使用命令 npm i

作用是读取package.json的配置文件版本号,从package-lock.json找到具体的url下载文件

5.切换npm仓库链接地址 淘宝

命令 npm i -g nrm

如果报错 Error: EACCES: permission denied, mkdir ‘/usr/local/lib/node_modules/nrm’

需要获取权限 sudo -i

输入管理密码

重新安装 npm i -g nrm

显示版本号 nrm -V

显示仓库链接地址 nrm ls

显示结果

npm ---------- https://registry.npmjs.org/
yarn --------- https://registry.yarnpkg.com/
tencent ------ https://mirrors.cloud.tencent.com/npm/
cnpm --------- https://r.cnpmjs.org/
taobao ------- https://registry.npmmirror.com/
npmMirror ---- https://skimdb.npmjs.com/registry/

选择淘宝路径 nrm use taobao

结果 Registry has been set to: https://registry.npmmirror.com/

6.如果npmstart失败

把node_modules 和 package-lock.json 删除

使用 npm i 安装依赖文件( i 就是 install的缩写 )

如果还是无法解决 使用npm cache clean --force , 再执行npm install

2.编码

1.删除src目录下所有文件

命令

cd src
rm -rf *

2.新建index.js

// console.log(“hello”);

importReactfrom’react’

importReactDomfrom’react-dom’

代码1.输出11111

ReactDom.render("11111",document.getElementById("root"))

代码2.输出一个div 11111

ReactDom.render(<div>11111</div>,document.getElementById("root"))

代码3.输出

  • 111
  • 111
  • 111
ReactDom.render(<div>
  <ul>
    <li>111</li>
    <li>111</li>
    <li>111</li>
  </ul>
</div>,document.getElementById("root"))

jsx=js+xml

代码4 输出111111

ReactDom.render(React.createElement("div",{
    id:"aaa",
    className:"bbb"
  },111111),document.getElementById("root")
);

3.新建class组件

在src目录下新建文件夹 01-base,新建文件01-class组件.js

class Test{
  constructor(){
    this.a=1;
  }

  testa(){
    console.log("testa");
  }


}

class ChildTest extends Test{
  testb(){
    console.log("testb");
  }
}

// var obj = new Test();
var obj = new ChildTest();
obj.testa();
obj.testb();
console.log(obj.a);

然后在index.js中引入01-class组件.js

import "./01-base/01-class组件"

4.新建函数式组件

在src/01-base文件夹下,新建文件02-函数式组件.js

function App(){
  return (
    <div>
      hello functional component
      <div>111</div>
      <div>222</div>
    </div>
  )
}

export default App

然后在index.js中引入02-函数式组件01-class组件.js

import App from "./01-base/02-函数式组件"

刷新页面 显示

hello functional component

111

222

5.新建组件的嵌套

在src/01-base文件夹下,新建文件03-组件的嵌套.js

在vscode中安装react插件ES7+ React/Redux/React-Native snippets

安装完成后

输入rcc会车 会自动生成react 代码


import React, { Component } from 'react'

export default class App extends Component {
  render() {
    return (
      <div>03-组件的嵌套</div>
    )
  }
}

新建组件 navbar,swiper,tabbar 和 child 组织嵌套关系

/**
 * rcc 回车
 */
import React, { Component } from 'react'

class Child extends Component{
  render(){
    return <div>child</div>
  }
}

class Navbar extends Component{
  render(){
    return <div>navbar
      <Child></Child>
    </div>
  }
}

function Swiper (){
  return <div>swiper</div>
}

// const Tabbar = () => {
//   return <div>tabbar</div>
// }

const Tabbar = () => <div>tabbar</div>

export default class App extends Component {
  render() {
    return (
      <div>
        <Navbar></Navbar>
        <Swiper></Swiper>
        <Tabbar></Tabbar>
      </div>
    )
  }
}

6.新建04-组件的样式

在src/01-base文件夹下,新建文件04-组件的样式.js

1.行内样式

import React, { Component } from 'react'

export default class app extends Component {
  render() {
    var myname = "tom"
    var obj = {
      backgroundColor:"yellow",
      fontSize:"30px"
    }
    return (
      <div>
        {10+20}-{myname}
        {10>20?'aaa':'bbb'}
        <div style={obj}>111111</div>
        <div style={{backgroundColor:"red"}}>222222</div>
      </div>
    )
  }
}

2.外部样式表

在01-base目录下新建css文件夹,在css文件夹下新建01-index.css文件

.active{background-color:green}

在04-组件的样式.js中引入css文件

import "./css/01-index.css"

在代码中使用css文件中的 active 的样式

 <div className='active'>333333</div>

插入代码 label的for 改成 htmlFor 指向 input的id属性

        <label htmlFor="username">用户名:</label>
        <input type="text" id="username"></input>

7.事件绑定-1

在01-base目录下新建05-事件绑定-1.js

import React, { Component } from 'react'

export default class app extends Component {
  render() {
    return (
      <div>
        <input />
        <button onClick={()=>{
          console.log("click1","如果处理逻辑过多,不推荐这种写法");
        }}>add1</button>
        <button onClick={this.handleClick2}>add2</button>
        <button onClick={this.handleClick3}>add3</button>
        <button onClick={()=>{
          this.handleClick4() //比较推荐
        }}>add4</button>
      </div>
    )
  }

  handleClick2(){
    console.log("click2");
  }

  handleClick3 = () => {
    console.log("click3");
  }

  handleClick4 = () => {
    console.log("click4");
  }
}

index.js中

import App from "./01-base/05-事件绑定-1"

onClick 事件绑定 4种些法,效果 点击click 按钮 console.log 打印click字符串。

8.事件绑定-2

在01-base目录下新建06-事件绑定-2.js

import React, { Component } from 'react'

export default class app extends Component {
  render() {
    return (
      <div>
        <input />
        <button onClick={()=>{
          console.log("click1","如果处理逻辑过多,不推荐这种写法");
        }}>add1</button>
        <button onClick={this.handleClick2}>add2</button>
        <button onClick={this.handleClick3}>add3</button>
        <button onClick={()=>{
          this.handleClick4() //比较推荐
        }}>add4</button>
      </div>
    )
  }

  handleClick2(){
    console.log("click2");
  }

  handleClick3 = () => {
    console.log("click3");
  }

  handleClick4 = () => {
    console.log("click4");
  }
}

index.js中

import App from "./01-base/06-事件绑定-2"

推荐些法

<button onClick={()=>{this.handleClick4()}}></button>

9.ref绑定

在01-base目录下新建07-ref.js

import React, { Component } from 'react'
//ref 方式1
// export default class app extends Component {
//   a = 100;
//   render() {
//     return (
//       <div>
//         <input ref="mytext" />
//         <button onClick={()=>{
//           console.log("click1",this.refs.mytext.value)
//         }}>add1</button>
//       </div>
//     )
//   }
// }

//ref 方式2
export default class app extends Component {
  a = 100;
  myref = React.createRef();
  render() {
    return (
      <div>
        <input ref={this.myref} />
        <button onClick={()=>{
          console.log("click1",this.myref.current.value)
        }}>add1</button>
        <button onClick={this.handleClick2.bind(this)}>add2</button>
        <button onClick={this.handleClick3}>add3</button>
      </div>
    )
  }

  handleClick2(){
    console.log("click2",this.myref.current.value);
  }

  handleClick3=()=>{
    console.log("click2",this.myref.current.value);
  }
}

index.js中

import App from "./01-base/07-ref"

10.状态state

在01-base目录下新建08-状态state.js

import React, { Component } from 'react'

export default class app extends Component {
  //state 写法1
  // state = {
  //   isCollect:true
  // }

  //state 写法2
  constructor(){
    super()
    this.state = {
      isCollect:true
    }
  }

  render() {
    return (
      <div>
        <h1>欢迎来到react开发</h1>
        <button onClick={()=>{
            this.setState({
              isCollect:!this.state.isCollect
            })
            if(this.state.isCollect){
              console.log("收藏逻辑");
            }else{
              console.log("取消收藏逻辑");
            }
          }
        }>{this.state.isCollect?"收藏":"取消收藏"}
        </button>
      </div>
    )
  }
}

      <div>
        <h1>欢迎来到react开发</h1>
        <button onClick={()=>{
            this.setState({
              isCollect:!this.state.isCollect
            })
            if(this.state.isCollect){
              console.log("收藏逻辑");
            }else{
              console.log("取消收藏逻辑");
            }
          }
        }>{this.state.isCollect?"收藏":"取消收藏"}
        </button>
      </div>
    )
  }
}

index.js中

import App from "./01-base/08-状态state"

11.循环渲染

在01-base目录下新建09-循环渲染.js

import React, { Component } from 'react'

export default class App extends Component {
  state = {
    // list: ["1111","2222","3333"]
    list: [{
      id: 1,
      text: "1111"
    },
    {
      id: 2,
      text: "2222"
    },{
      id: 3,
      text: "3333"
    }]
  }
  render() {
    //提取变量newlist
    // var newlist = this.state.list.map(item=><li>{item}</li>)
    return (
      <div>
        {
          // newlist
          this.state.list.map((item,index)=><li key={index}>{item.text}--{index}</li>)
        }
      </div>
    )
  }
}
/**
 * 为了列表的复用和重排,设置key值,提高性能
 * 理想key,item.id
 * 不涉及到列表的增加删除,重排,设置成索引没有问题。
 */


/**
 * 原生js - map
 */

var list = ["aa","bb","cc"]
var newlist = list.map(item=>`<li>${item}</li>`);
console.log(newlist.join(""));

index.js中

import App from "./01-base/09-循环渲染"

添加删除按钮

import React, { Component } from 'react'
import "./css/01-index.css"
export default class app extends Component {
  a = 100;
  myref = React.createRef();
  state = {
    list:[
      {
        id: 1,
        text: "aa"
      },
      {
        id: 2,
        text: "bb"
      },
      {
        id: 3,
        text: "cc"
      }
    ]
  }
  render() {
    return (
      <div>
        <input ref={this.myref} />
        <button onClick={this.handleClick2.bind(this)}>add2</button>
        <ul>
          {
            this.state.list.map((item,index)=>
            <li key={item.id}>
              {item.text}
              {/* <button onClick={this.handleDelClick.bind(this,index)}>del</button> */}
              <button onClick={()=>this.handleDelClick(index)}>del</button>
            </li>)
          }
        </ul>
        {/* {this.state.list.length===0?<div>暂无代办事项</div>:null} */}
        {/* {this.state.list.length===0 && <div>暂无代办事项</div>} */}
        <div className={this.state.list.length===0?'':'hidden'}>暂无代办事项</div>

      </div>
    )
  }
  //add新增
  handleClick2(){
    console.log("click2",this.myref.current.value);
    let newlist=[...this.state.list];
    newlist.push({
      id: Math.random()*10000,
      text: this.myref.current.value
    });
    this.setState({
      list:newlist
    })
  }

  //删除 concat() splice()
  handleDelClick(index){
    console.log("delete " + index);
    let newlist=this.state.list.concat();
    newlist.splice(index,1);
    this.setState({
      list: newlist
    });
  }

}

12.todolist

在01-base目录下新建10-todolist.js

import React, { Component } from 'react'
import "./css/01-index.css"
export default class app extends Component {
  a = 100;
  myref = React.createRef();
  state = {
    list:[
      {
        id: 1,
        text: "aa"
      },
      {
        id: 2,
        text: "bb"
      },
      {
        id: 3,
        text: "cc"
      }
    ]
  }
  render() {
    return (
      <div>
        <input ref={this.myref} />
        <button onClick={this.handleClick2.bind(this)}>add2</button>
        <ul>
          {
            this.state.list.map((item,index)=>
            <li key={item.id}>
              {/* {item.text} */}
              {/* 富文本展示 */}
              <span dangerouslySetInnerHTML={
                {
                  __html: item.text
                }
              } ></span>
              {/* <button onClick={this.handleDelClick.bind(this,index)}>del</button> */}
              <button onClick={()=>this.handleDelClick(index)}>del</button>
            </li>)
          }
        </ul>
        {/* {this.state.list.length===0?<div>暂无代办事项</div>:null} */}
        {/* {this.state.list.length===0 && <div>暂无代办事项</div>} */}
        <div className={this.state.list.length===0?'':'hidden'}>暂无代办事项</div>

      </div>
    )
  }
  //add新增
  handleClick2(){
    console.log("click2",this.myref.current.value);
    let newlist=[...this.state.list];
    newlist.push({
      id: Math.random()*10000,
      text: this.myref.current.value
    });
    this.setState({
      list:newlist
    })
    // 清空输入栏
    this.myref.current.value="";
  }

  //删除 concat() splice()
  handleDelClick(index){
    console.log("delete " + index);
    let newlist=this.state.list.concat();
    newlist.splice(index,1);
    this.setState({
      list: newlist
    });
  }

}

index.js中

import App from "./01-base/10-todolist"

13.dangerouslySetInnerHTML

在01-base目录下新建11-dangerouslySetInnerHTML.js

import React, { Component } from 'react'

export default class App extends Component {
  state={
    myhtml:`<b>1</b><i>1</i>`
  }
  render() {
    return (
      <div>
        {
          <div dangerouslySetInnerHTML = {
            {
              __html: this.state.myhtml
            }
          }></div>
        }
      </div>
    )
  }
}

index.js中

import App from "./01-base/11-dangerouslySetInnerHTML"

14.axios 请求接口

打开/src/maizuocomponent/Cinema.js

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

export default class Cinema extends Component {
  constructor(){
    super()
    //简写
    //axios.get("url").then(res=>{console.log(res)}).catch(err=>{console.log(err)});
    //原始模式
    axios({
      url: "https://m.maizuo.com/gateway?cityId=310100&ticketFlag=1&k=4403380",
      method: "get",
      header: {
        'X-Client-Info': '{"a":"3000","ch":"1002","v":"5.2.1","e":"1677936159991149602897921","bc":"310100"}',
        'X-Host': 'mall.film-ticket.cinema.list'
      }
    }).then(res=>{
      console.log(res.data)
    }).catch(err=>{
      console.log(err);
    })

  }
  render() {
    return (
      <div>Cinema</div>
    )
  }
}

添加fileter

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

export default class Cinema extends Component {
  state = {
    cinemaList:[],
    bakCinemaList:[]
  }

  constructor(){
    super()

    //简写
    //axios.get("url").then(res=>{console.log(res)}).catch(err=>{console.log(err)});
    //原始模式
    axios({
      url: "http://reacttp5.com/react/Index/list",
      method: "get"
      // header: {
      //   'X-Client-Info': '{"a":"3000","ch":"1002","v":"5.2.1","e":"1677936159991149602897921","bc":"310100"}',
      //   'X-Host': 'mall.film-ticket.cinema.list'
      // }
    }).then(res=>{
      console.log(res.data.data.cinemas)
      this.setState({cinemaList:res.data.data.cinemas,bakCinemaList:res.data.data.cinemas})
    }).catch(err=>{
      console.log(err);
    })

  }
  render() {
    return (
      <div>
        <input onInput={this.handleInput}/>
        {
          this.state.cinemaList.map((item)=>
            <dl key={item.cinemaId}>
              <dt>{item.name}</dt>
              <dd>{item.address}</dd>
            </dl>
          )
        }
      </div>
    )
  }

  handleInput=(event)=>{
    console.log("input",event.target.value);
    var newlist = this.state.bakCinemaList.filter(item=>item.name.toUpperCase().includes(event.target.value.toUpperCase())||
    item.address.toUpperCase().includes(event.target.value.toUpperCase()));
    console.log(newlist);
    this.setState({
      cinemaList:newlist
    });
  }
}

/**
 * filter
 */

var arr = ["aaa","bbb","ccc"]
// var newarr = arr.filter(itme=>true);
// var newarr = arr.filter(itme=>false);
var newarr = arr.filter(item=>item.includes("a"));

console.log(newarr);

15.setState同步异步

在01-base目录下新建13-setState同步异步.js

import React, { Component } from 'react'

export default class App extends Component {
  state = {
    count : 1
  }
  
  render() {
    return (
      <div>
        {this.state.count}
        <button onClick={this.handleAdd1}>add1</button>
        <button onClick={this.handleAdd2}>add2</button>
        <button onClick={this.handleAdd3}>add3</button>
      </div>
    )
  }

  handleAdd1=()=>{
    this.setState({count:this.state.count+1});
    console.log(this.state.count);
    this.setState({count:this.state.count+1});
    console.log(this.state.count);
    this.setState({count:this.state.count+1});
    console.log(this.state.count);
  }

  handleAdd2=()=>{
    setTimeout(()=>{
        this.setState({count:this.state.count+1});
        console.log(this.state.count);
        this.setState({count:this.state.count+1});
        console.log(this.state.count);
        this.setState({count:this.state.count+1});
        console.log(this.state.count);
    },0)
  }

  handleAdd3=()=>{
    this.setState({
      count:this.state.count+1
    },()=>{
      console.log(this.state.count);
    });

    this.setState({
      count:this.state.count+1
    },()=>{
      console.log(this.state.count);
    });

    this.setState({
      count:this.state.count+1
    },()=>{
      console.log(this.state.count);
      //状态 和 DOM更新完了
    });
  }
}

/**
 * setState 处在同步逻辑中,异步更新状态,更新真实DOM。
 * setState 处在异步逻辑中,同步更新状态,同步更新真实DOM。
 * setState 接收第二个参数,第二个参数是回调函数,状态和DOM更新完后就被触发。
 *
 */


index.js中

import App from "./01-base/13-setState同步异步"

16.betterScroll 滚动条插件

使用鼠标右键 左边 文件夹 helloreact 在集成终端中打开

yum i better-scroll

在01-base目录下新建14.betterScroll.js

import React, { Component } from 'react'
import BetterScroll from 'better-scroll'

export default class App extends Component {
  state = {
    list : []
  }
  render() {
    return (
      <div>
        <button onClick={()=>this.getData()}>click</button>
        <div className="wrapper" style={{height:'200px',background:'green',overflow:'hidden'}}>
          <ul className="content">
            {
              this.state.list.map((item,index)=><li key={index}>{item}</li>)
            }
          </ul>
        </div>
      </div>
    )
  }

  getData(){
    var list = [1,2,3,4,5,6,7,8,9,0,11,12,13,14,15]
    //方案一 同步
    // this.setState({
    //   list: list
    // },()=>{
    //   console.log(this.state.list);
    //   console.log(document.querySelectorAll('li'));
    //   new BetterScroll(".wrapper")
    // })

    //方案二 异步 
    setTimeout(() => {
      this.setState({
        list: list
      },()=>{
        console.log(this.state.list);
        console.log(document.querySelectorAll('li'));
        new BetterScroll(".wrapper")
      })
    }, 0);
  }
}

在01-base目录下新建15.betterScroll-cinema14.betterScroll.js

import React, { Component } from 'react'
import axios from 'axios'
import BetterScroll from 'better-scroll'
export default class Cinema extends Component {
  state = {
    cinemaList:[],
    bakCinemaList:[]
  }

  constructor(){
    super()

    //简写
    //axios.get("url").then(res=>{console.log(res)}).catch(err=>{console.log(err)});
    //原始模式
    axios({
      url: "http://reacttp5.com/react/Index/list",
      method: "get"
      // header: {
      //   'X-Client-Info': '{"a":"3000","ch":"1002","v":"5.2.1","e":"1677936159991149602897921","bc":"310100"}',
      //   'X-Host': 'mall.film-ticket.cinema.list'
      // }
    }).then(res=>{
      console.log(res.data.data.cinemas)
      this.setState({cinemaList:res.data.data.cinemas,bakCinemaList:res.data.data.cinemas})
      new BetterScroll(".wrapper");
    }).catch(err=>{
      console.log(err);
    })

  }
  render() {
    return (
      <div>
        <input onInput={this.handleInput}/>
        <div className='wrapper' style={{height:'200px',background:'green',overflow:'hidden'}}>
        <div className='content'>
          {
            this.state.cinemaList.map((item)=>
              <dl key={item.cinemaId}>
                <dt>{item.name}</dt>
                <dd>{item.address}</dd>
              </dl>
            )
          }
        </div>


        </div>

      </div>
    )
  }

  handleInput=(event)=>{
    console.log("input",event.target.value);
    var newlist = this.state.bakCinemaList.filter(item=>item.name.toUpperCase().includes(event.target.value.toUpperCase())||
    item.address.toUpperCase().includes(event.target.value.toUpperCase()));
    console.log(newlist);
    this.setState({
      cinemaList:newlist
    });
  }
}

/**
 * filter
 */

var arr = ["aaa","bbb","ccc"]
// var newarr = arr.filter(itme=>true);
// var newarr = arr.filter(itme=>false);
var newarr = arr.filter(item=>item.includes("a"));

console.log(newarr);

index.js中

import App from "./01-base/15.betterScroll-cinema"

17.props 属性

在01-base目录下新建16.props.js

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

export default class App extends Component {
  render() {
    //上面父组件传来的一个对象
    var obj = {
      title: "测试",
      leftShow: false
    }

    return (
      <div>
        <div>
          <h2>首页</h2>
          <Navbar title="首页" leftShow={false}></Navbar>
        </div> 
        <div>
          <h2>列表</h2>
          <Navbar title="列表"></Navbar>
        </div>
        <div>
          <h2>购物车</h2>
          <Navbar title="购物车"></Navbar>
        </div>
   
        <Navbar title= {obj.title} leftShow={obj.leftShow}></Navbar>
        <Navbar {...obj}></Navbar>

      </div>
    )
  }
}

新建在01-base目录下新建Navbar文件夹,在Navbar文件夹下新建index.js

import React, { Component } from 'react'
import PropTypes from 'prop-types'

export default class Navbar extends Component {
  state={
    //只能内部自己使用
  }
  //属性类型 方式2 
  static propTypes = {
    title: PropTypes.string,
    leftShow: PropTypes.bool
  }
  //属性默认值 方式2 
  static defaultProps={
    leftShow: true
  }

  render() {
    console.log(this.props) 
    let {title,leftShow} = this.props
    return (
      <div>
        {leftShow && <button>返回</button>}
        Navbar - {title} 
        <button>首页</button>
      </div>
    )
  }
}
//属性类型 方式1 
// Navbar.propTypes = {
//   title: PropTypes.string,
//   leftShow: PropTypes.bool
// }
//属性默认值 方式1
// Navbar.defaultProps={
//   leftShow: true
// }

class Test{
  a = 1
  static a = 100
}

//Test.a = 100
var obj = new Test();
console.log(Test.a,obj.a);

index.js中

import App from "./01-base/15.betterScroll-cinema"

props函数式组件

在01-base目录下新建17.props函数式组件.js

import React, { Component } from 'react'
import Navbar from './Navbar'
import SideBar from './Sidebar'

export default class App extends Component {
  render() {
    return (
      <div>
        {/* 类组件 */}
        <Navbar title = "导航"></Navbar>
        {/* 函数式组件 */}
        <SideBar bg = "yellow" position = "left"></SideBar>
      </div>
    )
  }
}

新建在01-base目录下新建Sidebar文件夹,在Sidebar文件夹下新建index.js

import React from 'react'

export default function index(props) {
  let {bg,position} = props
  console.log(position);

  var obj1 = {
    left : 0
  }
  
  var obj2 = {
    right : 0
  }

  var obj ={
    background: bg,
    width: "200px",
    position: "fixed"
  }

  var styleobj = position==="left"?{...obj,...obj1}:{...obj,...obj2}

  return (
    <div style={styleobj}>
      <ul >
        <li>111</li>
        <li>111</li>
        <li>111</li>
        <li>111</li>
        <li>111</li>
        <li>111</li>
      </ul>
    </div>
  )
}

index.js中

import App from "./01-base/15.betterScroll-cinema"

18.状态vs属性

在01-base目录下新建18-状态vs属性.js

import React, { Component } from 'react'

class Child extends Component{
  render(){
    return <div>
      child - {this.props.text}
      <button onClick={()=>{
        this.props.text = "333333"
      }}>click-子</button>
    </div>
  }
}

export default class App extends Component {
  state = {
    text : "111111"
  }
  render() {
    return (
      <div>
        <button onClick={()=>{
          this.setState({
            text: "222222"
          })
        }}>click-父</button>
        <Child text={this.state.text}></Child>
      </div>
    )
  }
}

index.js中

import App from "./01-base/18-状态vs属性"

19.非受控组件

在01-base目录下新建19-非受控.js

import React, { Component } from 'react'

export default class App extends Component {
  myusername = React.createRef()
  render() {
    return (
      <div>
        <h1>登录页</h1>
        {/* <input type="text" ref={this.myusername} value="tom"  ></input> */}
        <input type="text" ref={this.myusername} defaultValue="tom" ></input>
        <button onClick={()=>console.log(this.myusername.current.value)}>登录</button>
        <button onClick={()=>{this.myusername.current.value=""}}>重置</button>
      </div>
    )
  }
}

index.js中

import App from "./01-base/19-非受控"

20.受控组件

在01-base目录下新建20-受控.js





import React, { Component } from 'react'

export default class App extends Component {
  state = {
    username: "tom"
  }
  render() {
    return (
      <div>
        <h1>登录页</h1>
        <input type="text" ref={this.myusername} value={this.state.username}
         onChange={(evt)=>{
          console.log(evt.target.value);
          this.setState({
            username:evt.target.value
          })
         }}></input>
        <button onClick={()=>{
          console.log(this.state.username)
        }}>登录</button>
        <button onClick={()=>{
          this.setState({
            username: ""
          });
        }}>重置</button>
      </div>
    )
  }
}

index.js中

import App from "./01-base/20-受控"

21.受控Cinema组件

在01-base目录下新建21-受控Cinema.js

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

export default class Cinema extends Component {
  state = {
    cinemaList:[],
    mytext:""
    // bakCinemaList:[]
  }

  constructor(){
    super()

    //简写
    //axios.get("url").then(res=>{console.log(res)}).catch(err=>{console.log(err)});
    //原始模式
    axios({
      url: "http://reacttp5.com/react/Index/list",
      method: "get"
      // header: {
      //   'X-Client-Info': '{"a":"3000","ch":"1002","v":"5.2.1","e":"1677936159991149602897921","bc":"310100"}',
      //   'X-Host': 'mall.film-ticket.cinema.list'
      // }
    }).then(res=>{
      console.log(res.data.data.cinemas)
      this.setState({
        cinemaList:res.data.data.cinemas,
        // bakCinemaList:res.data.data.cinemas
      })
    }).catch(err=>{
      console.log(err);
    })

  }
  render() {
    return (
      <div>
        <input value={this.state.mytext} onChange={(evt)=>{
          this.setState({
            mytext:evt.target.value
          })
        }}/>
        {
          this.getCinemaList().map((item)=>
            <dl key={item.cinemaId}>
              <dt>{item.name}</dt>
              <dd>{item.address}</dd>
            </dl>
          )
        }
      </div>
    )
  }

  getCinemaList(){
    return this.state.cinemaList.filter(item=>item.name.toUpperCase().includes(this.state.mytext.toUpperCase())||
      item.address.toUpperCase().includes(this.state.mytext.toUpperCase()));
  }
  // handleInput=(event)=>{
  //   console.log("input",event.target.value);
  //   var newlist = this.state.bakCinemaList.filter(item=>item.name.toUpperCase().includes(event.target.value.toUpperCase())||
  //   item.address.toUpperCase().includes(event.target.value.toUpperCase()));
  //   console.log(newlist);
  //   this.setState({
  //     cinemaList:newlist
  //   });
  // }
}

index.js中

import App from "./01-base/21-受控Cinema"

22.受控todolist

在01-base目录下新建22-受控todolist.js

import React, { Component } from 'react'
import "./css/01-index.css"
export default class app extends Component {
  a = 100;
  // myref = React.createRef();
  state = {
    // checkedList:[],
    mytext: "",
    list:[
      {
        id: 1,
        text: "aa",
        checked: false
      },
      {
        id: 2,
        text: "bb",
        checked: false
      },
      {
        id: 3,
        text: "cc",
        checked: false
      }
    ]
  }
  render() {
    return (
      <div>
        {/* <input ref={this.myref} /> */}
        <input value={this.state.mytext} onChange={(evt)=>{
          this.setState({
            mytext: evt.target.value
          })
        }}></input>
        <button onClick={this.handleClick2.bind(this)}>add2</button>
        <ul>
          {
            this.state.list.map((item,index)=>
            <li key={item.id}>
              <input type="checkbox" checked={item.checked} onChange={()=>this.handleChecked(index)}></input>
              {/* {item.text} */}
              {/* 富文本展示 */}
              <span dangerouslySetInnerHTML={
                {
                  __html: item.text
                }
              } style={{textDecoration:item.checked?"line-through":""}}></span>
              {/* <button onClick={this.handleDelClick.bind(this,index)}>del</button> */}
              <button onClick={()=>this.handleDelClick(index)}>del</button>
            </li>)
          }
        </ul>
        {/* {this.state.list.length===0?<div>暂无代办事项</div>:null} */}
        {/* {this.state.list.length===0 && <div>暂无代办事项</div>} */}
        <div className={this.state.list.length===0?'':'hidden'}>暂无代办事项</div>

      </div>
    )
  }

  //勾选
  handleChecked(index){
    let newlist = this.state.list;
    newlist[index].checked=!newlist[index].checked;
    this.setState({
      list:newlist
    })
  }
  //add新增
  handleClick2(){
    // console.log("click2",this.myref.current.value);
    let newlist=[...this.state.list];
    newlist.push({
      id: Math.random()*10000,
      text: this.state.mytext
    });
    this.setState({
      list:newlist,
      mytext:""
    })
  }

  //删除 concat() splice()
  handleDelClick(index){
    console.log("delete " + index);
    let newlist=this.state.list.concat();
    newlist.splice(index,1);
    this.setState({
      list: newlist
    });
  }

}

index.js中

import App from "./01-base/22-受控todolist"

3.高级

01.子传父

在src目录下新建 02-advanced, 在advanced目录下新建01-子传父.js

import React, { Component } from 'react'

class Navbar extends Component{
  render(){
    return (
      <div style={{background:"red"}}>
        <button onClick={()=>{
          console.log("子通知父,让父的isShow取反",this.props.event);
          this.props.event() //调用父组件传来的回调函数
        }}>click</button>
        <span>navbar</span>
      </div>
    )
  }
}

class Sidebar extends Component{
  render(){
    return (
      <div style={{background:"yellow",width:"200px"}}>
        <ul>
          <li>111111</li>
          <li>111111</li>
          <li>111111</li>
          <li>111111</li>
          <li>111111</li>
          <li>111111</li>
          <li>111111</li>
          <li>111111</li>
          <li>111111</li>
          <li>111111</li>
        </ul>
      </div>
    )
  }
}

export default class App extends Component {
  state=({
    isShow:false
  })
  handleEvent=()=>{
    this.setState({
      isShow:!this.state.isShow
    })
    console.log("父组件定义的event事件");
  }
  render() {
    return (
      <div>
        <Navbar event={this.handleEvent}></Navbar>
        {this.state.isShow && <Sidebar></Sidebar>}
      </div>
    )
  }
}

/**
 * 父传子 属性
 * 子传父 回调函数callback
 */

index.js中

import App from "./01-base/22-受控todolist"

02.非受控卖座选项卡功能.js

在src目录下新建 02-advanced, 在advanced目录下新建02-非受控卖座选项卡功能.js

import React, { Component } from 'react'

class Navbar extends Component{
  render(){
    return (
      <div style={{background:"red"}}>
        <button onClick={()=>{
          console.log("子通知父,让父的isShow取反",this.props.event);
          this.props.event() //调用父组件传来的回调函数
        }}>click</button>
        <span>navbar</span>
      </div>
    )
  }
}

class Sidebar extends Component{
  render(){
    return (
      <div style={{background:"yellow",width:"200px"}}>
        <ul>
          <li>111111</li>
          <li>111111</li>
          <li>111111</li>
          <li>111111</li>
          <li>111111</li>
          <li>111111</li>
          <li>111111</li>
          <li>111111</li>
          <li>111111</li>
          <li>111111</li>
        </ul>
      </div>
    )
  }
}

export default class App extends Component {
  state=({
    isShow:false
  })
  handleEvent=()=>{
    this.setState({
      isShow:!this.state.isShow
    })
    console.log("父组件定义的event事件");
  }
  render() {
    return (
      <div>
        <Navbar event={this.handleEvent}></Navbar>
        {this.state.isShow && <Sidebar></Sidebar>}
      </div>
    )
  }
}

/**
 * 父传子 属性
 * 子传父 回调函数callback
 */

复制01-base目录下/maizuocomponent文件夹,到02-advanced文件夹下。

Center.js

import React, { Component } from 'react'

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

Cinema.js

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

export default class Cinema extends Component {
  state = {
    cinemaList:[],
    bakCinemaList:[]
  }

  constructor(){
    super()

    //简写
    //axios.get("url").then(res=>{console.log(res)}).catch(err=>{console.log(err)});
    //原始模式
    axios({
      url: "http://reacttp5.com/react/Index/list",
      method: "get"
      // header: {
      //   'X-Client-Info': '{"a":"3000","ch":"1002","v":"5.2.1","e":"1677936159991149602897921","bc":"310100"}',
      //   'X-Host': 'mall.film-ticket.cinema.list'
      // }
    }).then(res=>{
      console.log(res.data.data.cinemas)
      this.setState({cinemaList:res.data.data.cinemas,bakCinemaList:res.data.data.cinemas})
    }).catch(err=>{
      console.log(err);
    })

  }
  render() {
    return (
      <div>
        <input onInput={this.handleInput}/>
        {
          this.state.cinemaList.map((item)=>
            <dl key={item.cinemaId}>
              <dt>{item.name}</dt>
              <dd>{item.address}</dd>
            </dl>
          )
        }
      </div>
    )
  }

  handleInput=(event)=>{
    console.log("input",event.target.value);
    var newlist = this.state.bakCinemaList.filter(item=>item.name.toUpperCase().includes(event.target.value.toUpperCase())||
    item.address.toUpperCase().includes(event.target.value.toUpperCase()));
    console.log(newlist);
    this.setState({
      cinemaList:newlist
    });
  }
}

/**
 * filter
 */

var arr = ["aaa","bbb","ccc"]
// var newarr = arr.filter(itme=>true);
// var newarr = arr.filter(itme=>false);
var newarr = arr.filter(item=>item.includes("a"));

console.log(newarr);

Film.js

import React, { Component } from 'react'

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

Navbar.js

import React, { Component } from 'react'

export default class Navbar extends Component {
  render() {
    return (
      <div style={{background:"yellow",textAlign:"center",overflow:"hidden"}}>
        <button style={{float:"left"}}>back</button>
        <span>卖座电影</span>
        <button style={{float:"right"}} onClick={()=>{this.props.myevent()}}>center</button>
      </div>
    )
  }
}

Tabbar.js

import React, { Component } from 'react'

export default class Tabbar extends Component {
  state = {
    list: [
      {
        id: 1,
        text: "电影"
      },
      {
        id: 2,
        text: "影院"
      },
      {
        id: 3,
        text: "我的"
      }
    ],
    current: this.props.defaultValue
  }
  render() {
    // this.state.current=this.props.parentcurrent
    // this.setState({
    //   current:this.props.parentcurrent
    // })
    return (
      <div>
        <ul>
          {
            this.state.list.map((item,index)=><li className={this.state.current===index?'active':null} key={item.id} onClick = {()=>this.handleClick(index)}>{item.text}</li>)
          }
        </ul>
      </div>
    )
  }
  handleClick(index){
    this.setState({
      current: index
    })
    //通知父组件,修改父组件那个状态
    this.props.myevent(index);
  }
}

03.受控卖座选项卡.js

复制02-advanced目录下maizuocomponent文件夹,重命名maizuocomponent2 文件夹。

新建03-受控卖座选项卡.js

import React, { Component } from 'react'
import "./css/02-maizuo.css"
import Film from './maizuocomponent2/Film'
import Cinema from './maizuocomponent2/Cinema'
import Center from './maizuocomponent2/Center'
import Tabbar from './maizuocomponent2/Tabbar'
import Navbar from './maizuocomponent2/Navbar'

export default class App extends Component {
  state = {
    list: [
      {
        id: 1,
        text: "电影"
      },
      {
        id: 2,
        text: "影院"
      },
      {
        id: 3,
        text: "我的"
      }
    ],
    current: 0
  }
  render() {
    return (
      <div>
        <Navbar myevent={()=>{
          console.log("navbar-center","告诉tabbar去切换到center组件。");
          this.setState({
            current: 2
          })
        }}></Navbar>
        {
          this.which()
        }
        <Tabbar myevent={(index)=>{
          console.log("父组件定义",index)
          this.setState({
            current: index
          })
        }} current={this.state.current} list={this.state.list}></Tabbar>
      </div>
    )
  }

  which(){
    switch(this.state.current){
      case 0: return <Film></Film> ;
      case 1: return <Cinema></Cinema> ;
      case 2: return <Center></Center> ;
      default: return null;
    }
  }
}

修改 /src/maizuocomponent2/Tabbar.js

import React, { Component } from 'react'

//1.类组件
// export default class Tabbar extends Component {
//   state = {
//     current: this.props.current
//   }
//   render() {
//     // this.state.current=this.props.parentcurrent
//     // this.setState({
//     //   current:this.props.parentcurrent
//     // })
//     return (
//       <div>
//         <ul>
//           {
//             this.props.list.map((item,index)=><li className={this.props.current===index?'active':null} key={item.id} onClick = {()=>this.handleClick(index)}>{item.text}</li>)
//           }
//         </ul>
//       </div>
//     )
//   }
//   handleClick(index){
//     this.setState({
//       current: index
//     })
//     //通知父组件,修改父组件那个状态
//     this.props.myevent(index);
//   }
// }

//2.函数组件
const Tabbar = (props) => {
  return (
    <div>
      <ul>
        {
          props.list.map((item,index)=>
          <li className={props.current===index?'active':null}
           key={item.id} onClick = {()=>
            props.myevent(index)}>{item.text}</li>)
        }
      </ul>
  </div>
  )
}

export default Tabbar

index.js中

import App from "./02-advanced/03-受控卖座选项卡"

04.父子通信版-表单域组件

在02-advanced目录下 创建04-父子通信版-表单域组件.js

import React, { Component } from 'react'

class Field extends Component{
  render(){
    return <div style={{background:"yellow"}}>
      <label htmlFor={this.props.id}>{this.props.label}</label>
      <input type={this.props.type} id={this.props.id} onChange={(evt)=>{
        this.props.onChangeEvent(evt.target.value) 
      }} value={this.props.value}></input>
    </div>
  }
}

export default class App extends Component {
  state=({
    username: "tom",
    password: ""
  })
  render() {
    return (
      <div>
        <h1>登录页面</h1>
        <Field label="用户名" type="text" id="username" onChangeEvent={(value)=>{
          console.log(value);
          this.setState({
            username:value
          })
        }} value={this.state.username}></Field>
        <Field label="密码" type="password" id="password" onChangeEvent={(value)=>{
          console.log(value);
          this.setState({
            password:value
          })
        }} value={this.state.password}></Field>
        <button onClick={()=>{
          console.log(this.state.username,this.state.password,"发送后端验证")
        }}>登录</button>
        <button onClick={()=>{
          this.setState({
            username:"",
            password:""
          })
        }}>取消</button>
      </div>
    )
  }
}

index.js中

import App from "./02-advanced/04-父子通信版-表单域组件"

importAppfrom"./02-advanced/04-父子通信版-表单域组件"

05.ref版本-表单域组件.js

在02-advanced目录下 创建05-ref版本-表单域组件.js

import React, { Component } from 'react'

class Field extends Component{
  state={
    value:""
  }
  clear(){
    this.setState({
      value: ""
    })
  }
  render(){
    return <div style={{background:"yellow"}}>
      <label htmlFor={this.props.id}>{this.props.label}</label>
      <input type={this.props.type} id={this.props.id} onChange={(evt)=>{
        this.setState({
          value:evt.target.value
        })
      }} value={this.state.value}></input>
    </div>
  }
}

export default class App extends Component {
  username = React.createRef();
  password = React.createRef(); 

  render() {
    return (
      <div>
        <h1>登录页面</h1>
        <Field label="用户名" type="text" id="username" ref={this.username}></Field>
        <Field label="密码" type="password" id="password" ref={this.password}></Field>
        <button onClick={()=>{
          console.log(this.username.current.state.value,this.password.current.state.value);
        }}>登录</button>
        <button onClick={()=>{
          this.username.current.clear()
          this.password.current.clear()
        }}>取消</button>
      </div>
    )
  }
}

index.js中

import App from "./02-advanced/05-ref版本-表单域组件"

06.中间人模式-状态提升

在02-advanced目录下 创建06-中间人模式-状态提升05-ref版本-表单域组.js

import React, { Component } from 'react'
import axios from 'axios'
import './css/03-communination.css'
export default class App extends Component {
  constructor(){
    super()
    this.state=({
      filmList:[],
      info:""
    })

    axios.get("/test.json").then(res=>{
      console.log(res.data.data.films)
      this.setState({
        filmList: res.data.data.films
      })
    })
  }

  render() {
    return (
      <div>
        {/* {this.state.info} */}
        {this.state.filmList.map(item=>
          <FilmItem key={item.filmId} {...item} onEvent={(value)=>
          {
            // console.log("父组件接收",value);
            this.setState({
              info: value
            })
          }}></FilmItem>)}
        <FilmDetail info={this.state.info}></FilmDetail>
      </div>
    )
  }
}

class FilmItem extends Component{
  render(){
    console.log(this.props)
    let {name,poster,grade,synopsis} = this.props
    return (
      <div className='filmitem' onClick={()=>
      {
        // console.log(synopsis);
        this.props.onEvent(synopsis);
      }}>
        <img src={poster} alt={name}></img>
        <h4>{name}</h4>
        <div>观众评分: {grade}</div>
      </div>
    )
  }
}

class FilmDetail extends Component{
  render(){
    return (
      <div className='filedetail'>{this.props.info}</div>
    )
  }
}

在02-advanced/css目录新建文件 03-communination.css

.filmitem img{
  width: 100px;
  float: left;
}

.filmitem {
  overflow: hidden;
  padding: 10px;
}

.filedetail{
  position:fixed;
  right: 0;
  top: 100px;
  background: yellow;
  width: 300px;
  min-height: 300px;
}

在index.js中

import App from "./02-advanced/06-中间人模式-状态提升"
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值