掌握 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}%)` }} >
能夠發現這樣的寫法,對編程控制樣式仍是頗有用的