JSX是什么?
既不是字符串也不是 HTML,是一种类似 XML 的语法标签,不能直接在浏览器运行,他是通过各种编译器编译成Js标准可执行的语法。
JSX使用规则
- 代码块(以 { 开头),就用JavaScript规则解析。
- (以 < 开头)标签,就用HTML规则解析;
- 用小骆驼峰定义属性名称
- 自定义属性 data-[属性名称]
JSX怎么编译的
解析
JSX 不是标准的Javascript代码它需要babel-preset-react-app语法解析包解析成Javascript可识别的代码,把jsx语法标签转义成
React.createElement()方法调用。
const element = (
<div className="my-class" >JSX语法标签</div>
);
babel 转义成:
const element = React.createElement(
'div', // type 标签
{className:'my-class'}, // props 属性
'JSX语法标签' // children 内容
);
生成虚拟DOM
React.createElement 将转化成为一个虚拟DOM,也就是一个对象。
const jsxObj = {
type: 'div', // 存储的是标签名或者组件名
props: { // props: 属性对象(给当前元素设置的属性都在这里)(如果有子元素,会多一个children属性,依次把子元素传递进来,没有就没有children属性)
style: '',
className: 'my-class',
children: 'JSX语法标签' // 可能有可能没有,有的话:可能是一个数组,也可能是一个字符串或者是一个对象。
},
key: null,
ref: null
}
生成真实DOM
render 原理是将 jsx 生成的对象生成
'type'类型的 DOM 元素,把属性'props'遍历追加到DOM上面,例如类名className,style,children...,然后 挂载在指定的容器上。
下面是自定义的一个 render函数:
function render(jsxObj, container,callback){
let {type,props} = jsxObj;
// 创建一个dom
let element = document.createElement(type);
for(let key in props){
_props = props[key];
if(element.hasOwnProperty(key))break;
if(typeof _props=='undefined')break;
// 事件监听
if(key.startsWith('on')){
let attch= key.slice(2).toLowerCase();
element.addEventListener(attch, _props, false);
continue;
}
key = key.toUpperCase();
switch (key){
case 'CHILDREN':
// 判断是否有子dom
if (typeof _props === "string"){
element.innerText = _props
}else {
// 递归
for(let children in _props){
render(children,element)
}
}
break;
case 'STYLE':
let _style = Object.keys(_props).map((name)=>{
let value = _props[name];
return `${name}:${value}`;
}).join(';');
element.setAttribute('style', _style)
break;
case 'CLASSNAME':
element.setAttribute('class', _props)
break;
default:
// 其它属性
break;
}
}
container.appendChild(element);
callback&&callback();
}
注意事项
- 属性名称是小驼峰命名
- jsx语法中只能有一个顶级标签(元素)
- 使用组件时,首字母必须大写
- jsx表达式不能使用if else(可以使用三元运算符)
- 调用的方法会指向 undefined, 其实就是this指向的问题了
这不是React bug,这是JavaScript中本来就有的。如果你传递一个函数名给一个变量,然后通过在变量后加括号()来调用这个方法,
const obj = {
title: 'JSX',
func:function(){
console.log(this)
}
}
obj.func(); // this指向obj
let funcb = obj.func
funcb(); // this指向window
JSX优点
- JSX执行更快
- 更安全防止注入攻击,编译时能及时发现错误
- 便于开发着阅览,编写模板更加简单快速