JSX是React中的一项技术,它不是一种全新的语言,而是一种JS的扩展,能够我们在react中编写像HTML模板的Javascript。
JSX入门
下面我们定义了一个包含字符串的div标签:
const element = <div>Hello, world!</div>
这种写法看起来很奇怪,像HTML和javascript的组合,但它是一个javascript。虽然咋一看像HTML,实际上是用于定义组件及其在标记内的定位的语法糖。在JSX表达式中,可以非常容易地插入属性:
const testId = 'test'
const element = <div id={testId}>Hello, world!</div>
看上去很简单吧,但是你也需要知道一些注意点:
- 如果属性中有‘-’,你需要把它转成驼峰写法,比如像data-*
- class 需要写成className
- for 需要写成htmlFor
(Note:class和for都是js中的保留字)
接下来,我们再来一个复杂的例子:
<div>
<Header />
<TableContent />
</div>
这段代码中,一个div标签包含了Header和TableContent两个组件。在jsx中render函数只能返回单个节点,所以如果我们需要返回两个兄弟节点,就需要用一个标签包含,这个标签可以是任意标签,而不仅仅是例子中的div标签。在例子中我们还可以看到,所有标签都是闭合的,而这点也是需要牢记的。
Transpiling JSX
在浏览器中,无法执行包含JSX代码的js文件,因此必须先将它们转换为常规js代码,这个过程就叫做transpiling。Transpiling是一个特定的术语,就是获取一种语言编写的源代码,并转换为另一种具有相似抽象级别的语言的过程。
举个例子,下面的两种写法其实是等价的:
//普通的js
ReactDOM.render(
React.DOM.div(
{ id: 'test' },
React.DOM.h1(null, 'A title'),
React.DOM.p(null, 'A paragraph')
),
document.getElementById('myapp')
)
//jsx写法
ReactDOM.render(
<div id="test">
<h1>A title</h1>
<p>A paragraph</p>
</div>,
document.getElementById('myapp')
)
对比一下我们可以看到,普通写法比jsx语法是多么的复杂,可读性也很差。那么我们如何将jsx转为普通js呢?答案是babel,你需要设置babel来实现这一过程,但是令人安心的是,在create-react-app中一切都已经设置好了,因此你不需要太在意如何去配置babel。
Js in JSX
我们也能够在jsx中混入js代码,只需要将你的js用花括号包括起来放在jsx中:
const testStr = 'A paragraph'
ReactDOM.render(
<div id="test">
<h1>A title</h1>
<p>{testStr}</p>
</div>,
document.getElementById('myapp')
)
上面的例子只是一个基础写法,我们定义了字符串变量testStr放入jsx中,我们也可以在jsx中执行一些js运算,比如数组的map方法:
const lists = [{
text:'list1'
},{
text:'list2'
}]
ReactDOM.render(
<table>
{lists.map((list, i) => {
return <tr>{list.text}</tr>
})}
</div>,
document.getElementById('myapp')
)
这个例子中你可以看到,我们在jsx中嵌套的js中又嵌套了js,实际使用中你可以根据你的需要来自由使用。
HTML in JSX
下面我们看一下如何在jsx中使用html:
- 你需要闭合所有标签,例<br>变成<br />
- 驼峰写法是新标准。在html中有一些属性没有使用驼峰写法例如onclick,jsx中都需要变成驼峰形式,例如onchange变成onChange,onclick变成onClick,onsubmit变成onSubmit等等。
- class变成className。在js中class是一个保留字,因此在jsx中我们需要把class变成className,与class一样的还有for,for需要变成htmlFor。
// error
<p class="description">
// correct
<p className="description">
CSS in JSX
还记得如何在HTML中书写行内样式吗?没错,在jsx中我们也能书写行内样式,但是style的接收值确发生了变化,以前我们使用包含css属性的字符串来写,但是在jsx中,我们需要的是一个对象:
var divStyle = {
color: 'white'
}
ReactDOM.render(
<div style={divStyle}>
Hello World!
</div>,
mountNode)
或
ReactDOM.render(
<div style={{ color: 'white' }}>
Hello World!
</div>
, mountNode)
在jsx中书写css与传统的css有一些不同点:
- 属性名需要用驼峰来属性,例如:font-size变成fontSize
- 属性值是一个字符串
- 不同属性之间用逗号来分隔
虽然jsx中可以书写css样式,但是这并不是完美无缺的办法,如果我们需要书写一些伪类样式,例如:hover,jsx将毫无办法。
Forms in JSX
jsx对HTML的form进行了一些小小的修改,能够让开发人员更轻松的使用form。
1.value和defeaultValue
value属性始终记录表单元素的当前值,defaultValue属性记录创建表单元素时设置的默认值。这样做有助于解决在检查input.value返回当前值和input.getAttribute('value')返回原始默认值时常规DOM交互的一些奇怪行为。
这也适用于textarea字段,例如:
<textarea>Some text</textarea>
也可以这样写
<textarea defaultValue={'Some text'} />
对于select元素,由
<select>
<option value="x" selected>
...
</option>
</select>
替换成:
<select defaultValue="x">
<option value="x">...</option>
</select>
2.onChange
在jsx中,我们用onChange事件来监听表单元素的值的变化,无论你是select,radio还是checkbox,甚至input和textarea的键入都会触发onChange。
3.spread属性
我们可以使用ES6中的spread操作符来设置属性,例:
<div>
<BlogPost title={data.title} date={data.date} />
</div>
可以这样写:
<div>
<BlogPost {...data} />
</div>
4.JSX中的循环
如果你有一组元素需要循环生成,那么你就可以创建一个循环,然后将JSX添加到一个数组,
你可以使用for循环:
const elements = ['one', 'two', 'three'];
const items = []
for (const [index, value] of elements.entries() {
items.push(<li key={index}>{value}</li>)
}
return (
<div>
{items}
</div>
)
还有一种简便的方式,你可以使用map方法来实现上面代码的功能:
const elements = ['one', 'two', 'three'];
return (
<ul>
{elements.map((value, index) => {
return <li key={index}>{value}</li>
})}
</ul>
)
网友评论