查看专栏其它文章:
② React 面向组件编程(state、props、refs)、事件处理
④ React 列表与Keys、虚拟DOM相关说明、AJAX
React
本人是个新手,写下博客用于自我复习、自我总结。
如有错误之处,请各位大佬指出。
学习资料来源于:尚硅谷
AJAX请求 (使用axios)
在之前的文章中已经介绍过这部分用法,想要回顾可参照我的第 ④ 篇文章,如果对具体AJAX的用法不熟悉,可以参考文章:Ajax介绍以及工作原理和实现详解(JS实现Ajax 和 JQ实现Ajax)
因为推荐使用 axios,所以这里只用 axios 进行演示。在项目中使用的用法和之前相同。只不过需要注意,不要忘记在项目中先导入 axios:npm i axios --save
index.js
import React from 'react'
import ReactDOM from 'react-dom'
import App from './components/app'
import './index.css'
ReactDOM.render(<App />, document.getElementById('root'))
app.jsx
import React from 'react'
import Search from './search'
import UserList from './user-list'
export default class App extends React.Component {
state = {
searchName: ''
}
refreshName = (searchName) => this.setState({searchName})
render() {
return (
<div className="container">
<section className="jumbotron">
<h3 className="jumbotron-heading">Search Github Users</h3>
<Search refreshName={this.refreshName}/>
</section>
<UserList searchName={this.state.searchName}/>
</div>
)
}
}
search.jsx
/**
* 上部的搜索模块
*/
import React, {Component} from 'react'
import PropTypes from 'prop-types'
class Search extends Component {
static propTypes = {
refreshName: PropTypes.func.isrequired
}
search = () => {
const name = this.nameInput.value.trim()
if(name){
this.props.refreshName(name)
}
}
render() {
return (
<div>
<input type="text" placeholder="enter the name you search"
ref={(input => this.nameInput = input)}/>
<button onClick={this.search}>Search</button>
</div>
)
}
}
export default Search
user-list.jsx
/**
* 下部的用户列表模块
*/
import React from 'react'
import PropTypes from 'prop-types'
import axios from 'axios'
class UserList extends React.Component {
static propTypes = {
searchName: PropTypes.string.isrequired
}
state = {
firstView: true,
loading: false,
users: null,
error: null
}
componentwillReceiveProps(nextProps) {
let searchName = nextProps.searchName
console.log('发送ajax请求', searchName)
const url = `https://api.github.com/search/users?q=${searchName}`
this.setState({ firstView: false, loading: true })
// 使用axios库
axios.get(url)
.then((response) => {
console.log(response)
this.setState({ loading: false, users: response.data.items })
})
.catch((error)=>{
// debugger
console.log('error', error.response.data.message, error.message)
this.setState({ loading: false, error: error.message })
})
}
render () {
if (this.state.firstView) {
return <h2>Enter name to search</h2>
} else if (this.state.loading) {
return <h2>Loading result...</h2>
} else if (this.state.error) {
return <h2>{this.state.error}</h2>
} else {
return (
<div className="row">
{
this.state.users.map((user) => (
<div className="card" key={user.html_url}>
<a href={user.html_url} target="_blank">
<img src={user.avatar_url} style={{width: '100px'}} alt='user'/>
</a>
<p className="card-text">{user.login}</p>
</div>
))
}
</div>
)
}
}
}
export default UserList
在这里使用到了之前在生命周期中提到过的,componentwillReceiveProps()
。这个勾子函数的使用也是比较频繁的,它的作用是:组件将要接收到新的props时回调。而在上面代码的整个过程中,只要从输入框中输入新数据搜索信息时,就会将该搜索内容通过props的方式传递给该组件,因此将axios请求放在其中,就是十分合适的。
组件间通信
方式一: 通过props传递
对于第一种方式应该已经不陌生了,在这里就不放代码了。测试语法时,所有组件传递用的都是 props。那在项目中,我们通常将共同的数据放在父组件上,特有的数据放在各自组件内部 (state)。然后涉及到数据传递,用的就是 props。
从目前来看,它的特点是:可以传递一般数据和函数数据,且只能一层一层传递。
方式二: 使用消息订阅(subscribe)-发布(publish)机制
对于这种方式,想要使用需要下载: npm install pubsub-js --save
它的使用方法:
import PubSub from 'pubsub-js' //引入
PubSub.subscribe('delete', function(data){ }); //订阅
PubSub.publish('delete', data) //发布消息
它和 props 那种需要一层一层传递的区别是:消息订阅-发布的方式可以做到直接传递
首先对于 app.jsx,之前的时候我们把共同的数据存放在父组件上,这样才能做到数据传递。但现在有了 消息订阅-发布的方式,我们已经不需要这么做了,现在可以做到直接传递:
import React from 'react'
import Search from './search'
import UserList from './user-list'
export default class App extends React.Component {
render() {
return (
<div className="container">
<section className="jumbotron">
<h3 className="jumbotron-heading">Search Github Users</h3>
<Search/>
</section>
<UserList/>
</div>
)
}
}
然后对于搜索框组件 search.jsx,我们要将输入的数据传递给用户列表组件,去使用 axios 获取数据,此时我们只需 发布消息 即可。需要注意的是,消息名要和订阅消息时的消息名相同,比如在这里是 search
。传递的消息是 searchName。
/**
* 上部的搜索模块
*/
import React, {Component} from 'react'
import PubSub from 'pubsub-js'
class Search extends Component {
search = () => {
const searchName= this.nameInput.value.trim()
if(searchName){
//发布消息
PubSub.publish('search', searchName)
}
}
render() {
return (
<div>
<input type="text" placeholder="enter the name you search"
ref={(input => this.nameInput = input)}/>
<button onClick={this.search}>Search</button>
</div>
)
}
}
export default Search
因此,根据上述内容,订阅消息时其消息名一定要为 search
才能匹配。这里的msg不用管,其实代表的是消息名。在这里接收传递过来消息的参数名是 searchName。但这个参数名,不一定要和发布消息时的相同。
/**
* 下部的用户列表模块
*/
import React from 'react'
import axios from 'axios'
import PubSub from 'pubsub-js'
class UserList extends React.Component {
state = {
firstView: true,
loading: false,
users: null,
error: null
}
componentDidMount() {
//订阅消息
PubSub.subscribe('search',(msg,searchName) => {
const url = `https://api.github.com/search/users?q=${searchName}`
this.setState({ firstView: false, loading: true })
// 使用axios库
axios.get(url).then((response) => {
this.setState({ loading: false, users: response.data.items })
}).catch((error)=>{
this.setState({ loading: false, error: error.message })
})
})
}
render () {
if (this.state.firstView) {
return <h2>Enter name to search</h2>
} else if (this.state.loading) {
return <h2>Loading result...</h2>
} else if (this.state.error) {
return <h2>{this.state.error}</h2>
} else {
return (
<div className="row">
{
this.state.users.map((user) => (
<div className="card" key={user.html_url}>
<a href={user.html_url} target="_blank">
<img src={user.avatar_url} style={{width: '100px'}} alt='user'/>
</a>
<p className="card-text">{user.login}</p>
</div>
))
}
</div>
)
}
}
}
export default UserList
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。