1、React复习
// vscode在js文件中,对jsx语法非常友好
const element = (
<div>
{/* 我是注释 */}
<h1>这是一个标题</h1>
<p>这是内容</p>
</div>
)
// react的组件: 函数组件 类组件
function Hello() {
return <div>hello react</div>
}
class World extends React.Component {
// 类组件一定需要有一个方法,render
constructor(props) {
super(props)
// 类组件中,可以通过state属性,提供一些状态
this.state = {
msg: '哈哈'
}
}
render() {
return (
<div>
这是world组件---
{this.state.msg} --- {this.props.name}
</div>
)
}
}
// 函数组件和类组件的区别
// 函数组件:无状态组件
// 类组件: 状态组件, 在类组件中,可以有自己的状态
// 将来,如果某个组件不需要有自己状态,这个组件的内容是固定死的,直接使用函数组件就行
// 如果组件有自己的状态,需要定义一个类组件即可。
ReactDOM.render(<World name="zs" age="18" />, document.getElementById('app'))
2、React事件
// 1. 在react中注册事件与给DOM注册事件基本是一样的, onclick onmouseenter onblur onkeyup
// 2. 在react中注册事件,采用驼峰命名法, onClick onMouseEnter onBlur
// 3. 在react中注册事件,通过{}传入的是一个函数, 而不是一个字符串
// 4. 在react中,如果想要组件浏览器的默认行为,不要使用return false,使用e.preventDefault()
class Event extends React.Component {
render() {
return (
<div>
<button onClick={this.clickFn}>点我注册事件</button>
<a href="http://web.itcast.cn" onClick={this.clickFn}>
传智大前端
</a>
</div>
)
}
clickFn(e) {
// 想要组件浏览器的默认行为
e.preventDefault()
console.log('哈哈')
}
}
ReactDOM.render(<Event />, document.getElementById('app'))
3、React事件-this的问题
// 在react的事件处理程序中,内部的this是指向undefined
// 解决方案1: 通过this.clickFn.bind(this)
// 解决方案2: 属性初始化器语法, 提供了一个箭头函数
// 解决方案3: 在函数外面包一层箭头函数 onClick={this.clickFn}
// onClick={()=>{this.clickFn()}}
class Event extends React.Component {
constructor(props) {
super(props)
// 提供组件自己的状态
this.state = {
msg: 'hello react'
}
// 可以在构造函数中,去处理事件处理函数的this问题
// this.clickFn = this.clickFn.bind(this)
}
render() {
return (
<div>
<p>{this.state.msg}</p>
{/* 需求:点击button的时候,需要改变msg的数据 */}
<button
onClick={() => {
this.clickFn()
}}
>
点我修改msg
</button>
<a href="" onClick={this.clickFn} />
</div>
)
}
clickFn() {
// 修改msg的数据
// 注意点: 在react注册事件的时候,提供的事件处理函数的内部this指向undefined
// 没办法访问到this,没有办法访问到当前实例,没有办法访问到数据
// 如果想要修改react的状态,不能直接通过this.state.xxx去修改
this.setState({
msg: '呵呵'
})
}
}
ReactDOM.render(<Event />, document.getElementById('app'))
// bind方法: 任何一个函数,都有bind方法,bind方法可以用来修改函数内部的this指向
// call apply
// function fn(){} fn.bind(obj)
4、React事件-传参的问题
// 在注册事件的时候,能够传递参数
class Event extends React.Component {
constructor(props) {
super(props)
}
render() {
return (
<div>
<ul>
<li>
{/* 能够把id传递过来 */}
<button
onClick={() => {
this.clickFn(1)
}}
>
删除1
</button>
</li>
<li>
<button
onClick={() => {
this.clickFn(2)
}}
>
删除2
</button>
</li>
<li>
<button>删除3</button>
</li>
</ul>
</div>
)
}
// 传参第一种: 通过bind的方式进行传参,还想要获取事件对象, 事件对象是最后一个参数
// 参数第二种: 通过给事件处理程序包裹一个箭头函数
clickFn(id) {
console.log(id)
}
}
ReactDOM.render(<Event />, document.getElementById('app'))
5、React条件渲染
// 条件渲染: 根据不同的条件,渲染不同的内容
// react中的条件渲染,和js的if-else是完全一样
function UserGreeting() {
return <div>欢迎回来,尊贵的v12用户</div>
}
function GuestGreeting() {
return <div>你好,请先登录</div>
}
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
isLogin: false
}
}
// 完成了条件渲染,根据isLogin来渲染不同的内容
render() {
if (this.state.isLogin) {
return <UserGreeting />
} else {
return <GuestGreeting />
}
}
}
ReactDOM.render(<App />, document.getElementById('app'))
6、React条件渲染-元素变量
class Score extends React.Component {
constructor(props) {
super(props)
this.state = {
score: 90
}
}
render() {
// 可以使用变量来保存react的对象
let content = null
if (this.state.score >= 90) {
// 元素变量, 把一个react对象赋值给一个变量
content = <p>A</p>
} else if (this.state.score >= 80) {
content = <p>B</p>
} else if (this.state.score >= 70) {
content = <p>C</p>
} else if (this.state.score >= 60) {
content = <p>D</p>
} else {
content = <p>E</p>
}
return (
<div>
<h3>提示消息</h3>
<p>你本次的成绩是</p>
{content}
</div>
)
}
}
ReactDOM.render(<Score />, document.getElementById('app'))
7、React条件渲染-与运算符
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
score: 90,
age: 18
}
}
render() {
return (
<div>
<h3>提示消息</h3>
{/* 可以在{}中直接书写任意的js表达式 */}
{/* {this.state.age >= 18 && <div>成年人</div>}
{this.state.age < 18 && <div>未成年人</div>} */}
{this.state.age >= 18 ? <div>成年人</div> : <div>未成年人</div>}
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById('app'))
8、React条件渲染-阻止组件渲染
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
age: 18
}
}
render() {
if (this.state.age < 18) {
// render一旦return null 就不会渲染其他内容
return null
}
return (
<div>
<h3>提示消息</h3>
<p>以下内容特别劲爆,未成年人不允许观看</p>
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById('app'))
// 条件渲染
// 1. 使用if-else根据条件来渲染不同的组件
// 2. 可以使用变量以及if-else来决定组件显示的内容
// 3. && 三元表达式 return null
// react的条件渲染和js是完全一致的。
9、React列表渲染
class List extends React.Component {
constructor(props) {
super(props)
this.state = {
list: ['张飞', '赵云', '马超', '貂蝉']
}
}
render() {
let content = this.state.list.map((item, index) => (
<li key={index}>{item}</li>
))
return (
<div>
<h3>人物列表</h3>
<ul>
{/* 直接显示了一个数组 */}
{content}
</ul>
</div>
)
}
}
ReactDOM.render(<List />, document.getElementById('app'))
// react中无论是条件渲染或者是列表渲染,都在js
10、React列表渲染
class List extends React.Component {
constructor(props) {
super(props)
this.state = {
list: [
{ id: 1, name: 'zs', age: 18, gender: '男' },
{ id: 2, name: 'ls', age: 19, gender: '男' },
{ id: 3, name: 'ww', age: 20, gender: '女' }
]
}
}
render() {
// key只有在兄弟之间才有意义,应该唯一
let content = this.state.list.map(item => (
<tr key={item.id}>
<td>{item.id}</td>
<td>{item.name}</td>
<td>{item.age}</td>
</tr>
))
return (
<table>
<tbody>{content}</tbody>
</table>
)
}
}
ReactDOM.render(<List />, document.getElementById('app'))
// react中无论是条件渲染或者是列表渲染,都在js
11、React列表渲染-可以直接在Jsx中使用map
class List extends React.Component {
constructor(props) {
super(props)
this.state = {
list: [
{ id: 1, name: 'zs', age: 18, gender: '男' },
{ id: 2, name: 'ls', age: 19, gender: '男' },
{ id: 3, name: 'ww', age: 20, gender: '女' }
]
}
}
render() {
let content = this.state.list.map(item => (
<tr key={item.id}>
<td>{item.id}</td>
<td>{item.name}</td>
<td>{item.age}</td>
<td>{item.gender}</td>
</tr>
))
return (
<table>
<tbody>
{/* 可以直接在{}中遍历 */}
{content}
</tbody>
</table>
)
}
}
ReactDOM.render(<List />, document.getElementById('app'))
// react中无论是条件渲染或者是列表渲染,都在js
12、案例-评论列表
class Comment extends React.Component {
constructor(props) {
super(props)
// 添加状态
this.state = {
list: [
{ id: 1, name: '张三', content: '沙发' },
{ id: 2, name: '李四', content: '板凳' },
{ id: 3, name: '王五', content: '卖瓜子' },
{ id: 4, name: '赵六', content: '今天吃了没' }
]
}
}
render() {
return (
<div>
<h1>评论案例</h1>
<ul>
{this.state.list.map(item => (
<li key={item.id}>
<h3>
评论人:
{item.name}
</h3>
<p>
评论内容:
{item.content}
</p>
</li>
))}
</ul>
</div>
)
}
}
ReactDOM.render(<Comment />, document.getElementById('app'))
13、案例-评论列表-多组件
// 评论组件
class Comment extends React.Component {
constructor(props) {
super(props)
// 添加状态
this.state = {
list: [
{ id: 1, name: '张三', content: '沙发' },
{ id: 2, name: '李四', content: '板凳' },
{ id: 3, name: '王五', content: '卖瓜子' },
{ id: 4, name: '赵六', content: '今天吃了没' }
]
}
}
render() {
return (
<div>
<h1>评论案例</h1>
<ul>
{this.state.list.map(item => (
<Item key={item.id} data={item} />
))}
</ul>
</div>
)
}
}
// 评论项组件,没有状态,数据是父组件传递过来的
function Item(props) {
return (
<li>
<h3>
评论人:
{props.data.name}
</h3>
<p>评论内容 {props.data.content}</p>
</li>
)
}
ReactDOM.render(<Comment />, document.getElementById('app'))
14、案例-评论列表-React中如何设置样式
//react中设置样式,有两种方式
// 1. 给元素添加一个className, 设置一个类样式
// 2. 给元素添加一个style属性,通过style属性设置行内样式
// 在使用style给元素设置样式的时候,style={对象}
class Comment extends React.Component {
constructor(props) {
super(props)
// 添加状态
this.state = {
list: [
{ id: 1, name: '张三', content: '沙发' },
{ id: 2, name: '李四', content: '板凳' },
{ id: 3, name: '王五', content: '卖瓜子' },
{ id: 4, name: '赵六', content: '今天吃了没' }
],
bgColor: 'pink'
}
}
render() {
return (
<div style={{ backgroundColor: this.state.bgColor }}>
<h1>评论案例</h1>
<ul style={{ listStyle: 'none' }}>
{this.state.list.map(item => (
<Item key={item.id} data={item} />
))}
</ul>
</div>
)
}
}
// 评论项组件,没有状态,数据是父组件传递过来的
function Item(props) {
let liStyle = { height: 100 }
return (
<li style={liStyle}>
<h3>
评论人:
{props.data.name}
</h3>
<p>评论内容 {props.data.content}</p>
</li>
)
}
ReactDOM.render(<Comment />, document.getElementById('app'))
15、React表单
// react操作表单的元素,操作表单的目的: 获取到用户输入的内容
// react操作表单: 受控组件 非受控组件
// 受控组件: 在当前组件中的表单元素受到了react的控制,
//1. 当表单元素的内容发生改变,react对应的状态也要发生改变
//2. 当react对应的状态发生改变,表单元素的内容也要发生改变。
class Form extends React.Component {
constructor(props) {
super(props)
this.state = {
username: 'hello react'
}
}
render() {
// 一旦给input设置了value属性,value属性对应了组件中的一个状态,受控组件
// 表单元素的值受到了react的控制,我们发现,表单没办法输入,没办法改变了
// 除了指定一个vlaue属性,还需要指定onChange事件,用来处理内容的变化
return (
<input
type="text"
value={this.state.username}
onChange={this.handleChange}
/>
)
}
handleChange = e => {
// 我们需要改变 state.username的值
this.setState({
username: e.target.value
})
}
}
ReactDOM.render(<Form />, document.getElementById('app'))
16、React表单-受控组件-textarea
class Form extends React.Component {
constructor(props) {
super(props)
this.state = {
username: 'hello react',
content: '我是内容'
}
}
render() {
return (
<div>
<h3>input</h3>
<input
type="text"
value={this.state.username}
onChange={this.handleChange}
/>
<h3>textarea</h3>
<textarea
cols="30"
rows="10"
value={this.state.content}
onChange={this.handleContent}
/>
</div>
)
}
handleChange = e => {
// 我们需要改变 state.username的值
this.setState({
username: e.target.value
})
}
handleContent = e => {
// 获取到文本框的内容
this.setState({
content: e.target.value
})
}
}
ReactDOM.render(<Form />, document.getElementById('app'))
17、React表单-受控组件-select
class Form extends React.Component {
constructor(props) {
super(props)
this.state = {
username: 'hello react',
content: '我是内容',
city: 4
}
}
render() {
return (
<div>
<h3>input</h3>
<input
type="text"
value={this.state.username}
onChange={this.handleChange}
/>
<h3>textarea</h3>
<textarea
cols="30"
rows="10"
value={this.state.content}
onChange={this.handleContent}
/>
<h3>select</h3>
<select value={this.state.city} onChange={this.handleSelect}>
<option value="1">北京</option>
<option value="2">上海</option>
<option value="3">广州</option>
<option value="4">深圳</option>
</select>
</div>
)
}
handleChange = e => {
// 我们需要改变 state.username的值
this.setState({
username: e.target.value
})
}
handleContent = e => {
// 获取到文本框的内容
this.setState({
content: e.target.value
})
}
handleSelect = e => {
this.setState({
city: e.target.value
})
}
}
ReactDOM.render(<Form />, document.getElementById('app'))
18、React表单-受控组件-通用的处理程序
class Form extends React.Component {
constructor(props) {
super(props)
this.state = {
username: 'hello react',
content: '我是内容',
city: 4
}
}
render() {
return (
<div>
<h3>input</h3>
<input
type="text"
value={this.state.username}
onChange={this.handleChange}
name="username"
/>
<h3>textarea</h3>
<textarea
cols="30"
rows="10"
value={this.state.content}
onChange={this.handleChange}
name="content"
/>
<h3>select</h3>
<select
value={this.state.city}
onChange={this.handleChange}
name="city"
>
<option value="1">北京</option>
<option value="2">上海</option>
<option value="3">广州</option>
<option value="4">深圳</option>
</select>
</div>
)
}
handleChange = e => {
let name = e.target.name
// 我们需要改变 state.username的值
// es6的属性名表达式
this.state[name] = e.target.value
this.setState(this.state)
}
}
ReactDOM.render(<Form />, document.getElementById('app'))
19、React非受控组件
// 1. 在构造函数中,需要自己创建一个引用 ref
class Form extends React.Component {
constructor(props) {
super(props)
// 1. 创建ref
this.usernameRef = React.createRef()
this.buttonRef = React.createRef()
}
render() {
return (
<div>
{/* 2. 我们创建的ref可以 在组件的任意地方使用 */}
<input ref={this.usernameRef} type="text" />
<button ref={this.buttonRef} onClick={this.get}>
获取value值
</button>
</div>
)
}
get = () => {
// 获取input框的value值
// 受控组件: 我们把input框的value值交给react来处理
// 非受控组件: 我们需要手动的操作DOM,手动获取到DOM的value值
// refs: 用于操作DOM的
// 3. 通过this.usernameRef.current
console.log(this.usernameRef.current.value)
}
}
ReactDOM.render(<Form />, document.getElementById('app'))
20、图书管理案例-列表
class Book extends React.Component {
constructor(props) {
super(props)
this.state = {
list: [
{ id: 1, name: '红楼梦', desc: '一堆乱七八糟的破事' },
{ id: 2, name: '西游记', desc: '小时候的经典' },
{ id: 3, name: '权威指南', desc: 'js程序员必读' }
],
name: '',
desc: '',
id: '',
index: 3
}
}
render() {
return (
<div className="container">
<div className="form">
书名:
<input
type="text"
value={this.state.name}
onChange={this.handleChange}
name="name"
/>
描述:
<input
type="text"
value={this.state.desc}
onChange={this.handleChange}
name="desc"
/>
<button onClick={this.addBook}>添加</button>
</div>
<table>
<thead>
<tr>
<th>编号</th>
<th>书名</th>
<th>描述</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{this.state.list.map((item, index) => (
<tr key={item.id}>
<td>{index + 1}</td>
<td>{item.name}</td>
<td>{item.desc}</td>
<td>
<a href="#" onClick={this.delBook.bind(this, item.id)}>
删除
</a>
|
<a href="#" onClick={this.showEdit.bind(this, item)}>
修改
</a>
</td>
</tr>
))}
</tbody>
</table>
</div>
)
}
addBook = () => {
// 判断是否有id值,如果有,是修改,否则是添加
if (this.state.id) {
// 修改
// 根据id找到需要修改的下标
let idx = this.state.list.findIndex(item => item.id === this.state.id)
this.state.list[idx].name = this.state.name
this.state.list[idx].desc = this.state.desc
} else {
// 添加
// 添加图书
this.state.list.push({
id: ++this.state.index,
name: this.state.name,
desc: this.state.desc
})
}
// 清空name和desc
this.state.name = ''
this.state.desc = ''
this.state.id = ''
this.setState(this.state)
}
handleChange = e => {
let { name, value } = e.target
this.setState({
[name]: value
})
}
delBook(id, e) {
e.preventDefault()
// 删除需要id
// 根据id获取到下标
let idx = this.state.list.findIndex(item => item.id === id)
// 删除对应的数据
this.state.list.splice(idx, 1)
this.setState(this.state)
}
showEdit = (book, e) => {
e.preventDefault()
this.state.id = book.id
this.state.name = book.name
this.state.desc = book.desc
this.setState(this.state)
}
}
ReactDOM.render(<Book />, document.getElementById('app'))
(1)index.css
/* * {
margin: 0;
padding: 0;
}
.container {
background-color: pink;
}
.item {
border: 1px solid #000;
height: 100px;
} */
.container {
width: 600px;
}
table {
margin-top: 30px;
border: 1px solid blue;
border-collapse: collapse;
width: 100%;
}
table th,
table td {
border: 1px solid blue;
height: 50px;
line-height: 50px;
text-align: center;
}
(2)index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet" href="index.css">
</head>
<body>
<div id="app"></div>
<!-- 1. 引包 -->
<script src="lib/react.development.js"></script>
<script src="lib/react-dom.development.js"></script>
<script src="lib/babel.min.js"></script>
<!-- 如果想要引入一个外部的文件,不能使用file协议, http协议 -->
<!-- <script type="text/babel" src="01-react复习.js"></script> -->
<!-- <script type="text/babel" src="02-react事件.js"></script> -->
<!-- <script type="text/babel" src="03-react事件-this的问题.js"></script> -->
<!-- <script type="text/babel" src="04-react事件-传参的问题.js"></script> -->
<!-- <script type="text/babel" src="05-react条件渲染.js"></script> -->
<!-- <script type="text/babel" src="06-react条件渲染-元素变量.js"></script> -->
<!-- <script type="text/babel" src="07-react条件渲染-与运算符.js"></script> -->
<!-- <script type="text/babel" src="08-react条件渲染-阻止组件渲染.js"></script> -->
<!-- <script type="text/babel" src="11-react列表渲染-可以直接在jsx中使用map.js"></script> -->
<!-- <script type="text/babel" src="12-案例-评论列表.js"></script> -->
<!-- <script type="text/babel" src="13-案例-评论列表-多组件.js"></script> -->
<!-- <script type="text/babel" src="14-案例-评论列表-react中如何设置样式.js"></script> -->
<!-- <script type="text/babel" src="15-react表单.js"></script> -->
<!-- <script type="text/babel" src="16-react表单-受控组件-textarea.js"></script> -->
<!-- <script type="text/babel" src="17-react表单-受控组件-select.js"></script> -->
<!-- <script type="text/babel" src="19-react非受控组件.js"></script> -->
<script type="text/babel" src="20-图书管理案例-列表.js"></script>
</body>
</html>