掌握 react 的基础特性javascript
react.js 自己只是一个精简的类库,提供了几个特性或者说是工具,每一个话题深刻均可以长篇大论。css
我这里只关注使用,毕竟轮子造出来仍是用的,而不是观赏。html
个人理解 jsx 就是 html + 表达式
的混合体前端
( ... )
把 jsx 代码包含起来const Element1 = () => (<h2>组件1 - 常量</h2>)
这样写的理由java
固然新版里若是你单行能够省略
错误 let Element4 = () => { return ( <h2>组件4 - es6 箭头函数</h2> <h2>组件4 - es6 箭头函数</h2> ) } 正确 let Element4 = () => { return ( <div> <h2>组件4 - es6 箭头函数</h2> <h2>组件4 - es6 箭头函数</h2> </div> ) }
若是你只有一个标签,本身自己就是顶级标签,无需加
{ ... }
开始你的js表达式function ElementShow(props) { return ( <div> <p>字符串: {props.name} </p> <p>日期变量: {props.date.toLocaleTimeString()}</p> </div> ) }
分别打印 属性值、时间函数react
<div> <ElementProps /> </div>
结束符 /
git
codepenes6
https://codepen.io/ducafecat/...github
function ElementShow(props) { props.isShow = true // 只读不能修改 ...
打印截图编程
记忆就行,和咱们以前写 html 有些差别
我看着都是由于 js 中保留字关系
jsx | html |
---|---|
tabIndex | index |
className | class |
htmlFor | for |
示例
const ElementProps = () => ( <div tabIndex="0" className="divbg" > JSX 属性 tabIndex、className </div> )
camelCase
错误 <Foo UserName="hello" phone_number={12345678} /> 正确 <Foo userName="hello" phoneNumber={12345678} />
错误 <Foo hidden={true} /> 正确 <Foo hidden />
key
属性是怎么回事示例
<ul> {NavRoutes.map((route, index) => ( <li key={route.id}> {route.title} </li> ))} </ul>
若是不写呢
看来是绕不过的
总结
react利用key来识别组件,它是一种身份标识标识
同层的惟一就行,不用全局惟一
避免使用数组的index做为key
值
代码
const jsContent = ` <script type="text/javascript"> alert("JSX 防注入攻击!") </script>` const ElementInject = () => <div>{jsContent}</div>
打印
内容在渲染以前都被转换成了字符串,这样能够有效地防止 XSS(跨站脚本) 攻击
childen
表示子节点对象这个属性表示,当前组件嵌套的对象集合
render() { return( <RadioGroup> <RadioButton value="first">First</RadioButton> <RadioButton value="second">Second</RadioButton> <RadioButton value="third">Third</RadioButton> </RadioGroup> ) }
RadioGroup
的props.childen
就是这三个RadioButton
你可能会问这有什么用,咱们能够用来加工呀,各类循环、克隆、修改,固然我是不太推荐这样去修改 dom 对象
codepen
https://codepen.io/ducafecat/...
组件内部的数据管理对象,自动状态控制
有的同窗可能对 MVVM
比较了解,必定会说 React
怎么没有双向绑定
这可能就是设计思想问题了,不想给工具赋予过多负重,轻巧才灵活,下一章,我会经过一个函数解决双向绑定来处理表单操做,就几行代码
这里咱们仍是谈谈基础操做,懂得同窗能够 PASS
class ElementStateStatic extends Component { constructor(props) { super(props) this.state = {date: new Date()} } render() { return <p>初始时间 => {this.state.date.toLocaleString()}</p> } }
constructor
是组件构造函数,给this.state
初始值时 要用key/val
形式的对象
jsx
中使用时直接this.state.data
对象调用便可
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 <p>更新时间 => {this.state.date.toLocaleString()}</p> } }
须要使用
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前将会当即调用 新增 |
代码
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 <p>时间 => {this.state.date.toLocaleString()}</p> } }
打印截图
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
组件实例化后和接受新属性时将会调用
代码
// 组件 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 <p>{this.state.date.toLocaleString()}</p> } } // 调用 <ElementLifecycleNew date={new Date('2009-09-09 09:09:09')} />
若是你不想改变状态 state
, 返回 null
getSnapshotBeforeUpdate + componentDidUpdate
getSnapshotBeforeUpdate()
在最新的渲染输出提交给DOM前将会当即调用。它让你的组件能在当前的值可能要改变前得到它们。这一辈子命周期返回的任何值将会 做为参数被传递给componentDidUpdate()
。
// 代码 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 ( <div style={{ height: 200, width: 150, backgroundColor: 'blue', position: 'relative', color: '#fff' }} > <p>{this.state.date.toLocaleString()}</p> <div ref={this.listRef} style={{ height: 20, width: 150, backgroundColor: 'red', top: 0, position: 'absolute' }} /> </div> ) } } // 调用
这个例子的流程是:
1. `componentDidMount` 中修改了 state 触发 `getSnapshotBeforeUpdate` 2. `getSnapshotBeforeUpdate` 获取修改前的 属性、状态,已修改的 状态,而后一个修改值 `offset` 3. `componentDidUpdate` 中的 `snapshot` 获取修改值 ,直接 `ref` `dom` 修改 `style`
简单说就是不修改 state 更新机制,来维护
dom
,好比改改 宽 高 位置
在 react 里使用事件,写法不少,这里采用官方推荐的方式
handleChange(e) { ... }
class InputView extends Component { constructor(props) { ... this.handleChange = this.handleChange.bind(this) }
使用
bind(this)
方式
<input ... onChange={this.handleChange} />
handleChangeVal(val, e) { console.log(val) this.setState({value: e.target.value}) }
<input ... onChange={this.handleChangeVal.bind(this, '123')} />
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 ( <form onSubmit={this.handleSubmit} style={{display: 'inline-flex'}}> <input type="text" value={this.state.value} onChange={this.handleChange} /> <input type="text" value={this.state.value} onChange={this.handleChangeVal.bind(this, '123')} /> <input type="submit" value="提交" /> <p>{this.state.value}</p> </form> ) } }
codepen
https://codepen.io/ducafecat/...
有两种方式维护样式
import
样式文件base.css
样式文件.bg { background-color: rgb(101, 40, 241); color: white; font-weight: 500; }
.js
中引入import './base.css'
style
style
对象const styles = {} styles.fill = { position: 'relative', height: '200px', width: '500px' } ...
<div style={styles.fill}>...
<div style={{ ...styles.fill, ...styles.hsl, background: `hsl(${params.h}, ${params.s}%, ${params.l}%)` }} >
能够发现这样的写法,对编程控制样式仍是颇有用的