组件间通信
- 方式一: 通过props传递
1) 共同的数据放在父组件上, 特有的数据放在自己组件内部(state)
2) 通过props可以传递一般属性和函数属性, 只能一层一层传递
3) 一般属性–>父组件传递数据给子组件–>子组件读取数据
4) 函数属性–>子组件传递数据给父组件–>子组件调用函数 -
方式二: 使用消息订阅(subscribe)-发布(publish)机制
1) 工具库:PubSubJS
2) 下载:npm install pubsub-js --save
3) 使用:
import PubSub from 'pubsub-js' //引入
PubSub.subscribe('delete', function(data){ }); //订阅
PubSub.publish('delete', data) //发布消息
- 方式三: redux
省略
DEMO:获取github用户信息
实现效果
通过props传递实现
App.jsx
代码如下:
import React, {Component} from "react"
import Search from './components/Search/Search'
import List from './components/List/List'
export default class App extends Component {
state = {
keyword: ''
}
setKeyWord = (keyword) => {
this.setState({keyword})
}
render() {
let {keyword} = this.state
return (
<div className="container">
<Search setKeyWord={this.setKeyWord}/>
<List keyword={keyword}/>
</div>
)
}
}
components/Search/Search.jsx
代码如下:
import React, {Component} from "react";
export default class Search extends Component {
search = () => {
let {keyword} = this
let {setKeyWord} = this.props
keyword = keyword.value
setKeyWord(keyword)
this.keyword.value = ''
}
render() {
return (
<section className="jumbotron">
<h3 className="jumbotron-heading">Search Github Users</h3>
<div>
<input type="text" placeholder="enter the name you search" ref={(input)=>{this.keyword = input}}/>
<button onClick={this.search}>Search</button>
</div>
</section>
);
}
}
components/List/List.jsx
代码如下:
import React, {Component} from "react";
import Item from '../Item/Item'
import axios from "axios";
export default class List extends Component {
state = {
isLoading: false,
users: [],
errMsg: ''
}
async componentWillReceiveProps({keyword}) {
this.setState({
isLoading: true,
})
const url = `https://api.github.com/search/users?q=${keyword}`
try {
let response = await axios.get(url)
let users = response.data.items.map((item, index) => {
return {
id: item.id,
html_url: item.html_url,
avatar_url: item.avatar_url,
user_name: item.login
}
})
this.setState({
isLoading: false,
users
})
} catch (err) {
this.setState({
isLoading: false,
errMsg: err.toString()
})
}
}
render() {
let {isLoading,users,errMsg} = this.state
if (users.length > 0) {
return (
<div className="row">
{
users.map((item) => {
console.log(item)
return <Item key={item.id} {...item}/>
})
}
</div>
);
} else {
if (isLoading) {
return <h2>Loading...</h2>
} else if (errMsg) {
return <h2>{errMsg}</h2>
} else {
return <h2>Enter name to search</h2>
}
}
}
}
components/Item/Item.jsx
代码如下:
import React, {Component} from "react";
import './Item.css'
export default class Item extends Component {
render() {
let {html_url,avatar_url,user_name} = this.props
return (
<div className="card ">
<a href={html_url} rel="noopener noreferrer" target="_blank">
<img alt="" src={avatar_url} style={{width: '100px'}}/>
</a>
<p className="card-text">{user_name}</p>
</div>
);
}
}
通过消息订阅机制实现
App.jsx
代码如下:
import React, {Component} from "react"
import Search from './components/Search/Search'
import List from './components/List/List'
export default class App extends Component {
render() {
return (
<div className="container">
<Search/>
<List/>
</div>
)
}
}
components/Search/Search.jsx
代码如下:
import React, {Component} from "react";
import PubSub from "pubsub-js";
import axios from "axios";
export default class Search extends Component {
search = async () => {
//获取用户输入
let keyword = this.keyword.value.trim()
//设置loading状态
PubSub.publish('updateListState',{isLoading: true,users: [],errMsg: ''})
//发送请求
const url = `https://api.github.com/search/users?q=${keyword}`
try {
let response = await axios.get(url)
let users = response.data.items.map((item, index) => {
return {
id: item.id,
html_url: item.html_url,
avatar_url: item.avatar_url,
user_name: item.login
}
})
PubSub.publish('updateListState',{isLoading: false,users,errMsg: ''})
} catch (err) {
PubSub.publish('updateListState',{isLoading: false,users:[],errMsg: err.toString()})
}
this.keyword.value = ''
}
render() {
return (
<section className="jumbotron">
<h3 className="jumbotron-heading">Search Github Users</h3>
<div>
<input type="text" placeholder="enter the name you search" ref={(input)=>{this.keyword = input}}/>
<button onClick={this.search}>Search</button>
</div>
</section>
);
}
}
components/List/List.jsx
代码如下:
import React, {Component} from "react";
import Item from '../Item/Item'
import PubSub from 'pubsub-js'
export default class List extends Component {
state = {
isLoading: false,
users: [],
errMsg: ''
}
componentDidMount() {
PubSub.subscribe('updateListState',(msg,{isLoading,users,errMsg})=>{
this.setState({
isLoading,
users,
errMsg,
})
})
}
render() {
let {isLoading,users,errMsg} = this.state
if (users.length > 0) {
return (
<div className="row">
{
users.map((item) => {
console.log(item)
return <Item key={item.id} {...item}/>
})
}
</div>
);
} else {
if (isLoading) {
return <h2>Loading...</h2>
} else if (errMsg) {
return <h2>{errMsg}</h2>
} else {
return <h2>Enter name to search</h2>
}
}
}
}
components/Item/Item.jsx
代码如下:
import React, {Component} from "react";
import './Item.css'
export default class Item extends Component {
render() {
let {html_url,avatar_url,user_name} = this.props
return (
<div className="card ">
<a href={html_url} rel="noopener noreferrer" target="_blank">
<img alt="" src={avatar_url} style={{width: '100px'}}/>
</a>
<p className="card-text">{user_name}</p>
</div>
);
}
}