条件渲染
1. if / else
render () {if (this.state.isLoading) { // 正在加载中return <h1>Loading...</h1>}return <div>这就是我们想要的内容</div>}
// 钩子函数 五秒钟之后 修改状态值componentDidMount () { setTimeout(() => {this.setState({isLoading : false})}, 3000);}
2. 三元表达式
return this.state.isLoading ? (<h1>Loading...</h1>) : (<div>这就是我们想要的内容</div>)
3. 逻辑运算符
return this.state.isLoading && (<h1>Loading...</h1>)
列表渲染
遍历1
// 准备数据
state = {list :['小苹果','大香蕉','黄橙子']
}return (<ul>{this.state.list.map(item => { return <li>{ item }</li>}) }
</ul>)
遍历2
// 准备数据
state = {list2: [{ id: 1, name: '春' }, { id: 2, name: '飞' }, { id: 3, name: '莲' }]
}
// 遍历return (<ul>{this.state.list2.map(item => { return <li key={item.id}>{ item.name }</li>}) }</ul>)
提取到函数
// render 钩子函数
render () {return (<ul>{ this.renderLi() }</ul>)}// 提取到的一个函数
// 必须要有返回值
renderLi () { return this.state.list2.map(item => { return <li key={item.id}>{ item.name }</li>})
}
处理样式
行内样式
// 这个{{}} 不是双括号语法, 而是单括号里面有个 样式对象
//{} 可以拿到原始类型
<div style={{ color: 'pink', backgroundColor: 'yellowgreen', height: 300 }}>
外联样式
//1. 外部 index.css
.red {color: red;font-size: 50px;
}//2. 引入
import './index.css'//3. 添加类<p className='red' >哈哈</p>
评论案例
步骤
-
准备数据 - 列表展示
-
受控组件
-
表单头部展示收集数据
-
补充 : 非受控组件
评论案例1 : 列表展示
- 准备数据
list: [{ id : 1, username :'张三', content :'做一个凡人' },{ id : 2, username :'李四', content :'贪财好色' },{ id : 3, username :'王五', content :'一身正气' }],
- 展示
<ul>{this.state.list.map(item => { return (<li key={item.id}><p>评论人 : {item.username}</p><p>评论内容 : {item.content}</p></li>)}) }
</ul>
评论案例2 : 受控组件
- 见下面的
受控组件模块
评论案例3 : 头部展示
- 结构
<div>评论的人 :<inputonChange={e => this.getValues('username', e.target.value)} # +name="username"value={username}style={{ width: '214px' }}type="text"/><br />评论内容 :<textareaonChange={e => this.getValues('content', e.target.value)} # +name="content"value={content}cols="30"rows="10"></textarea><button onClick={this.add}>添加评论</button>
</div>
- 处理表单数据
getValues = (name, value) => {this.setState({[name]: value})
}
- 添加评论
add = () => { // 获取数组const { list, content, username } = this.state let obj = {id: +new Date(),content,name : username}this.setState({list: [obj, ...list],content: '',username :''}) }
评论案例4 : 非受控组件
- 见 下面
非受控组件模块
受控组件
导入 : 给 input 添加了一个value ,展示默认值
受控组件介绍
-
表单元素 是用来收集数据的
-
react 表单元素分为 : 受控组件 + 非受控组件
-
受控组件 : 受 React 控制的组件
-
如何成为受控组件 ? 给 input 添加value 值, 那么这个input 就成了受控组件
-
M ==> V , V ==> M (我们自己处理)
- 1.需要给 input 添加 value 并且赋值 => M ==> V
- 2.onChange={ this.handleInput } ==> 监听 V 的数据变化, 收集值赋值给 M
- 3. handleInput = (e) => {// 监听input 的变化// (V) 拿到文本框的值, 修改 state 里面的数据(M)console.log(e,target.value)// 修改状态this.setState({username : e.target.value})}
其他表单处理受控组件
// 文本输入框
<input onChange={this.handleInput} value={username} type="text" /> <br />
// 文本域
<textarea onChange={this.handleTextarea} value={content} cols="30" rows="10"></textarea>
// 下拉框
<select value={city} onChange={this.handleSelect}><option value="sh">上海</option><option value="hz">杭州</option><option value="bj">北京</option>
</select>
- 处理
// 处理 input handleInput = (e) => { this.setState({username: e.target.value})}// 同上
.....
优化1
// 让其他表单都绑定到一个事件中
// 文本输入框
<input name='username' onChange={this.handleInput} value={username} type="text" /> <br />
// 文本域
<textarea name='content' onChange={this.handleTextarea} value={content} cols="30" rows="10"></textarea>
// 下拉框
<select name='city' value={city} onChange={this.handleSelect}><option value="shanghai">上海</option><option value="hangzhou">杭州</option><option value="beijing">北京</option>
</select>
- 处理
handle = e => { // console.log(e.target.name);this.setState({[e.target.name] : e.target.value})}
优化2
// 文本输入框
<input onChange={(e) => this.getValues('username', e.target.value)} value={username} type="text" /> <br />
// 文本域
<textarea onChange={(e) => this.getValues('content', e.target.value)} value={content} cols="30" rows="10"></textarea>
// 下拉框
<select value={city} onChange={ (e) => this.getValues('city', e.target.value) }><option value="shanghai">上海</option><option value="hangzhou">杭州</option><option value="beijing">北京</option>
</select>
- 处理
getValues = (name, value) => { this.setState({[name] : value})}
非受控组件
导入 : 如果不想让inptu 成为受控组件 , 又想添加默认值
####非受控组件介绍:
- 添加 defaultValue :
<input type="text" defaultValue={this.state.name} />
- 它默认就是一个非受控组件
- 非受控组件操作 DOM 直接获取 数据 – 通过 ref
使用步骤
- 1-创建 ref 引用
constructor(){super()// 方式1this.iptRef = React.createRef()
}
// 和 state 一样
// 方式2: 属性初始化语法
iptRef = React.createRef()
- 2-绑定 ref
<input ref={ this.iptRef } />
- 3-获取数据
// 可以通过尝试点击按钮
click = () => {console.log(this.iptRef.current.value)
}
组件通讯
父传子
- 通过普通的props属性传递, 实现父传子即可
// 父组件
class Parent extends React.Component {// 1. 准备好数据state = {pName : '父的数据'}render() {return (<div><p>哈哈</p>//2. 通过属性 将数据传递给子组件<Child name={this.state.pName}></Child></div>)}
}
// 子组件
// 3. 通过 props 获取数据
const Child = (props) => <div>子组件 { props.name }</div>
子传父
- 思路 : 父组件中提供了一个方法, 由子组件调用这个方法, 将数据作为参数传递给父组件
- 步骤 :
- 1-在父组件中提供一个方法
- 2-将这个方法通过属性传递给子组件
- 3-子组件中通过props 拿到这个方法调用, 并且将数据作为参数传递
// 父组件
class Parent extends React.Component {// 第一步 :父组件准备一个方法pFn = (data) => { console.log('调用了',data);}render() {return (<div><p>哈哈</p>{/* 第二步 : 通过属性将方法产传递给子组件 */}<Child cfn={ this.pFn } ></Child></div>)}
}
// 子组件
class Child extends React.Component { render () { return (<div><button onClick={this.sendMsg}>点击发送</button></div>)}sendMsg = () => { // 第三步 : 子组件通过props 拿到这个方法, 并且传参this.props.cfn('撩汉子')}
}
兄弟组件通讯
- 思路 : 状态提升
改造评论案例 ★
-
组件化
- index.js => Comments父组件
- components/
- CommentsList.js ==> CommentsList 列表组件
- CommentsLForm.js ==> CommentsLForm 表单组件
-
父传子 => 把 list 传给 CommentsList 组件 => 遍历展示列表
-
子传父 => 把表单里的数据新对象 => 点击添加评论 => 传给 Comments组件
-
pGetData
-
添加评论
context
- 使用场景 : 跨多层组件传递数据
- 如果两个组件是
远房亲戚
的关系,此时,就可以使用 Context 来通讯。
- 如果两个组件是
- 画图 : One > Two > Three > Four
- Context 中提供了两个组件
- Provider 组件 : 提供组件, 提供数据
- Consumer 组件 : 消费组件, 接收数据
// 1. 创建 Context 对象, 并解构出来两个组件
const { Provider, Consumer } = React.createContext() # +//2. 类组件
class One extends React.Component {state = {color :'red'}render() {return (// 第二步 : 使用 Provider 组件包裹 one组件, 只有被包裹的部分里面才能获取数据 // 通过 value 属性提供要共享的数据<Provider value={ this.state.color }> # +<div><p> One </p><Two></Two></div></Provider>)}
}
class Two extends React.Component {
....
}
class Three extends React.Component {....
}
class Four extends React.Component {render() {return (<div><p>Four</p>{/* 3.在 Four 组件中, 通过 consumer 来获取数据 */}{/* 遵循的是 render-props 思想 后面介绍 */}<Consumer>{data => { return <p style={{ color : data }} >这是测试用的</p> # +}}</Consumer></div>)}
}