JSX
React 是怎么解析JSX語(yǔ)法的寝衫?
要提出兩個(gè)方法
react.createElement
這里有三個(gè)入?yún)ⅲ?code>type, config
, children
type
: dom的類(lèi)型烦周,如div
config
: dom的屬性,如style={{color: #fff}}
// 給props賦值config
for (propName in config) {
if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {
props[propName] = config[propName];
}
}
children
:當(dāng)前dom的子元素,可能有多個(gè),也可能沒(méi)有。
源碼中用var childrenLength = arguments.length - 2;
來(lái)計(jì)算子元素的個(gè)數(shù)
var childrenLength = arguments.length - 2; // 計(jì)算子元素的個(gè)數(shù)
if (childrenLength === 1) {
props.children = children;
} else if (childrenLength > 1) {
var childArray = Array(childrenLength);
for (var i = 0; i < childrenLength; i++) {
childArray[i] = arguments[i + 2];
}
{
if (Object.freeze) {
Object.freeze(childArray); // 凍結(jié)子元素
}
}
props.children = childArray; // 將children賦值給props
}
打印出一個(gè)virtual dom
image.png
react.createElement源碼
function createElement(type, config, children) {
var propName; // Reserved names are extracted
var props = {};
var key = null;
var ref = null;
var self = null;
var source = null;
if (config != null) {
if (hasValidRef(config)) {
ref = config.ref;
{
warnIfStringRefCannotBeAutoConverted(config);
}
}
if (hasValidKey(config)) {
key = '' + config.key;
}
self = config.__self === undefined ? null : config.__self;
source = config.__source === undefined ? null : config.__source; // Remaining properties are added to a new props object
for (propName in config) {
if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {
props[propName] = config[propName];
}
}
} // Children can be more than one argument, and those are transferred onto
// the newly allocated props object.
var childrenLength = arguments.length - 2;
if (childrenLength === 1) {
props.children = children;
} else if (childrenLength > 1) {
var childArray = Array(childrenLength);
for (var i = 0; i < childrenLength; i++) {
childArray[i] = arguments[i + 2];
}
{
if (Object.freeze) {
Object.freeze(childArray);
}
}
props.children = childArray;
} // Resolve default props
if (type && type.defaultProps) {
var defaultProps = type.defaultProps;
for (propName in defaultProps) {
if (props[propName] === undefined) {
props[propName] = defaultProps[propName];
}
}
}
{
if (key || ref) {
var displayName = typeof type === 'function' ? type.displayName || type.name || 'Unknown' : type;
if (key) {
defineKeyPropWarningGetter(props, displayName);
}
if (ref) {
defineRefPropWarningGetter(props, displayName);
}
}
}
return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);
}
reactDom.render()
將JSX 翻譯為 html燎竖。
ReactDOM.render(
<div>
<input type="text" style={inputStyle} value={value}/>
<button>{buttonName}</button>
</div>,
document.getElementById("container")
)
diff算法
tree
逐層比較,不會(huì)移動(dòng)要销,遇到不同只會(huì)刪除和創(chuàng)建
component
組件差異性比較底瓣,不會(huì)移動(dòng),遇到不同只會(huì)刪除和創(chuàng)建
element (key)
可以根據(jù)key移動(dòng)/添加/刪除蕉陋,只會(huì)對(duì)老的節(jié)點(diǎn)做向后移的操作
diff算法
為什么不建議用index做key
key
的作用,如果key相同拨扶,則只會(huì)對(duì)比改變屬性凳鬓,反之,key不同患民,會(huì)卸載并重新加載缩举。
<ul>
<li key = "0">松子</li>
<li key = "1">開(kāi)心果</li>
<li key = "2">核桃</li>
</ul>
如果上述列表順序發(fā)生變化,但若用index做key匹颤,實(shí)際index不會(huì)發(fā)生變化:
<ul>
<li key = "0">開(kāi)心果</li>
<li key = "1">核桃</li>
<li key = "2">松子</li>
</ul>
如遇到非受控組件仅孩,則如果向數(shù)組頭部添加元素,會(huì)導(dǎo)致value回顯錯(cuò)誤印蓖。
<ul>
{demo.map(((it, index)=>{
return <input key={index}></input>
}))}
</ul>
<Button onClick={()=>setDemo(["girl"].concat(demo))}>交換</Button>
reactkey.gif