JSX是什么
实际上, JSX 仅仅只是 React.createElement(component, props, …children) 函数的语法糖
JSX
能够提供给我们在JavaScript代码中编写HTML
标签的能力
这样做的好处:
- 将
HTML
代码片段可以当做变量任意地进行赋值、传递和计算等操作,在使用上更加地灵活; - 使得结构(视图层
HTML
)与行为(逻辑层JS
)相统一,都在同一个文件、函数中处理,编写、维护和复用更加地方便和高效
以上仅个人见解
如下的代码:
function hello() {
return <h1 className="title" title="hello">Hello world</h1>
}
会被编译为:
function hello() {
return React.createElement("h1", {
className: "title",
title: "hello"
}, "Hello world");
}
尝试其他JSX转换类型,可以在线Babel测试
React.createElement
- 参数1 - 指定生成的标签名称
- 参数2 - 对象,标签的属性
- 参数3、4、5… - 子节点
function hello() {
return
<ul>
<li>1</li>
<li>1</li>
<li>1</li>
</ul>
}
// 编译为
function hello() {
return React.createElement(
"ul",
null,
React.createElement("li", null, "1"),
React.createElement("li", null, "1"),
React.createElement("li", null, "1")
);
}
不需要太了解编译后的函数,写好JSX
表达式就好了
指定React元素类型
确定是组件
JSX
转换程序会将以小写字母开头的标签当做普通的HTML
元素去创建,而大写字母开头的标签会当做组件处理,在作用域内寻找相应的变量,继而渲染、创建HTML
元素
当返回一个普通的JSX HTML
标签时,React.createElement
会直接创建相应的标签
export default function Home() {
return (
<>
<h1> {props.text} </h1>
</>
)
}
当返回一个组件的时候
- 要确保该组件变量在作用域内
- 函数组件:返回
JSX
表达式;类组件:具有render()
方法
export default function Home() {
return (
<>
<Hello text="Hello World" />
</>
)
}
或者:
function Hello (props) {
return <h1> {props.text} </h1>
}
function WhoAmI (props) {
return <h1> {props.name} </h1>
}
const MyComponents = {
Hello,
WhoAmI,
}
export default function Home() {
return (
<>
<MyComponents.Hello text="Hello World" />
<MyComponents.WhoAmI name="Lucy" />
</>
)
}
运行时确定组件
需要注意的是,JSX
表达式的组件名称不能是一个属性计算表达式,像这样:
export default function Home() {
return (
<>
// 错误!不能如此访问
<MyComponents['Hello'] text="Hello World" />
</>
)
}
可以先使用一个变量接收,修改为如此:
export default function Home() {
const Hello = MyComponents['Hello']
return (
<>
<Hello text="Hello World" />
</>
)
}
JSX
属性传递
JSX
属性传递有多重方式:
字面量。字符串基本数据类型,可以直接作为props
传递,如:
<Hello text="Hello World" />
如果需要传递数字类型、Boolean
类型这些基本类型,需要使用{ }
包裹,以下方式是不对的
// 传递的 num 是字符串类型,isLogin 其实为 true
<MyComponents.Hello num="1" isLogin="false" />
正确的传递方式是:
<MyComponents.Hello num={1} isLogin={false} />
props
为true
对于undefined
、null
、false
、0
在Boolean
转换后都会计算为false
,需要注意的是,当使用&&
运算符计算渲染页面元素时,0
仍然会执行渲染
{this.props.data.length && <h1>Hello World</h1>}
所以最好保证&&
的左边是一个返回boolean
类型的表达式
{this.props.data.length > 0 && <h1>Hello World</h1>}
JSX
表达式作为子元素
可以使用任何JavaScript
表达式作为JSX
的子元素,例如:
export default function Home() {
const num = 5
const list = [1,2,3]
const isLogin = true
return (
<>
{num < 5 ? 'hello' : 'world'}
{list.map(n => <li key={n}>{n}</li>)}
{isLogin && <h1>Hello world</h1>}
</>
)
}
甚至可以使用一个函数作为JSX
子元素,总之,是JavaScript表达式即可,函数作为JSX
表达式如下例子所示:
function Repeat (props) {
const items = []
const textArr = ['hello', 'how old are you!', 'have a good time!']
for (let i = 0, j = props.runTimes; i < j; i++) {
items.push(props.children(textArr[i % 3], i))
}
return <>{items}</>
}
export default function Home() {
return (
<>
<Repeat runTimes={10}>
{(text, idx) => <h3 key={idx}>{text}</h3>}
</Repeat>
</>
)
}
该Repeat
函数的作用是重复执行子元素(函数)的行为,重复次数由Repeat
组件的runTimes
属性决定,重复行为由父级组件中传递的子元素(函数)决定