React 基础入门:脚手架、JSX、组件与状态管理
December 19, 2024 (1y ago)
在React基础中,我们需要完成如下的学习
- 脚手架使用 。
- jsx
- 组件,
- 状态,
- 事件,
- 案例
一,入门&&脚手架
React是什么
是什么?
一个构件V的层面,不是一个完成的MVC,一个构建用户界面的库
特点?
- 声明式:你只需要描述UI长什么样就好了/
- 基础组件: 最重要的内容,
- 到处跑:原生应用可以,vr可以 ,
基础的使用
是安装脚手架
npm i recat rect-dom
第一个是核心包,提供创建元素,组件等功能
第二个是一个提供DOM相关的包- 引入recat 还有 recat-dom
- 创建recat元素
- 渲染recat到页面中
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<script src="https://cdn.bootcdn.net/ajax/libs/react/17.0.1/umd/react.development.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/react-dom/17.0.1/umd/react-dom.development.js"></script>
<!-- 为了使用jsx我们需需要用bable进行预编译 -->
<script src="https://cdn.bootcss.com/babel-core/5.8.34/browser.min.js"></script>
<body>
<div id="app"></div>
<div id="app2"></div>
</body>
<script type="text/babel">
const CommonA = () => {
return <a>123</a>;
};
ReactDOM.render(<CommonA></CommonA>, document.getElementById("app2"));
</script>
</html>
脚手架
以前我们都是直接使用cli但是我们都不知道为什么要使用cli接下里,听老夫吹水一波
- 是现代开发必备的
- 充分的利用了各种工具webpack bable eslint等,辅助开发
- 零配置,无序配置,关注的是代码业务 而不是配置
- 执行命令创建项目
npx create-react-app my-app
npx 是5.2的东西,npm不需要安装脚手架,可以直接用。create-react-app是脚手架的名称 - 运行 start就好了
在Reatc脚手架项目中配置项目
实际上的效果是没有任何变化的
import React from 'react'
import ReactDOM from 'react-dom' // z注意,如果你做的原生app用的就是零个RN去渲染,而不是ReactDOM
const title = React.createElement( 'h1',null,'hellwe!')
// 注意这个root是再public下的index中的根元素的
ReactDOM.render( title,document.getElementById('root') )二、JSX 核心
首先我们来介绍如下的学习目标
- jsx基础的使用
- jsx中的js表达式
- jsx中的条件渲染
- jsx中的列表渲染
- jsx中的演示处理
- 手写太累了?建议试一下vs的提示代码插件,完美提升开发速度
jsx基础使用
实际上就是js版的html,jsx是JavaScript xml 表示在js中写xml和html内容
import React from 'react'
import ReactDOM from 'react-dom'
// const title = React.createElement( 'h1',null,'hellwe!')
// 使用jsx
const title = <h1>hellow jsx</h1>
// 注意这个root是再public下的index中的根元素的
ReactDOM.render( title,document.getElementById('root') )为什么脚手架中 直接写可以html?
注意脚手架内部做了转化bable @bable/preset-reacle
注意事项:在jsx中注意实现
- {}中可以使用js语法
- jsx自己页是一个变量 可以插入
- jsx中对象是一个例外,不能插入
- 注意{}中不能出现体语句,if/for
const name = 'zs'
const age = 18
const gender = 'man'
const div = (
<div>我是一个div</div>
)
const title = (
// 注意属性名需要用小驼峰
// 注意一些特殊的属性名,class => calssName for => htmlFor。。。。
// 建议使用小括号包裹起来jsx
<h1 className="title">
姓名:{name}
<br />
年龄:{age}
<br />
行呗:{gender + 5}
{div}
</h1>
)条件渲染& 列表渲染
注意,这个就是React中的特点,用正确的方式做正确的事情,
- 使用函数去判断,完成条件渲染
- 使用map方法去做隐射,注意要谢上key
const loadData = () => {
return isloading && (<div>显示完成~</div>)
}
// 列表渲染
const list = [
{id:1,name:'zs'},
{id:2,name:'ls'},
{id:3,name:'ww'}
]
const title = (
<div>
<h2>
{loadData()}
</h2>
<div>
<ul>
{list.map( v => <li key={v.id} > {v.name} </li> )}
</ul>
</div>
</div>
)jsx中的样式绑定
实际上非常的容易,两种方式styel内嵌还有映入文件,挂类名的
import './index.css'
const text= (
<div className="title" style={{'color':'red','backgroundColor':'pink'}}>
点击
</div>
)总结 Resct完全使用js语言,来编写ui,而不是找轮子增强HTML功能!在React中能用js的地方绝对不增加新的语法
三、组件
react中的组件的非常重要的东西。
基础的使用
组价就是recat的核心,独立性,组合型,可组合可以复用
- 使用组件有两种方式,函数式(不常用),箭头函数也是ok的,但是后续有问题的,我们后面再说,
为什么要使用大写?因为可以区分是组件还是元素
function Hellow () {
return ( <h1>helloe 我是一个函数组件</h1> )
}
// 注意这个root是再public下的index中的根元素的
ReactDOM.render( <Hellow />,document.getElementById('root') )- 使用类来创建(常用)
- React.Component必须继承 必须由返回值,必须由值
// React.Component必须继承 必须由返回值,必须由值
class Hello extends React.Component {
render() {
return ( <h1>是我了,没错了!</h1> )
}
}
// 注意这个root是再public下的index中的根元素的
ReactDOM.render( <Hello />,document.getElementById('root') )单独抽离组件
这个很重要,直接抽离出去就好了,做起来也非常的好,直接抽出来就好了
hello.js
import React from 'react'
class Hello extends React.Component {
render() {
return ( <h1>是我了,没错了!</h1> )
}
}
export default Hello
// 这样就好了
import Hello from './hello'
// 注意这个root是再public下的index中的根元素的
ReactDOM.render( <Hello />,document.getElementById('root') )事件处理&事件对象
- 我们先来看看如何进行事件的绑定,事件的搬定是非常简单的,只需要
注意啊。class组件是this 而,函数组件是没有this的!
import React from 'react'
class Hello extends React.Component {
hander(){
console.log('点击了我!');
}
render() {
// 这里需要注意的点是onclick必须是小驼峰的
return ( <button onClick={this.hander}> 点击我</button> )
}
}
export default Hello- 事件对象
hander(e){
// 注意这个e是跨平台的!,这个e也叫“作合成事件”
e.preventDefault()
console.log('点击了我!');
}四 、状态
有、无状态state
事实上,有非常简单的理解就是有状态组件就是指的是class的组件

状态到底是什么?
实际上状态就是data数据(类似于vue中的data)
- 我们来定义一个数据
class Hello extends React.Component {
// constructor(){
// super()
// this.state = {
// count = 0
// }
// }
state = {
count : 0
}
hander = (e) => { // 注意这里的this问题 箭头函数可以,bind也可以
this.setState({
count : this.state.count + 1
})
}
render() {
// 这里需要注意的点是onclick必须是小驼峰的
return (
<div>
<h1>{this.state.count}</h1>
<button onClick={this.hander}> 点击我可以+1</button>
</div> )
}
}- 我们来改变一个数据(React中默认支持响应mvvm) 详细的代码如上已经给出
五、事件
受控组件还有非受控组件
所谓的受控组件,就是有recate的state控制的组件,默认的情况下,html有自己的状态,比如input框,可以自己输入,
但是recate希望由自己的state控制,于是就有了受控组件,实现一个受控组件
- 实现一个最简单的受控组件input进行双向的数据绑定
state = {
text :'',
}
// 事件
hander = (e) => { // 注意这里的this问题
this.setState({
text : e.target.value,
})
}
<div>
<h1>{this.state.text}</h1>
<input value={this.state.text} onChange={this.hander}></input>
</div>- 实现多个受控的组件
import React from 'react'
class Hello extends React.Component {
// constructor(){
// super()
// this.state = {
// count = 0
// }
// }
state = {
text :'',
content:'',
city:'bj',
checked:false
}
// 事件
hander = (e) => { // 注意这里的this问题
this.setState({
text : e.target.value,
})
}
handerContet = (e) => { // 注意这里的this问题
this.setState({
content : e.target.value,
})
}
handerCity = (e) => { // 注意这里的this问题
this.setState({
city : e.target.value,
})
}
handerCheckebox = (e) => { // 注意这里的this问题
this.setState({
checked : e.target.checked,
})
}
render() {
return (
<div>
{/* input简单的受控组件 */}
<div>
<h1>{this.state.text}</h1>
<input value={this.state.text} onChange={this.hander}></input>
</div>
{/* 富文本受控组件 */}
<div>
<textarea value={this.state.content} onChange={this.handerContet}></textarea>
</div>
{/* 下拉选择受控组件 */}
<div>
<select value={this.state.city} onChange={this.handerCity}>
<option value="sh">上海</option>
<option value="gz">官洲</option>
<option value="bj">北京</option>
</select>
</div>
</div> )
}
}
export default Hello多表单元素的优化
使用一个处理程序,处理多个事件,实际上,这个也是一个造轮子的过程,我们给选框,打一个记号,然后根据记号,改变值
import React from 'react'
class Hello extends React.Component {
// constructor(){
// super()
// this.state = {
// count = 0
// }
// }
state = {
text :'',
content:'',
city:'bj',
checked:false
}
// 事件
handerFrom = (e) => { // 注意这里的this问题
let target = e.target
let value = target.type === "checkbox"
? target.checked
: target.value
let name = target.name
this.setState({
[name] : value
})
}
render() {
return (
<div>
{/* input简单的受控组件 */}
<div>
<h1>{this.state.text}</h1>
<input name="text" value={this.state.text} onChange={this.handerFrom}></input>
</div>
{/* 富文本受控组件 */}
<div>
<textarea name="content" value={this.state.content} onChange={this.handerFrom}></textarea>
</div>
{/* 下拉选择受控组件 */}
<div>
<select name="select" value={this.state.city} onChange={this.handerFrom}>
<option value="sh">上海</option>
<option value="gz">官洲</option>
<option value="bj">北京</option>
</select>
</div>
</div> )
}
}
export default Hello非受控组件
这个知识点,我们了解就好了,在react中是不推荐直接操作dom的

React中的组件基础总结

六、综合练习
- 渲染列表
列表渲染,条件渲染
有关于列表的渲染还是非常的简单的,只需要渲染遍历map就好了
import React from 'react'
class Commont extends React.Component {
state = {
comment:[
{ id:1, name:'jack', content:'沙发!!!' },
{ id:2, name:'roes', content:'heieh' },
{ id:3, name:'tom', content:'板凳' },
{ id:4, name:'JRET', content:'有点意思~' }
]
}
render() {
return (
<div className="app">
{/* 顶部盒子 */}
<div>
<input className="user" type='text' placeholder="请输入评论人" />
<br />
<textarea
className="content"
cols="30"
rows="10"
placeholder="请输入评论内容"
/>
<br />
<button>发布评论</button>
</div>
{/* 中间盒子 */}
<div className="no-comment">暂无评论,快去评论吧</div>
{/* 品论额列表 */}
//核心代码
<ul>
{
this.state.comment.map(item => (
<li key={item.id}>
<h3>评论人: {item.name} </h3>
<p> 评论内容:{item.content} </p>
</li>
) )
}
</ul>
</div>
)
}
}
export {Commont}做好写死的渲染之后,现在我们“活起来”尝试使用一下条件渲染吧~( 又是一个造轮子的过程,注意啊,我们不允许在jsx中出现语句,形入if/else不允许出现)
// 这里只是给出核心代码,三元表达式那是真的香啊!!!
{
this.state.comment.length === 0
? (
<div className="no-comment">暂无评论,快去评论吧</div>
)
: (
<ul>
{
this.state.comment.map(item => (
<li key={item.id}>
<h3>评论人: {item.name} </h3>
<p> 评论内容:{item.content} </p>
</li>
) )
}
</ul>
)
}功能是可以并且允许 无限的优化的。接下来,我们丢带方法里去
renderList() {
if( this.state.comment.length === 0 ){
return ( <div className="no-comment">暂无评论,快去评论吧</div> )
}
return (
this.state.comment.map(item => (
<li key={item.id}>
<h3>评论人: {item.name} </h3>
<p> 评论内容:{item.content} </p>
</li>
) )
)
}- 发布评论功能
受控组件,更新状态
准备数据,实现受控组件,注意这里的 属性名表达式(ES6的语法),这个也是非常重要的一点!
// 注意,这里只是列举了一些核心的代码块
state = {
comment:[
{ id:1, name:'jack', content:'沙发!!!' },
{ id:2, name:'roes', content:'heieh' },
{ id:3, name:'tom', content:'板凳' },
{ id:4, name:'JRET', content:'有点意思~' }
],
userName:'',
userContent:''
}
// 首先双向的数据搬定方式,注意this问题!
handleChange = (e) => {
const { name,value } = e.target
this.setState({
[name]:value
})
}
// DOM的互动
<div className="app">
<div>
<input
className="user"
type='text'
placeholder="请输入评论人"
value={userName}
name='userName'
onChange={this.handleChange}
/>
<br />
<textarea
className="content"
cols="30"
rows="10"
placeholder="请输入评论内容"
value={userContent}
name='userContent'
onChange={this.handleChange}
/>接下俩的事情久是水到渠成了!获取数据更新数组列表就完事了!
// 这里只是列举出几个核心的代码.注意这里的结构赋值很重要!,数组的往前的添加方法666的写法
// 点击按钮添加数据
addCommet = () => {
const { userContent,userName,comment } = this.state
let newComment = [ {
id:comment[comment.length-1].id + 1, // id自增
name:userName,
content:userContent
} ,...comment ]
this.setState({
comment:newComment
})
}
<button onClick={this.addCommet}>发布评论</button>完善组件的功能
// 点击按钮添加数据
addCommet = () => {
const { userContent,userName,comment } = this.state
// 做一些数据校验的工作
if(userContent.trim() === '' || userName.trim() === '' ){
alert('请输入评论人/品论内容')
return
}
let newComment = [ {
id:Math.random(),
name:userName,
content:userContent
} ,...comment ]
this.setState({
comment:newComment,
// 优化,点击之后清空表单
userContent:'',
userName:''
})
}代码集合
渲染的逻辑这里就不写了,直接拿出去渲染就是了
import React from 'react'
class Commont extends React.Component {
state = {
comment:[
{ id:1, name:'jack', content:'沙发!!!' },
{ id:2, name:'roes', content:'heieh' },
{ id:3, name:'tom', content:'板凳' },
{ id:4, name:'JRET', content:'有点意思~' }
],
userName:'',
userContent:''
}
// 条件渲染列表组件
renderList () {
if( this.state.comment.length === 0 ) {
return ( <div className="no-comment">暂无评论,快去评论吧</div> )
}
return (
this.state.comment.map(item => (
<li key={item.id}>
<h3>评论人: {item.name} </h3>
<p> 评论内容:{item.content} </p>
</li>
) )
)
}
// 首先双向的数据搬定方式,注意this问题!
handleChange = (e) => {
const { name,value } = e.target
this.setState({
[name]:value
})
}
// 点击按钮添加数据
addCommet = () => {
const { userContent,userName,comment } = this.state
// 做一些数据校验的工作
if(userContent.trim() === '' || userName.trim() === '' ){
alert('请输入评论人/品论内容')
return
}
let newComment = [ {
id:Math.random(),
name:userName,
content:userContent
} ,...comment ]
this.setState({
comment:newComment,
// 优化,点击之后清空表单
userContent:'',
userName:''
})
}
// 正式的返回值
render() {
// 先进行结构。使得结构看起来更加的清晰
const { userName,userContent } = this.state
return (
<div className="app">
<div>
<input
className="user"
type='text'
placeholder="请输入评论人"
value={userName}
name='userName'
onChange={this.handleChange}
/>
<br />
<textarea
className="content"
cols="30"
rows="10"
placeholder="请输入评论内容"
value={userContent}
name='userContent'
onChange={this.handleChange}
/>
<br />
<button onClick={this.addCommet}>发布评论</button>
</div>
{this.renderList()}
</div>
)
}
}
export {Commont}