jsx的使用
let data=123;
ReactDOM.render(<div>
<h2>hello</h2>
<p>{data}</p>
<Child/>
</div>,
document.querySelector("#root")
- 注意事项
- {}
中括号中可以放js表达式 不能放对象(会报错),数组中的项也不能是对象 可以放函数,但函数执行需要有返回值(否则报错)
- 循环绑定
let arr=['a','b','c','d'] ReactDOM.render(<ul> { arr.map((item,index)=>{//如果{}中是个函数的话 函数执行必须要有返回值,否则会报错。 return <li key={index}>{item}</li> }) } </ul>,root)
let arr=[<div>hello</div>,<div>world</div>,<p>haha</p>] ReactDOM.render(<ul> {=arr} </ul>,root)
- 判断(需要使用三元运算符)
let data={show:true}; ReactDOM.render(<div>{data.show?123:''}</div>,root)
- className代替class
ReactDOM.render(<div className={class1}>123</div>,root)
- style
orReactDOM.render(<div style={{color:red}}>123</div>,root)
5.只能有一个顶级元素let style1={color:red} ReactDOM.render(<div style={style1}>123</div>,root)
jsx语法中只能有一个顶级标签(元素)这和react的diff算法相关
- false,null,undefined,和 true 都是有效的的 children(子元素) 。但是并不会被渲染,下面的JSX表达式渲染效果是相同的,都是空
<div /> <div></div> <div>{false}</div> <div>{null}</div> <div>{undefined}</div> <div>{true}</div> </div>
- label的for属性用htmlFor代替
ReactDOM.render(<label htmlFor="name" ></label>,root)
jsx的编译过程
- 有 JSX 的地方,在文件开头就需要引入 React,因为实际上 JSX 是使用了 React.createElement,JSX 只是一个JS 的语法糖,所以需要引入 React 包,否则会报错。
- react-dom 是一个把React 代码渲染到网页端的包,主要利用了render函数。
- 示例:babel编译jsx
ReactDom.render(<ul className="list">
<li className="item">a</li>
<li className="item">b</li>
</ul>,root)
//转化为
createElement('ul',{className:'item'},[
createElement('li',{class:'item'},['a']),
createElement('li',{class:'item'},['b']),
])
-
createElement函数的实现
createElement执行会把jsx转化成为一个虚拟DOM,就是一个对象
vertualDom <==>
{
type:'ul',
props:{class:'list',children:[
{
type:'li',
props:{class:'item',children:'a'},
key:null,
ref:null
},
{
type:'li',
props:{class:'item',children:'b'},
key:null,
ref:null
},
]},
key:null,
ref:null
}
实现
//函数接受三个参数type,props,children,产出一个虚拟DOM对象
//如果props中有ref或key,就把ref或key放到外边,props中的ref或key为undefined,否则外边的ref或key为null;
//如果有childs,就把childs放到props的children上,如果childs只有一个,就是一个字符串,否租就是一个数组
function createElement(type,props,...childs){
props=props||{}
let ref=null,key=null;
if(ref in props){
ref=props.ref;
props.ref=undefined;
}else{
ref=null;
}
if(key in props){
key =props.key ;
props.key =undefined;
}else{
key =null;
}
let obj={
type,
props:{
...props,
//如果没有childs就是"",如果有一项就是一个字符串,如果有多项就是一个数组
children:childs.length<=1?(childs[0]||''):childs
},
key,
ref,
}
return obj;
}
-
render函数的实现
render将createElement中传出的虚拟DOM转化为真实的DOM,挂载到页面上
//函数传入虚拟DOM,容器和执行结束后的回调函数
function render(objJSX,container,callback){
let {type,props}=objJSX;
let newElement=document.createElement(type);
for(let attr in props){
let value=props[attr];
if(props.hasOwnProperty(attr))break;
if(typeof value=='undefined')break;
if(attr.startsWith('on')){//事件处理
let attch=attr.slice(2).toLowerCase();
newElement.addEventListener(attch,value,false);
continue;
}
switch(attr.toUpperCase){
case 'CLASSNAME'://class特殊处理
newElement.className=value;
break;
case 'STYLE'://style特殊处理
for(let st in attr){
newElement.style[st]=attr[st]
}
break;
case 'CHILDREN'://children特殊处理
!value intenceof Array?value =[value ]:null;//不是数组变成数组
value.forEach((item)=>{
if(typeof item=='string'){//是个字符串,直接插入
newElement.appendChild(document.createTextNode(item))
}else{//是一个对象,递归调用
render(item,newElement)
}
})
break;
default://普通属性
newElement.setAttribute(attr,value);
}
}
container.appendChild(newElement);
callback&&callback();
}