0.箭头函数绑定this
//src/index.js
// 1.引入模块
import React from 'react'
import ReactDOM from 'react-dom'
class App extends React.Component {
// 方法一
handelClick() {
console.log(this);
}
// 方法二(推荐写法)
// handelClick = () => {
// console.log(this);
// }
render() {
// 方法一:包裹一层 箭头函数的方式 (不太推荐)
return (<button onClick={() => this.handelClick()}>按钮</button>)
// 方法二:类实例箭头函数的方式(推荐写法)
// return (<button onClick={this.handelClick}>按钮</button>)
// 方法三:调用的时候用bind绑定this (传参的时候使用)
// return (<button onClick={this.handelClick.bind(this)}>按钮</button>)
}
}
//3.将创建好的类组件挂载到dom上
ReactDOM.render(<App />, document.getElementById('root'))
1.call apply bind 区别和用法
- 功能都是操作不同对象
- apply需要用数组包裹参数
- bind返回新函数需要自调用
<script>
let obj = {
name: '山竹',
say(value, value2) {
console.log(this.name, value, value2);
}
}
let newName = { name: '杀生丸' }
// call()
obj.say.call(newName, '超级帅der')//杀生丸 超级帅der undefined
// apply()
obj.say.apply(newName, ['超级帅der'])//杀生丸 超级帅der undefined
// bind()
obj.say.bind(newName, '超级帅der')('只有bind才显示value2')//杀生丸 超级帅der 只有bind才显示value2
</script>
2.受控表单实现
- 声明state
- 绑定state中的值 给表单
- 监听表单值改变 并且更新到state当中
//src/index.js
// 1.引入模块
import React from 'react'
import ReactDOM from 'react-dom'
class App extends React.Component {
// 声明state
state = {
isValue: '',
ispwd: ''
}
// 2.监听触发事件,获取input事件
handelChange = (e) => {
// 结构name
const { name } = e.target
console.log(e);
//获取的name更新给声明的state
this.setState({
[name]: e.target.value
})
}
// 点击按钮
handelClick = (e) => {
console.log(e)
}
render() {
return (
<div>
{/* 1.触发事件 3.接收到更新的state赋值给input中的value*/}
<div>
账户名:
<input onChange={this.handelChange} value={this.state.isValue}
type='text'
name='isValue'
/>
</div>
<div>
密码:
<input onChange={this.handelChange} value={this.state.isPwd}
type='pwd'
name='ispwd'
/>
</div>
</div>)
}
}
//3.将创建好的类组件挂载到dom上
ReactDOM.render(<App />, document.getElementById('root'))
3.非受控表单实现
- 创建Ref引用
- 绑定Ref引用到表单元素
- 通过引用拿到具体的表单元素以及值
- defaultValue默认值设定
//src/index.js
// 1.引入模块
import React from 'react'
import ReactDOM from 'react-dom'
class App extends React.Component {
// 1.创建Ref引用
constructor() {
super()
//创建引用,引用命名一Ref结尾
//React.createRef()是一个工厂设计模式
this.usernameRef = React.createRef()
this.pwdRef = React.createRef()
}
// 3.通过引用拿到具体的表单元素以及值
handelClick = () => {
console.log(this.usernameRef.current.value, this.pwdRef.current.value);
}
//设定state
state = { username: '山竹' }
render() {
return (
<div>
{/* 2.绑定Ref引用到表单元素 */}
{/* 4.defaultValue默认值设定 */}
<div>
账户名:
<input defaultValue={this.state.username} type='text' ref={this.usernameRef} />
</div>
<div>
密码:
<input type='pwd' ref={this.pwdRef} />
</div>
<button onClick={this.handelClick}>按钮</button>
</div>)
}
}
//3.将创建好的类组件挂载到dom上
ReactDOM.render(<App />, document.getElementById('root'))
4.表单总结
- 表单值处理推荐使用受控表单的模式,因为拿值比较方便
- 非受控表单主要用于需要操作DOM的时候,比如:video canvas 或者动画等待
- 受控表单最后拿值可以直接到state当中去拿,非受控拿值 需要通过引用挨个取值
5.组件传值父传子
this.props接收父组件传递的值
//src/index.js
// 1.引入模块
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
class Father extends Component {
state = {
num: 18
}
render() {
return (
<div style={{ background: 'red' }}>
我是父组件
<Son num={this.state.num} />
{/* 引入子组件 */}
</div>
)
}
}
class Son extends Component {
render() {
return (
// 通过this.props接收
<div style={{ background: 'pink', margin: 10 }}>
我是子组件,从父组件传递过来的值是{this.props.num}
</div>
)
}
}
//3.将创建好的类组件挂载到dom上
ReactDOM.render(<Father />, document.getElementById('root'))
6.组建传值子传父
- 父组件定义一个方法
- 父组件在使用子组件的地方 通过组件传值 传方法给子组件
- 子组件拿到父组件传过来的方法 调用该方法同时传实参给方法
- 父组件方法中通过形参难道子组件传来的数据 更新到state当中
//src/index.js
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
class Father extends Component {
state = {
num: ''
}
// 4.监听子组件事件
// 需要用箭头函数改变this指向,否则指向调用者--子组件
receiveNum = (props) => {
console.log(props);
// 5.保存子组件的值
this.setState({
num: props
})
}
render() {
return (
<div style={{ background: 'red' }}>
我是父组件,从子组件传递过来的值是:{this.state.num}
{/* 3.监听子组件传递过来的事件 */}
<Son onReceive={this.receiveNum} />
</div>
)
}
}
class Son extends Component {
state = {
num: 18
}
// 2.传递给父组件
handelClick = () => {
this.props.onReceive(this.state.num)
}
render() {
return (
<div style={{ background: 'pink', margin: 10 }}>
我是子组件
{/* 1.触发子传父事件 */}
<button onClick={this.handelClick}>按钮</button>
</div>
)
}
}
ReactDOM.render(<Father />, document.getElementById('root'))
7.兄弟传值
子传父再父传子
//src/index.js
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
class Father extends Component {
state = {
num: ''
}
// 4.监听子组件事件
// 需要用箭头函数改变this指向,否则指向调用者--子组件
receiveNum = (props) => {
console.log(props);
// 5.保存子组件的值
this.setState({
num: props
})
}
render() {
return (
<div style={{ background: 'red' }}>
我是父组件,从子组件传递过来的值是:{this.state.num}
{/* 3.监听子组件传递过来的事件 */}
{/* 第一个子组件 */}
<Son onReceive={this.receiveNum} />
{/* 第二个子组件 */}
{/* 6.传递给第二个子组件,形成兄弟传值 */}
<Sony num={this.state.num} />
</div>
)
}
}
class Son extends Component {
state = {
num: 18
}
// 2.传递给父组件
handelClick = () => {
this.props.onReceive(this.state.num)
}
render() {
return (
<div style={{ background: 'pink', margin: 10 }}>
我是子组件
{/* 1.触发子传父事件 */}
<button onClick={this.handelClick}>按钮</button>
</div>
)
}
}
class Sony extends Component {
render() {
return (
<div style={{ background: 'yellow', margin: 10 }}>
{/* 7.接收父组件的值,形成兄弟传值 */}
我是第二个子组件,从父组件接收的值是{this.props.num}
</div>
)
}
}
ReactDOM.render(<Father />, document.getElementById('root'))
8.Context 跨组件层级传值
- 创建Provider和Consumer组件
- 使用Procider传递值
- 使用Consumer接收跨组件值
import React from 'react';
import ReactDOM from 'react-dom';
// 引入样式
import './index.css';
// 1.创建Provider和Consumer组件
const { Provider, Consumer } = React.createContext()
class App extends React.Component {
state = {
txt: '传家宝'
}
render() {
return (
// 2.使用Procider传递值
<Provider value={this.state.txt}>
<div className="app container">
<Node />
</div>
</Provider>
)
}
}
const Node = props => {
return (
<div className="node">
<SubNode />
</div>
)
}
const SubNode = props => {
return (
<div className="subnode">
<Child />
</div>
)
}
const Child = props => {
return (
<div className="child">
{/* 3.使用Consumer接收跨组件值 */}
我是曾孙子节点 --
<Consumer>
{(data) => {
return data
}}
</Consumer>
</div>
)
}
ReactDOM.render(<App />, document.getElementById('root'));
样式参考
/* index.css */
.container {
text-align: center;
margin: 0 auto;
}
.btn {
width: 200px;
height: 100px;
border-radius: 50px;
background-color: aquamarine;
}
span {
margin: 10px;
}
.app {
width: 300px;
padding: 10px;
border: 1px solid #999;
}
.user {
width: 100%;
box-sizing: border-box;
margin-bottom: 10px;
}
.content {
width: 100%;
box-sizing: border-box;
margin-bottom: 10px;
}
.no-comment {
text-align: center;
margin-top: 30px;
}
.app {
height: 100px;
padding: 10px;
background-color: #c4d0dc;
}
.node {
height: 80px;
padding: 10px;
background-color: yellowgreen;
}
.subnode {
height: 60px;
padding: 10px;
background-color: #dcdc39;
}
.child {
height: 40px;
padding: 10px;
background-color: skyblue;
}
9.props之children的用法
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
// 引入图片
import img from './image/5.jpg'
// 方法一:函数式
// class App extends Component {
// render() {
// return (
// <div>
// {this.props.children()}
// </div>
// )
// }
// }
// 方法二
class App extends Component {
render() {
return (
<div>
{this.props.children}
</div>
)
}
}
//方法一
// ReactDOM.render(<App>{() => {
// return <img src={img} />
// }}</App>, document.getElementById('root'));
// 方法二
ReactDOM.render(<App><img src={img} />
</App>, document.getElementById('root'));
效果