本章内容
目录
- 1、js 表达式
- 2、列表渲染
- 3、条件渲染
- 4、className
- 5、jsx 中的样式处理
- 6、dangeouslySetInnerHTML
- 7、htmlFor
- 8、使用 jsx 的注意事项
上一节内容我们完成了一个简单的TodoList
案例。到现在为止我们已经知道怎么在 JSX
中使用 “js 表达式”和”列表渲染“了,本节我们继续使用之前的工程项目来编写代码,补充在 React
使用 JSX
语法的一些细节。
1、js 表达式
JSX
中使用表达式:{ JS 表达式 }
- 可使用的
js
表达式有:
字符串、数值、布尔值、null、undefined、数组、对象
函数: add(1, 2)
js运算: 1+2、'abc'.split('') 等
...
- 注意:
if..else
、switch..case
等是js
语句,不是表达式,不能出现在{}
中
// App.js 文件中,注释之前的代码,换成以下代码,运行并打开浏览器观察显示结果import React, { Component } from 'react'
class App extends Component {constructor(props) {super(props)this.obj = {name: 'bob', age: 12}}// 加法add(a, b) {return a+b}// 减法minus (a, b) { return a-b}render() {return (<div className="App"><p>字符串: { 'str' }</p><p>数值: { 111 }</p><p>布尔值: { true ? 'true': 'false' }</p><p>null: { null }</p><p>undefined: { undefined }</p><p>数组: { [1, 2, 3, 4] }</p><p>对象: { this.obj.name} - {this.obj.age }</p><p>函数:{ this.add(1, 2)}, {this.minus(10, 1)}</p><p>计算: { 1+3333 }</p></div>)}}
export default App
2、列表渲染
- 在
TodoList
案例中,我们已经了解到列表的渲染可以使用map
实现。 - 渲染过程中需要指定
key
, 这是React
内部用于性能优化的,我们后面会详细讲一下.
// App.js 文件中,注释之前的代码,换成以下代码,运行并打开浏览器观察显示结果import React, { Component } from 'react'class App extends Component {constructor (props) {super(props)this.userList = [{ name: 'bob', age: 22 },{ name: 'liii', age: 18 },{ name: 'mary', age: 19 },{ name: 'tom', age: 31 }]this.lower20List = this.userList.filter(item => item.age < 20)}render() {return (<div className="App"><p>展示用户列表数据:</p><ul>{this.userList.map((item, index) => <li>{item.name} --- {item.age}</li>)}</ul><p>展示20岁以下的用户数据</p><ul>{this.lower20List.map((item, index) => <li key={index}>{item.name} --- {item.age}</li>)}</ul></div>)}}export default App
3、条件渲染
官网这里详细介绍了在 JSX
中如何进行条件渲染。具体的方式有:
- 使用
if
表达式语句、switch
语句 - 使用三目运算
( condition ? a : b)
- 使用
{ condition && a }
或者{condtion || a}
// App.js 文件中,注释之前的代码,换成以下代码,运行并打开浏览器观察显示结果import React, { Component } from 'react'
function ShowScoreMessage(props){ // 注意组件函数的命名需要使用大驼峰方式if (props.score < 60) {return (<div><p>你的分数是: {props.score}</p><div>不及格!!!</div></div>)} else {return (<div><p>你的分数是: {props.score}</p><div>及格!!!</div></div>)}
}class App extends Component {contructor() {this.sex = 'male' // 1.1 定义一个性别的变量this.score = 99 // 2.1 定义一个score,根据 score 显示不同的提示组件this.isEdit = true // 3.1 定义一个isEidt 变量,用于表示当前是否是编辑状态}render() {return (<div>{/* 1.2 使用三目运算进行条件渲染 */}{this.sex==='male' ? ' 我是一个男孩': '我是一个女孩'}{ false ? <span>this is span</span> : null}{/* 2.2 使用 if 语句进行条件渲染 */}<ShowScoreMessage score={this.score}></ShowScoreMessage>{/* 3.2 使用 && 运算符显示数据 */}{ this.isEdit && '现在是编辑状态'}</div>)}
}
export default App
4、className
-
在传统的前端编程中,如果想给一个
HTML
元素添加类名,只需要给其class
属性进行赋值即可 -
但是在
React
的JSX
语法里,如果想给一个HTML
元素赋值类名,必须使用className
。如果使用class
关键字,React 会认为它是 E6中的类。为了避免歧义,React
建议我们将HTML
属性class
改写成className
. -
当然了,如果你硬要使用
class
来添加类名,确实能生效,但是仔细观察会发现浏览器的控制台会有个错误警告
/* App.css 文件*/
.p1 {color: #f00;
}.p2 {color: aqua;
}
// App.js 文件中,注释之前的代码,换成以下代码,运行并打开浏览器观察显示结果import React, { Component } from 'react'
import './App.css'class App extends Component {render() {return (<div>{/* 你会发现使用 class 也生效,就是控制台会出现错误警告 */}<p class="p1">这是一个class 为 p1 的 p元素</p>{/* 建议使用 className 来赋值类名 */}<p className="p2">这是一个class 为 p2 的 p元素</p>{/* 如果的类名是动态的,仍然可以结合jsx 的表达式+条件渲染 */}<p className={false ? 'p1' : ''}>这个p元素的类名是动态的</p></div>)}}export default App
5、jsx 中的样式处理
React
中的样式处理,一般有三种方式:
- 第一种方式是直接行内样式绑定
- 第二种是将样式提取到一个变量中,再将变量绑定到
style
属性上(常用) - 第三种是动态控制类名,不同类名里定义不同的样式
/* App.css 文件*/
.p1 {color: #f00;
}.p2 {color: aqua;
}
import React, { Component } from 'react'
import './App.css'class App extends Component {constructor(props) {super(props)this.styleObj = {color: '#f00',fontSize: '16px'}this.isP1 = false}render() {return (<div>{/* 1、行内样式 */}<p style={{color: '#0f0', border: '1px solid #ccc'}}>字体绿色,边框1px</p>{/* 2、将样式提取到一个变量中,然后赋值变量到 style 属性上 */}<p style={this.styleObj}>字体红色, 字号16px</p>{/* 3、使用动态类名来控制样式 */}<p className={this.isP1 ? 'p1': 'p2'}>类名为p2的样式</p></div>)}
}
export default App
6、dangeouslySetInnerHTML
-
到现在为止,我们知道在
JSX
中如果要渲染一个常规的字符串,可以将字符串赋值一个变量,然后直接使用{}
进行渲染。 -
那现在假设一下,如果这个字符变量里存储的不是普通的字符串,而是一段
HTML
,那要怎么才能正确显示这段HTML
呢? -
现在我们来实现一个需求:有个字符变量,内容为
<h1>这是一个 h1 标签</h1>
, 希望在页面显示的结果是“一级标题”样式的 ”这是一个 h1 标签“,而不是<h1> 这是一个 h1 标签</h1>
-
React
中提供了dangeouslySetInnerHTML
属性,允许将HTML
插入到组件中。相当于js
的innerHTML
。dangeouslySetInnerHTML
在使用时必须传递一个对象,该对象具有一个名为__html
的属性,该属性包含您要插入到组件中的HTML
字符串 -
但要注意的是,就如同它的命名一样。它是危险的,由于不会转义,就意味着存在
XSS
攻击或者其他安全问题
import React, { Component } from 'react'class App extends Component {constructor(props) {super(props)this.str = '<h1>这是一个 h1 标签</h1>'}render() {return (<div>{/* 直接渲染,你会发现界面显示的是: <h1>这是一个 h1 标签</h1> */}{this.str}{/* 在 React 中可以使用 dangerouslySetInnerHTML 来实现直接将 HTML 插入到组件中 */}<p dangerouslySetInnerHTML={{__html: this.str}}></p></div>)}}export default App
7、htmlFor
- 需求:有个可以输入姓名的输入框,要求点击”姓名“时,
input
框也可以获得焦点 - 传统的做法是,使用
label
元素包裹 ”姓名“,然后其for
属性绑定input
的id
属性,这样就可实现点击"姓名"后input
框获得焦点 - 如果我们直接按照传统方式在
React
中写,会发现效果虽然实现了,但是控制台会有个错误警告 - 在
React
如果你要使用label
的for
,那么要将for
改写成htmlFor
<label for="username">姓名</label>
<input id="username" value="bob" name="username" type="text" />
import React, { Component } from 'react'class App extends Component {render() {return (<div>{/* 功能实现了,但是控制台会出现一个错误警告 */}<label for="username">姓名: </label><input id="username" value="bob" name="username" type="text" />{/* 在 React 如果你要使用 label的 for ,那么要将 for 改写成 htmlFor */}<label htmlFor="username">姓名: </label><input id="username" value="bob" name="username" type="text" /></div>)}}export default App
8、使用 jsx 的注意事项
JSX
必须有一个根节点,如果没有根节点则使用<></>
(幽灵节点)或者Fragment
代替根节点- 所有标签必须形成闭合,双标签闭合或者单标签闭合都可
JSX
语法更贴近js
语法,属性名采用驼峰命名法,例:className,htmlFor
JSX
支持多行(换行),如需换行,可使用()
包裹
到此,本章内容结束!