写在前面,大家好!我是【跨考菌】,一枚跨界的程序猿,专注于后台技术的输出,目标成为
全栈攻城狮
!这博客是对我跨界过程的总结和思考。如果你也对Java
、后端技术
感兴趣,抑或是正在纠结于跨界,都可以关注我的动态,让我们一起学习,一起进步~
我的博客地址为:【跨考菌】的博客
目录
上篇【React新手学习指南】02 React生命周期浅析(超详细小白也能看懂) 介绍了React面向组件编程的相关内容,包括三大属性和常见的生命周期函数的详解。本文开始学习React应用的简单上手。和【跨考菌】一起加油吧~
如果你觉得对你有帮助的话,记得帮博主一键三连😊哦
1 使用create-react-app创建react应用
1.1 React脚手架
- xxx脚手架: 用来帮助程序员快速创建一个基于xxx库的模板项目
a. 包含了所有需要的配置
b. 指定好了所有的依赖
c. 可以直接安装/编译/运行一个简单效果 - react提供了一个用于创建react项目的脚手架库: create-react-app
- 项目的整体技术架构为: react + webpack + es6 + eslint
- 使用脚手架开发的项目的特点: 模块化, 组件化, 工程化
1.2 创建项目流程
npm install -g create-react-app
create-react-app hello-react
cd hello-react
npm start
1.3 React脚手架项目的结构
ReactNews
|--node_modules---第三方依赖模块文件夹
|--public
|-- index.html-----------------主页面
|--scripts
|-- build.js-------------------build打包引用配置
|-- start.js-------------------start运行引用配置
|--src------------源码文件夹
|--components-----------------react组件
|--index.js-------------------应用入口js
|--.gitignore------git版本管制忽略的配置
|--package.json----应用包配置文件
|--README.md-------应用描述说明的readme文件
2 案例一(动态评论)
2.1 效果
2.2 拆分组件
应用组件: App
- state: comments/array
添加评论组件: CommentAdd
- state: username/string, content/string
- props: add/func
评论列表组件: CommentList
- props: comments/array, delete/func
评论项组件: CommentItem
- props: comment/object, delete/func, index/number
2.3 实现
app.jsx
import React from 'react'
import CommentAdd from '../comment-add/comment-add'
import CommentList from '../comment-list/comment-list'
class App extends React.Component {
constructor (props) {
super(props)
this.state = {
comments: []
}
this.delete = this.delete.bind(this)
}
componentDidMount () {
//模拟异步获取数据
setTimeout(() => {
const comments = [
{
username: "Tom",
content: "ReactJS好难啊!",
id: Date.now()
},
{
username: "JACK",
content: "ReactJS还不错!",
id: Date.now() + 1
}
]
this.setState({
comments
})
}, 1000)
}
add = (comment) => {
let comments = this.state.comments
comments.unshift(comment)
this.setState({ comments })
}
delete (index) {
let comments = this.state.comments
comments.splice(index, 1)
this.setState({ comments })
}
render () {
return (
<div>
<header className="site-header jumbotron">
<div className="container">
<div className="row">
<div className="col-xs-12">
<h1>请发表对React的评论</h1>
</div>
</div>
</div>
</header>
<div className="container">
<CommentAdd add={this.add}/>
<CommentList comments={this.state.comments} delete={this.delete}/>
</div>
</div>
)
}
}
export default App
comment-add.jsx:
import React from 'react'
import PropTypes from 'prop-types'
class CommentAdd extends React.Component {
constructor(props) {
super(props)
this.state = {
username: '',
content: ''
}
this.addComment = this.addComment.bind(this)
this.changeUsername = this.changeUsername.bind(this)
this.changeContent = this.changeContent.bind(this)
}
addComment() {
// 根据输入的数据创建评论对象
let {username, content} = this.state
let comment = {username, content} // 构造需要的json
// 添加到comments中, 更新state
this.props.add(comment)
// 清除输入的数据
this.setState({
username: '',
content: ''
})
}
changeUsername(event) {
this.setState({
username: event.target.value
})
}
changeContent(event) {
this.setState({
content: event.target.value
})
}
render() {
return (
<div className="col-md-4">
<form className="form-horizontal">
<div className="form-group">
<label>用户名</label>
<input type="text" className="form-control" placeholder="用户名"
value={this.state.username} onChange={this.changeUsername}/>
</div>
<div className="form-group">
<label>评论内容</label>
<textarea className="form-control" rows="6" placeholder="评论内容"
value={this.state.content} onChange={this.changeContent}></textarea>
</div>
<div className="form-group">
<div className="col-sm-offset-2 col-sm-10">
<button type="button" className="btn btn-default pull-right" onClick={this.addComment}>提交
</button>
</div>
</div>
</form>
</div>
)
}
}
CommentAdd.propTypes = {
add: PropTypes.func.isRequired
}
export default CommentAdd
comment-list.jsx:
import React from 'react'
import PropTypes from 'prop-types'
import CommentItem from '../comment-item/comment-item'
import './commentList.css'
class CommentList extends React.Component {
constructor (props) {
super(props)
}
render () {
let comments = this.props.comments
let display = comments.length > 0 ? 'none' : 'block'
return (
<div className="col-md-8">
<h3 className="reply">评论回复:</h3>
<h2 style={{ display: display }}>暂无评论,点击左侧添加评论!!!</h2>
<ul className="list-group">
{
comments.map((comment, index) => {
console.log(comment)
return <CommentItem comment={comment} key={index} index={index} delete={this.props.delete}/>
})
}
</ul>
</div>
)
}
}
CommentList.propTypes = {
comments: PropTypes.array.isRequired,
delete: PropTypes.func.isRequired
}
export default CommentList
comment-item.jsx:
import React from 'react'
import PropTypes from 'prop-types'
import './commentItem.css'
class CommentItem extends React.Component {
constructor (props) {
super(props)
this.deleteComment = this.deleteComment.bind(this)
}
deleteComment () {
let username = this.props.comment.username
if (window.confirm(`确定删除${username}的评论吗?`)) {
this.props.delete(this.props.index)
}
}
render () {
let comment = this.props.comment
return (
<li className="list-group-item">
<div className="handle">
<a href="javascript:" onClick={this.deleteComment}>删除</a>
</div>
<p className="user"><span >{comment.username}</span><span>说:</span></p>
<p className="centence">{comment.content}</p>
</li>
)
}
}
CommentItem.propTypes = {
comment: PropTypes.object.isRequired,
index: PropTypes.number.isRequired,
delete: PropTypes.func.isRequired
}
export default CommentItem
3 案例二(根据关键词拉取github相关项目)
3.1 效果
3.2 拆分组件
App
* state: searchName/string
Search
* props: setSearchName/func
List
* props: searchName/string
* state: firstView/bool, loading/bool, users/array, errMsg/string
3.3 实现
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:
/**
* 上部的搜索模块
*/
import React, {Component} from 'react'
import PubSub from 'pubsub-js';
class Search extends Component {
search = () => {
var searchName = this.nameInput.value
console.log('searchName:', searchName)
// 子页面发送state
PubSub.publish("searchName", searchName);
console.log('end')
}
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 axios from 'axios'
import PubSub from 'pubsub-js';
class UserList extends React.Component {
state = {
firstView: true, // 第一次看
loading: false, // 加载中
users: null, // 用户集合
error: null
}
async componentDidMount() {
PubSub.subscribe('searchName', (msg, searchName) => { // 箭头函数,等价于func定义的函数
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 })
})
// try {
// const result = await axios.get(url)
// this.setState({ loading: false, users: result.data.items })
// } catch(err) {
// // debugger
// console.log('----', err.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
如果对你有帮助,记得帮博主一键三连😊哦