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-中间人模式-状态提升"