目录
React 快速上手 – 04 基础特性 JSX、Props、State、Lifecycle、Event、Style
- 01 前言
- 02 开发环境搭建
- 03 脚手架创建项目 一切都是组件
- 04 基础特性 JSX、Props、State、Lifecycle、Event、Style
- 05 组件渲染控制
- 06 容器组件、展示组件
- 07 前端路由 react-router
- 08 状态管理 react-redux
- 09 数据请求 fetch
- 10 属性类型检查 prop-types
掌握 react 的基础特性
react.js 本身只是一个精简的类库,提供了几个特性或者说是工具,每个话题深入都可以长篇大论。
我这里只关注使用,毕竟轮子造出来还是用的,而不是观赏。
我的理解 jsx 就是 html + 表达式
的混合体
( ... )
把 jsx 代码包含起来const Element1 = () => (
组件1 - 常量
)
这样写的理由
当然新版里如果你单行可以省略
错误
let Element4 = () => {
return (
组件4 - es6 箭头函数
组件4 - es6 箭头函数
)
}
正确
let Element4 = () => {
return (
组件4 - es6 箭头函数
组件4 - es6 箭头函数
)
}
如果你只有一个标签,自己本身就是顶级标签,无需加
{ ... }
开始你的js表达式字符串: {props.name} 日期变量: {props.date.toLocaleTimeString()}function ElementShow(props) {
return (
)
}
分别打印 属性值、时间函数
结束符 /
codepen
https://codepen.io/ducafecat/…
function ElementShow(props) {
props.isShow = true // 只读不能修改
...
打印截图
记忆就行,和我们之前写 html 有些差异
我看着都是因为 js 中保留字关系
jsx | html |
---|---|
tabIndex | index |
className | class |
htmlFor | for |
示例
const ElementProps = () => (
JSX 属性 tabIndex、className
)
camelCase
错误
phone_number={12345678}
/>
正确
phOneNumber={12345678}
/>
错误
/>
正确
/>
key
属性是怎么回事示例
{NavRoutes.map((route, index) => (
{route.title}
))}
如果不写呢
看来是绕不过的
总结
react利用key来识别组件,它是一种身份标识标识
同层的唯一就行,不用全局唯一
避免使用数组的index作为
key
值
代码
const jsCOntent= `
`
const ElementInject = () =>
打印
内容在渲染之前都被转换成了字符串,这样可以有效地防止 XSS(跨站脚本) 攻击
childen
表示子节点对象这个属性表示,当前组件嵌套的对象集合
render() {
return(
)
}
RadioGroup
的
props.childen
就是这三个
RadioButton
你可能会问这有什么用,我们可以用来加工呀,各种循环、克隆、修改,当然我是不太推荐这样去修改 dom 对象
codepen
https://codepen.io/ducafecat/…
组件内部的数据管理对象,自动状态控制
有的同学可能对 MVVM
比较了解,一定会说 React
怎么没有双向绑定
这可能就是设计思想问题了,不想给工具赋予过多负重,轻巧才灵活,下一章,我会通过一个函数解决双向绑定来处理表单操作,就几行代码
这里我们还是谈谈基础操作,懂得同学可以 PASS
初始时间 => {this.state.date.toLocaleString()}class ElementStateStatic extends Component {
constructor(props) {
super(props)
this.state = {date: new Date()}
}
render() {
return
}
}
constructor
是组件构造函数,给
this.state
初始值时 要用
key/val
形式的对象
jsx
中使用时直接
this.state.data
对象调用即可
更新时间 => {this.state.date.toLocaleString()}class ElementStateUpdate extends Component {
constructor(props) {
super(props)
this.date = props.date
this.state = {date: new Date()}
}
componentDidMount() {
if (this.date !== undefined) {
// 传值方式
this.setState({date: this.date})
// 函数方式
// this.setState((state, props) => {
// return {date: this.date}
// })
}
}
render() {
return
}
}
需要使用
this.setState
函数设置
简单操作,直接 传入 key / value
的对象
state
或者组件属性 props
,需要写成this.setState((state, props) => {
let date = state.data
date = date.addDay(10)
return {date}
})
codepen
https://codepen.io/ducafecat/…
状态 | 说明 |
---|---|
Mount | 已插入真实 DOM |
Update | 正在被重新渲染 |
Unmount | 已移出真实 DOM |
状态 | 说明 |
---|---|
componentDidMount | 在第一次渲染后调用,只在客户端。 |
shouldComponentUpdate | 返回一个布尔值。在组件接收到新的props或者state时被调用。 |
componentDidUpdate | 在组件完成更新后立即调用。在初始化时不会被调用。 |
componentWillUnmount | 在组件从 DOM 中移除的时候立刻被调用。 |
getDerivedStateFromProps | 组件实例化后和接受新属性时将会调用 新增 |
getSnapshotBeforeUpdate | 在最新的渲染输出提交给DOM前将会立即调用 新增 |
代码
时间 => {this.state.date.toLocaleString()}class ElementLifecycle extends Component {
constructor(props) {
super(props)
this.date = props.date
this.state = {date: this.date}
}
componentDidMount() {
console.log('componentDidMount 在第一次渲染后调用')
if (this.date !== undefined) {
this.setState({date: this.date})
}
}
shouldComponentUpdate(nextProps, nextState) {
console.log(
'shouldComponentUpdate 在组件接收到新的props或者state时被调用',
nextProps,
nextState
)
return true // 返回一个布尔值,大家可以试着在这里返回 false
}
componentDidUpdate(prevProps, prevState) {
console.log(
'componentDidUpdate 在组件完成更新后立即调用',
prevProps,
prevState
)
}
componentWillUnmount() {
console.log('componentWillUnmount 在组件从 DOM 中移除的时候立刻被调用')
}
render() {
return
}
}
打印截图
codepen
https://codepen.io/ducafecat/…
react 16.x
新版本变动分别是 componentWillMount
, componentWillReceiveProps
, componentWillUpdate
理由是在新的升级中,存在漏洞(在Facebook上,他们维护了超过50,000个React组件。 )
注意:
弃用警告将在未来的16.x版本中启用,但旧版生命周期将继续运行至17.x版。
即使在17.x版中,仍然可以使用它们,但它们会以『UNSAFE_』为前缀被重命名,以表明它们可能会引起问题。我们还准备了一个自动化的脚本来在现有代码中对它们重新命名。
UNSAFE_componentWillMount()
UNSAFE_componentWillReceiveProps()
UNSAFE_componentWillUpdate()
getDerivedStateFromProps
组件实例化后和接受新属性时将会调用
代码
{this.state.date.toLocaleString()}// 组件
class ElementLifecycleNew extends Component {
constructor(props) {
super(props)
this.state = {}
}
static getDerivedStateFromProps(nextProps, prevState) {
console.log(
'getDerivedStateFromProps 组件实例化后和接受新属性时将会调用',
nextProps,
prevState
)
// return null // 无需改变 返回 null
return {
date: new Date('2011-11-11 11:11:11')
}
}
render() {
return
}
}
// 调用
如果你不想改变状态 state
, 返回 null
getSnapshotBeforeUpdate + componentDidUpdate
getSnapshotBeforeUpdate()
在最新的渲染输出提交给DOM前将会立即调用。它让你的组件能在当前的值可能要改变前获得它们。这一生命周期返回的任何值将会 作为参数被传递给
componentDidUpdate()
。
{this.state.date.toLocaleString()} 这个例子的流程是: 简单说就是不修改 state 更新机制,来维护 在 react 里使用事件,写法很多,这里采用官方推荐的方式 使用 {this.state.value} codepen https://codepen.io/ducafecat/… 有两种方式维护样式 可以发现这样的写法,对编程控制样式还是很有用的 © 会煮咖啡的猫咪// 代码
class ElementLifecycleNew2 extends Component {
listRef = React.createRef()
constructor(props) {
super(props)
this.state = {
date: props.date
}
}
componentDidMount() {
console.log('componentDidMount')
this.setState({date: new Date('2011-11-22 22:22:22')})
}
getSnapshotBeforeUpdate(prevProps, prevState) {
console.log('getSnapshotBeforeUpdate', prevProps, prevState, this.state)
return {
offset: 80
}
}
componentDidUpdate(prevProps, prevState, snapshot) {
console.log('componentDidUpdate', snapshot)
this.listRef.current.style.top = `${snapshot.offset}px`
}
render() {
return (
position: 'relative',
color: '#fff'
}}
>
red',
top: 0,
position: 'absolute'
}}
/>
)
}
}
// 调用1. `componentDidMount` 中修改了 state 触发 `getSnapshotBeforeUpdate`
2. `getSnapshotBeforeUpdate` 获取修改前的 属性、状态,已修改的 状态,然后一个修改值 `offset`
3. `componentDidUpdate` 中的 `snapshot` 获取修改值 ,直接 `ref` `dom` 修改 `style`
dom
,比如改改 宽 高 位置5. 事件 Event
5.1 无参数传递
handleChange(e) {
...
}class InputView extends Component {
constructor(props) {
...
this.handleChange = this.handleChange.bind(this)
}
bind(this)
方式 ...
OnChange={this.handleChange}
/>5.2 有参数传递
handleChangeVal(val, e) {
console.log(val)
this.setState({value: e.target.value})
} ...
OnChange={this.handleChangeVal.bind(this, '123')}
/>5.3 例子
class InputView extends Component {
constructor(props) {
super(props)
this.state = {value: ''}
this.handleChange = this.handleChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
}
handleChange(e) {
this.setState({value: e.target.value})
}
handleChangeVal(val, e) {
console.log(val)
this.setState({value: e.target.value})
}
handleSubmit(e) {
e.preventDefault() // 阻止事件
console.log('handleSubmit')
}
render() {
return (
type="text"
value={this.state.value}
OnChange={this.handleChange}
/>
type="text"
value={this.state.value}
OnChange={this.handleChangeVal.bind(this, '123')}
/>
)
}
}6. 样式 Style
6.1
import
样式文件base.css
样式文件.bg {
background-color: rgb(101, 40, 241);
color: white;
font-weight: 500;
}.js
中引入import './base.css'
6.2 直接编写
style
style
对象const styles = {}
styles.fill = {
position: 'relative',
height: '200px',
width: '500px'
}
...
...styles.fill,
...styles.hsl,
background: `hsl(${params.h}, ${params.s}%, ${params.l}%)`
}}
>本文代码
参考
微信 ducafecat
镜像 Git
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有