React
父组件传过来的数据
属性
代码示例:
// src/test/Test04.jsx
import React, {Component} from 'react';
import Test05 from "./Test05";
export default class Test04 extends Component {
render() {
let myObj = {
foo: 'foo',
bar: 'bar'
}
let shiYu = '时雨'
return (
<div>
<Test05 {...myObj} title={shiYu}/>
</div>
);
}
}
// src/test/Test05.jsx
import React, {Component} from 'react';
import PropTypes from 'prop-types'
export default class Test05 extends Component {
static ProTypes = { // 定义类属性
title: PropTypes.string.isRequired, // 父类传过来的数据类型必须是string(isRequired:必须传的参数)
}
static defaultProps = {
hello: 'Hello' // 默认值
}
render() {
console.log(this.props)
let {hello, title, foo, bar} = this.props // 解构
return (
<div>
{hello + title + foo + bar}
</div>
);
}
}
父子通信
- 用属性把父组件的状态给子组件使用
- 子组件使用回调函数通知父组件改变状态
- 父组件再用属性把状态传给子组件使用
代码示例:
// src/test/Test04.jsx
import React, {Component} from 'react';
import Test05 from './Test05'
export default class Test04 extends Component {
state = {
title: 'Foo'
}
render() {
return (
<div>
{this.state.title}
<Test05 title={(text) => {
this.setState({
title: text
})
}}/>
</div>
);
}
}
// src/test/Test05.jsx
import React, {Component} from 'react';
export default class Test05 extends Component {
render() {
return (
<div>
<button onClick={() => {
this.props.title('Bar')
}}>改变父类状态
</button>
</div>
);
}
}
// src/test/Test04.jsx
import React, {Component} from 'react';
class Field extends Component {
state = {
value: ''
}
clear() {
this.setState({
value: ''
})
}
render() {
return (
<div style={{background: 'gray'}}>
<label>{this.props.label}</label>
<input type={this.props.type} onChange={(evt) => {
this.setState({
value: evt.target.value
})
}} value={this.state.value}/>
</div>
)
}
}
export default class Test04 extends Component {
name = React.createRef()
pwd = React.createRef()
render() {
return (
<div>
<Field label={'用户名'} type={'text'} ref={this.name}/>
<Field label={'密码'} type={'password'} ref={this.pwd}/>
<button onClick={() => { // 需要借助传过去的ref属性
console.log(this.name.current.state.value, this.pwd.current.state.value) // 直接获取
}}>提交
</button>
<button onClick={() => {
this.name.current.clear() // 直接调用
this.pwd.current.clear()
}}>清空
</button>
</div>
);
}
}
非父子通信
中间人模式
代码示例:
/* /src/css/css02.css */
.filmItem img {
width: 100px;
float: left;
}
.filmItem {
overflow: hidden;
padding: 10px;
}
.FilmDetail {
position: fixed;
right: 0;
top: 100px;
background: #30363d;
width: 200px;
}
// src/test/Test04.jsx
// public/test.json
import React, {Component} from 'react';
import axios from "axios";
import '../css/css02.css'
class FilmItem extends Component {
render() {
let {name, poster, grade, synopsis} = this.props
return (
<div className={'filmItem'} onClick={() => {
this.props.onEvent(synopsis)
}}>
<img src={poster} alt={name}/>
<h4>{name}</h4>
<div>评分:{grade}</div>
</div>
)
}
}
class FilmDetail extends Component {
render() {
return (
<div className={'FilmDetail'}>
{this.props.value}
</div>
)
}
}
export default class Test04 extends Component {
constructor() {
super()
this.state = {
list: [],
value: ''
}
axios.get(`/test.json`).then((res) => {
console.log(res.data.films)
this.setState({
list: res.data.films
})
}).catch((err) => {
console.log(err)
})
}
render() {
return (
<div>
{
this.state.list.map((item) =>
<FilmItem key={item.filmId} {...item} onEvent={(value) => {
this.setState({
value: value
})
}}/>
)
}
<FilmDetail value={this.state.value}/>
</div>
);
}
}
订阅发布模式
代码示例:
// src/test/Test04.jsx
// public/test.json
import React, {Component} from 'react';
import axios from "axios";
import '../css/css02.css'
let bus = { // 调度中心
list: [],
subscribe(callback) { // 订阅
this.list.push(callback)
},
publish(text) { // 发布
this.list.forEach(callback => {
callback && callback(text) // 防止undefined
})
}
}
class FilmItem extends Component {
render() {
let {name, poster, grade, synopsis} = this.props
return (
<div className={'filmItem'} onClick={() => {
bus.publish(synopsis)
}}>
<img src={poster} alt={name}/>
<h4>{name}</h4>
<div>评分:{grade}</div>
</div>
)
}
}
class FilmDetail extends Component {
constructor() { // React实例化的时候会对其进行调用
super()
this.state = {
text: ''
}
bus.subscribe((text) => {
this.setState({
text: text
})
})
}
render() {
return (
<div className={'FilmDetail'}>
{this.state.text}
</div>
)
}
}
export default class Test04 extends Component {
constructor() {
super()
this.state = {
list: [],
}
axios.get(`/test.json`).then((res) => {
console.log(res.data.films)
this.setState({
list: res.data.films
})
}).catch((err) => {
console.log(err)
})
}
render() {
return (
<div>
{
this.state.list.map((item) =>
<FilmItem key={item.filmId} {...item}/>
)
}
<FilmDetail/>
</div>
);
}
}
context
代码示例:
// src/test/Test04.jsx
// public/test.json
import React, {Component} from 'react';
import axios from "axios";
import '../css/css02.css'
const GlobalContext = React.createContext() // 创建context对象
class FilmItem extends Component {
render() {
let {name, poster, grade, synopsis} = this.props
return (
<GlobalContext.Consumer>
{
(value) => {
console.log(value)
return (
<div className={'filmItem'} onClick={() => {
value.changeText(synopsis)
}}>
<img src={poster} alt={name}/>
<h4>{name}</h4>
<div>评分:{grade}</div>
</div>
)
}
}
</GlobalContext.Consumer>
)
}
}
class FilmDetail extends Component {
render() {
return (
<GlobalContext.Consumer>
{
(value) => {
return (
<div className={'FilmDetail'}>
{
value.text
}
</div>
)
}
}
</GlobalContext.Consumer>
)
}
}
export default class Test04 extends Component {
constructor() {
super()
this.state = {
list: [],
text: ''
}
axios.get(`/test.json`).then((res) => {
console.log(res.data.films)
this.setState({
list: res.data.films
})
}).catch((err) => {
console.log(err)
})
}
render() {
return (
<GlobalContext.Provider value={{
text: this.state.text,
changeText: (value) => {
this.setState({ // 必须写成方法,否则render不会刷新
text: value
})
}
}}>
<div>
{
this.state.list.map((item) =>
<FilmItem key={item.filmId} {...item}/>
)
}
<FilmDetail/>
</div>
</GlobalContext.Provider>
);
}
}
插槽
代码示例:
// src/test/Test04.jsx
import React, {Component} from 'react';
class Child extends Component {
render() {
return (
<div>
{this.props.children[0]}
{this.props.children[1]}
{this.props.children[2]}
</div>
)
}
}
export default class Test04 extends Component {
render() {
return (
<div>
<Child>
<div>111</div>
<div>222</div>
<div>333</div>
</Child>
</div>
);
}
}