引言
作为 React 的初学者,往往会写出以下代码:
render() {
return (
<div>
<h1>List of todos</h1>
console.log(this.props.todos)
</div>
);
这样做将不会在控制台上打印出你所期望的 todos 信息,它只会在浏览器中渲染出字符串 console.log(this.props.todos)
。
解决方案
最常用的方案
在你的 JSX 代码中嵌入表达式:
render() {
return (
<div>
<h1>List of todos</h1>
{ console.log(this.props.todos) }
</div>
);
}
另一个受欢迎的方案
将你的 console.log
放置于 return()
之前:
render() {
console.log(this.props.todos);
return (
<div>
<h1>List of todos</h1>
</div>
);
}
新颖的方案
我们完全可以定制一个 <ConsoleLog>
组件:
const ConsoleLog = ({ children }) => {
console.log(children);
return false;
};
然后在需要的时候引入该组件:
render() {
return (
<div>
<h1>List of todos</h1>
<ConsoleLog>{ this.props.todos }</ConsoleLog>
</div>
);
}
这一切如何解释
首先,JSX
不是原生的 JavaScript
,也不是 HTML
,它是一种拓展语言。
拓展语言是指需要经过编译后才能被浏览器执行的语言,比如我们熟知的样式预处理器:sass,采用该语言编写的样式文件,后缀名为 .scss,经过 webpack 中 sass-loader 的处理,最终转换为浏览器可以理解的 .css 文件
相同的,.jsx
最终会被编译为原生的 .js
。举个🌰,我们在 JSX
写入:
const element = (
<h1 className="greeting">
Hello, world!
</h1>
);
它将最终被编译为:
const element = React.createElement(
'h1',
{className: 'greeting'},
'Hello, world!'
);
这一切都是 Babel(下一代 JavaScript 编译器)
在背后做的功劳,大家可以打开 Babel/repl 亲自试一试。
我们来看 React.createElement
的每个参数代表了什么?
'h1'
: 标签的名称,是一个字符串{ className: 'greeting' }
: 将<h1>
的属性转化为对象,例如 className,事件处理器,props'Hello, world!'
: 被叫做children
,包含<h1>
标签内的所有子内容
我们将视线转向文章开头的代码:
<div>
<h1>List of todos</h1>
console.log(this.props.todos)
</div>
会被最终编译为:
// 当包含多个子元素时,children将视为一个数组
React.createElement(
'div',
{}, // 没有属性
[
React.createElement( // 遇到新标签h1,再次执行React.createElement
'h1',
{}, // 同样没有属性
'List of todos',
),
'console.log(this.props.todos)'
]
);
结尾
当你想使用 console.log
时,只需将代码嵌入到 {}
中