(07)React 入门——④ JSX 语法细节补充 | React 基础理论实操
转载请注明出处,未经同意,不可修改文章内容。
🔥🔥🔥“前端一万小时”两大明星专栏——“从零基础到轻松就业”、“前端面试刷题”,已于本月大改版,合二为一,干货满满,欢迎点击公众号菜单栏各模块了解。
涉及面试题:
1. 什么是内联条件表达式?
2. 为什么 React 使用 className 而不是 class 属性?
3. 在 React 中如何使用 innerHTML?
4. 如何在 React 中使用样式?
5. 如何有条件地渲染组件?
6. 如何有条件地应用样式类?
7. 如何使用 React label 元素?
8. 如何合并多个内联的样式对象?
9. 如何用 React 漂亮地显示 JSON?
10. 模块化样式文件有什么好处?
11. 是否可以在没有 JSX 的情况下使用 React?
[编号:react_07]
1 className
紧接上篇的代码,我们给 TodoList 增加点样式。
1️⃣首先,我们在 src
目录下增加一个文件 style.css
:
2️⃣在这个 style.css
里边我们写一些代码:
.input {
border: 1px solid red;
}
3️⃣然后进入 TodoList
文件,将上边的 CSS 样式引入:
import React, { Component, Fragment } from "react";
import "./style.css"; // 3️⃣-①:将当前目录下的 CSS 样式引入;
class TodoList extends Component {
constructor(props) {
super(props);
this.state = {
inputValue: "",
list: []
};
}
render() {
return(
<Fragment>
<div>
{/*
❌3️⃣-②:按已有的知识储备,我们会想当然地在这里给 input 标签绑定
一个名为 input 的 class,以便引入的样式生效!
*/}
<input
class="input"
value={this.state.inputValue}
onChange={this.handleInputChange.bind(this)}
/>
<button onClick={this.handleBtnClick.bind(this)}>
提交
</button>
</div>
<ul>
{
this.state.list.map((item, index)=>{
return(
<li
key={index}
onClick={this.handleItemDelete.bind(this, index)}
>
{item}
</li>
)
})
}
</ul>
</Fragment>
)
}
handleInputChange(e) {
this.setState({
inputValue: e.target.value
})
}
handleBtnClick() {
this.setState({
list: [...this.state.list, this.state.inputValue],
inputValue: ""
})
}
handleItemDelete(index) {
const list = [...this.state.list]
list.splice(index, 1)
this.setState({
list: list
}
)
}
}
export default TodoList;
3️⃣-③:保存后,在页面看看效果(样式确实生效了,但控制台却给我们报了“警告”);
❓3️⃣-④:怎么解决上图中的“警告”呢?
答:在 React 里,React 会认为 class
这个“关键字”表示的是 ES6 中的“类”。如果你在 HTML 属性中使用 class
,那么就会和“类” class
产生歧义!
所以,React 不建议我们把 CSS 中“类选择器”对应的 HTML 属性 class
写成 class
,而要用 className
来代替。
<input
className="input"
value={this.state.inputValue}
onChange={this.handleInputChange.bind(this)}
/>
看下效果(样式生效,且不报“警告”):
2 dangerouslySetInnerHTML
❓紧接上边的代码,继续实现一个需求:在页面的 input 框里输入 <h1>hello, Oli.</h1>
并点击“提交”按钮后,我希望在下边的列表项里显示的是“一级标题”样式的 hello, Oli.
,而不是 <h1>hello, Oli.</h1>
。
目前的代码效果为:
答:
import React, { Component, Fragment } from "react";
import "./style.css";
class TodoList extends Component {
constructor(props) {
super(props);
this.state = {
inputValue: "",
list: []
};
}
render() {
return(
<Fragment>
<div>
<input
className="input"
value={this.state.inputValue}
onChange={this.handleInputChange.bind(this)}
/>
<button onClick={this.handleBtnClick.bind(this)}>
提交
</button>
</div>
<ul>
{
this.state.list.map((item, index)=>{
return(
<li
key={index}
onClick={this.handleItemDelete.bind(this, index)}
dangerouslySetInnerHTML={{__html: item}}
>
{/*
{item}
2️⃣既然 item 写到上边去了,
那 li 标签中间的这个 item 就应该删掉了!
*/}
</li>
/*
1️⃣在“JSX 语法”里边,想要某些内容不自动“转义”,
我们需要“危险地设置 li 标签的 innerHTML 属性”——dangerouslySetInnerHTML;
*/
/*
1️⃣-①:就如名字所直译的一样,这种做法是“危险”的。由于不会被转义,
就意味着有“XSS 攻击”的可能。但若真有这需求,也不得不这么做!
*/
// 1️⃣-②:等号的右边是用 {} 包裹的 JS 表达式;
// 1️⃣-③:由于这里的 JS 表达式是一个“JS 对象”,故又是一个 {} 的包裹形式;
/*
1️⃣-④:这个“JS 对象”里边,“属性名”表示——往 li 标签里显示一个 html 这个“属性”,
写法为 __html;
“属性值”表示——循环过程中产生的这个 item。
*/
)
})
}
</ul>
</Fragment>
)
}
handleInputChange(e) {
this.setState({
inputValue: e.target.value
})
}
handleBtnClick() {
this.setState({
list: [...this.state.list, this.state.inputValue],
inputValue: ""
})
}
handleItemDelete(index) {
const list = [...this.state.list]
list.splice(index, 1)
this.setState({
list: list
}
)
}
}
export default TodoList;
最终效果:
3 htmlFor
❓紧接以上的代码,我想实现一个需求:在页面的 input 框前边增加一些文字 请输入要进行的事项:
,然后点击这些文字时,鼠标就定位到 input 框里,呈现“输入”状态。
🔗前置知识:《HTML:③ HTML 表单详解》
注释 4:
<label for="username">姓名</label> <!-- 注释4 -->
<input id="username" type="text" name="username" value="Oliver"> <!-- 注释5 -->
label for
是为了给一个 input 输入框前边加上可点击的说明文字;label
里边的for
和input
里边的id
连用,是为了:正常情况下,我要在这个输入框里边输入的话,我仅仅点击前边的说明文字是没反应的,我必须要点击这个输入框才能进入可输入模式。而这里的label for
和id
的连用就可以实现点击输入框前边的输入文字也可以进入输入模式。(注意:有 for 就必须有一个 id)
答:
import React, { Component, Fragment } from "react";
import "./style.css";
class TodoList extends Component {
constructor(props) {
super(props);
this.state = {
inputValue: "",
list: []
};
}
render() {
return(
<Fragment>
<div>
<label for="insertArea">请输入要进行的事项:</label>
{/* ❌1️⃣根据前置知识,我们貌似能很快写出满足需求的代码; */}
<input
id="insertArea"
className="input"
value={this.state.inputValue}
onChange={this.handleInputChange.bind(this)}
/>
<button onClick={this.handleBtnClick.bind(this)}>
提交
</button>
</div>
<ul>
{
this.state.list.map((item, index)=>{
return(
<li
key={index}
onClick={this.handleItemDelete.bind(this, index)}
dangerouslySetInnerHTML={{__html: item}}
>
</li>
)
})
}
</ul>
</Fragment>
)
}
handleInputChange(e) {
this.setState({
inputValue: e.target.value
})
}
handleBtnClick() {
this.setState({
list: [...this.state.list, this.state.inputValue],
inputValue: ""
})
}
handleItemDelete(index) {
const list = [...this.state.list]
list.splice(index, 1)
this.setState({
list: list
}
)
}
}
export default TodoList;
看下页面效果(效果是出来了,但是控制台却给我们报了“警告”):
2️⃣怎么解决这个“警告”呢?
答:同本文的第 1 点一样,在 React 里,React 会认为“关键字” for
表示的是“循环”。如果你在 HTML 属性中使用 for
,那么就会和“循环” for
产生歧义!
故,React 要求我们,如果你想在 <label>
标签里使用属性 for
,你得换种写法—— htmlFor
。
<label htmlFor="insertArea">请输入要进行的事项:</label>
看下页面效果:
祝好,qdywxs ♥ you!
转载自:https://juejin.cn/post/7268539701941878819