Agenda
- JSX In Depth
- Booleans, Null, and Undefined Are Ignored
- Typechecking With PropTypes
- Refs and the DOM
- Context
Agenda
- JSX In Depth
- Booleans, Null, and Undefined Are Ignored
- Typechecking With PropTypes
- Refs and the DOM
- Context
JSX In Depth
Props Default to "True"
傳遞一個(gè)沒有值的屬性圆兵,其默認(rèn)值是true
<MyTextBox autocomplete />
//is equal
<MyTextBox autocomplete={true} />
<MyTextBox autocomplete/>
console.log(this.props.autocomplete)
// true
<MyTextBox />
console.log(this.props.autocomplete)
// undefined
Spread Attributes
const Component1 = () => {
return <Greeting firstName="Ben" lastName="Hector" />
}
const Component2 = () => {
const props = {firstName: 'Ben', lastName: 'Hector'}
return <Greeting {...props} />;
}
高效但是混亂
We recommend that you use this syntax sparingly.
String Literals
自動(dòng)刪除行首/末位空格坎弯,刪除空行
<div>Hello World</div>
<div>
Hello World
</div>
<div>
Hello
World
</div>
<div>
Hello World
</div>
Booleans, Null, and Undefined Are Ignored
Booleans(false & true), null, undefined都是合法值
<div />
<div></div>
<div>{false}</div>
<div>{null}</div>
<div>{true}</div>
全部 render null
const messages = []
<div>
{messages.length &&
<MessageList messages={messages} />
}
</div>
number '0'不會(huì)被轉(zhuǎn)化為 false
<div>
{messages.length > 0 &&
<MessageList messages={messages} />
}
</div>
確保在&&前面的是booleans
若要顯示‘false & true, null, undefined’渴逻,需轉(zhuǎn)換為 string
<div>
My JavaScript variable is {String(myVariable)}.
</div>
Typechecking With PropTypes
我經(jīng)常使用的 PropTypes
MyComponent.propTypes = {
optionalArray: React.PropTypes.array,
optionalBool: React.PropTypes.bool,
optionalFunc: React.PropTypes.func,
optionalNumber: React.PropTypes.number,
optionalObject: React.PropTypes.object,
optionalString: React.PropTypes.string,
optionalSymbol: React.PropTypes.symbol,
}
限制在枚舉的數(shù)組中
optionalEnum: React.PropTypes.oneOf(['News', 'Photos'])
限制在多個(gè)類型中
optionalUnion: React.PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.number,
React.PropTypes.instanceOf(Message)
])
限定數(shù)組中 value 的類型
optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number)
限定對(duì)象中 value 的類型
optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number)
限定數(shù)據(jù)結(jié)構(gòu)
optionalObjectWithShape: React.PropTypes.shape({
color: React.PropTypes.string,
fontSize: React.PropTypes.number
})
shape只能用在對(duì)象中
optionalObjectWithShape: React.PropTypes.shape({
colors: React.PropTypes.shape({
backgroundColor: React.PropTypes.string.isRequired
})
自定義一個(gè)validator,異常情況 return Error 對(duì)象
customProp: (props, propName, componentName) => {
if (!/matchme/.test(props[propName])) {
return new Error(
'Invalid prop `' + propName + '` supplied to' +
' `' + componentName + '`. Validation failed.'
)
}
}
可以用箭頭函數(shù)
自定義arrayOf
和 objectOf
customArrayProp: React.PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) {
console.log('location', location)
//location prop
console.log('propFullName', propFullName)
//propFullName customArrayProp[0]
})
遍歷每一個(gè)元素
Default Prop Values
會(huì)不會(huì)報(bào)錯(cuò)?
class Greeting extends React.Component {
static propTypes = {
name: PropTypes.string.isRequired
}
static defaultProps = {
name: 'Stranger'
}
render() {
return (
<h1>Hello, {this.props.name}</h1>
)
}
}
propTypes類型檢查在defaultProps賦值后進(jìn)行
Refs and the DOM
The ref Callback Attribute
ref 屬性可以接受一個(gè)回調(diào)函數(shù)
并且在組件mounted和unmounted時(shí)立即調(diào)用
回調(diào)函數(shù)的參數(shù)是該 DOM element鲫骗,unmounted的時(shí)候是 null
class CustomTextInput extends React.Component {
constructor(props) {
super(props)
this.handleFocus = this.handleFocus.bind(this)
}
handleFocus() {
this.textInput.focus()
}
render() {
return (
<div>
<input
type="text"
ref={(input) => { this.textInput = input }}
/>
<input
type="button"
value="Focus the text input"
onClick={this.handleFocus}
/>
</div>
)
}
}
class AutoFocusTextInput extends React.Component {
componentDidMount() {
this.customTextInput.handleFocus()
}
render() {
return (
<CustomTextInput
ref={(customTextInput) => { this.customTextInput = customTextInput }}
/>
)
}
}
class CustomTextInput extends React.Component {
handleFocus() {
this.textInput.focus()
}
render() {
return (
<input
ref={(input) => { this.textInput = input}
/>
)
}
}
Functional components
函數(shù)式組件织阳,需要提前聲明
function CustomTextInput(props) {
// textInput must be declared here so the ref callback can refer to it
let textInput = null
function handleClick() {
textInput.focus()
}
return (
<div>
<input
type="text"
ref={(input) => { textInput = input; }} />
<input
type="button"
value="Focus the text input"
onClick={handleClick}
/>
</div>
)
}
Don't Overuse Refs
Reconciliation
The Diffing Algorithm
Elements Of Different Types
<div>
<Counter />
</div>
<span>
<Counter />
</span>
這里的<Counter />
是一個(gè)完全新的組件,舊的狀態(tài)都將清除
當(dāng)根元素類型變化填帽,毀掉舊的樹蛛淋,創(chuàng)建新的樹
包含在樹里的組件會(huì)被卸載,所有狀態(tài)清空
DOM Elements Of The Same Type
<div className="before" title="stuff" />
<div className="after" title="stuff" />
類型相同篡腌,只更新屬性
<div style={{color: 'red', fontWeight: 'bold'}} />
<div style={{color: 'green', fontWeight: 'bold'}} />
只更新 color褐荷,不更新 fontWeight
Recursing On Children
<ul>
<li>first</li>
<li>second</li>
</ul>
<ul>
<li>first</li>
<li>second</li>
<li>third</li>
</ul>
在末尾添加,前面的不會(huì)重新渲染
<ul>
<li> first </li>
<li> second </li>
</ul>
<ul>
<li> third </li>
<li> first </li>
<li> second </li>
</ul>
更新所有<li>
[slide]
{:&.bounceIn}
Keys
<ul>
<li key="2015">Duke</li>
<li key="2016">Villanova</li>
</ul>
<ul>
<li key="2014">Connecticut</li>
<li key="2015">Duke</li>
<li key="2016">Villanova</li>
</ul>
添加 key嘹悼,更加高效
key 只需在兄弟節(jié)點(diǎn)中唯一
Context
Why Not To Use Context
如果希望穩(wěn)定叛甫,一定不要用 context。
這是一個(gè)實(shí)驗(yàn)性 API杨伙,可能會(huì)在后續(xù)版本中移除
How To Use Context
不用 context 其监,組件結(jié)構(gòu)如下:
class Button extends React.Component {
render() {
return (
<button style={{background: this.props.color}}>
{this.props.children}
</button>
)
}
}
class Message extends React.Component {
render() {
return (
<div>
{this.props.text} <Button color={this.props.color}>Delete</Button>
</div>
)
}
}
class MessageList extends React.Component {
render() {
const color = "purple";
const children = this.props.messages.map((message) =>
<Message text={message.text} color={color} />
)
return <div>{children}</div>
}
}
使用 context傳遞 props
class Button extends React.Component {
render() {
return (
<button style={{background: this.context.color}}>
{this.props.children}
</button>
)
}
}
Button.contextTypes = {
color: React.PropTypes.string
}
class Message extends React.Component {
render() {
return (
<div>
{this.props.text} <Button>Delete</Button>
</div>
)
}
}
class MessageList extends React.Component {
getChildContext() {
return {color: "purple"}
}
render() {
const children = this.props.messages.map((message) =>
<Message text={message.text} />
)
return <div>{children}</div>
}
}
添加childContextTypes 和 getChildContext
如果未定義contextTypes,context是一個(gè)空對(duì)象