React进阶笔记1(jsx深入理解)

深入jsx

从本质上来说,jsx只是为React.creatElement(component,props)提供的语法糖。例如:

<Mybutton color="blue" shadowsize={2}>
    click me
</Mybutton>

编译后得到(也就是React底层实现的过程):

React.createElement(
    Mybutton,//组件名
    {color:"blue",shadowsize:2},//相关属性
    "click me" //文本内容
)

如果节点中没有子代。子节点,还可以直接使用自闭和标签。如:

<div className="sidebar" />

然后编译为:

React.createElement(
    'div',
    {className:"sidebar"},
    null
)

如果你想彻底验证 JSX 是如何转换为 JavaScript 的,你可以尝试 在线 Babel 编译器.

指定React元素类型

jsx的标签名决定了React的元素类型。

大写开头的jsx标签表示一个React组件。这些标签会被编译成同名的变量然后引用。如果你使用<Kolento />,就必须在作用域中生命Kolento变量。

React必须声明

由于jsx在编译后会调用React.createElement()方法,所以你的jsx中必须首先声明React变量,否则就找不到React了。

例如:下面的声明都是必须的。
尽管React和CustomButton都没有被直接调用。

import React from 'react';
import CustomButton from './CustomButton';
function WarningButton(){
// 返回 React.createElement(CustomButton, {color: 'blue'}, null);
    return <CustomButton color="blue" />
}

如果使用script加载React,他会作用于全局

点表示法

我们还可以使用React中的点表示法来引用React组件。你可以方便的从一个模块中,导出许多React组件,有一个叫Components.DatePicker的组件。可以直接在jsx中使用它。
调用的时候只要Components.DatePicker 即可

const MyComponents = {
    DatePicker:function Date(props){
        return <div>Imagine a {props.color} datepicker here</div>    
    }
}

function BlueDatePicker(){
    return <MyComponents.DatePicker color="blue" />
}

首字母大写

当元素的首字母以小写开头,则表示他是一个内置的组件,如div span,并将字符串 ‘div’ 或 ‘span’ 传 递给 React.createElement。 以大写字母开头的类型,如 <Foo /> 编译为 React.createElement(Foo),并它正对应于你在 JavaScript 文件中定义或导入的组件。

我们建议用大写开头命名组件。如果你的组件以小写字母开头,请在 JSX 中使用之前其赋值给大写开头的变量。

错误demo
import React from 'react';

// 错误!组件名应该首字母大写:
function hello(props) {
  // 正确!div 是有效的 HTML 标签:
  return <div>Hello {props.toWhat}</div>;
}

function HelloWorld() {
  // 错误!React 会将小写开头的标签名认为是 HTML 原生标签:
  return <hello toWhat="World" />;
}

为了解决这个问题,我们将 hello 重命名为 Hello,然后使用 <Hello /> 引用:

import React from 'react';

// 正确!组件名应该首字母大写:
function Hello(props) {
  // 正确!div 是有效的 HTML 标签:
  return <div>Hello {props.toWhat}</div>;
}

function HelloWorld() {
  // 正确!React 能够将大写开头的标签名认为是 React 组件。
  return <Hello toWhat="World" />;
}

在运行时选择类型

我们不能使用表达式来作为React的标签,如果想用表达式的方式确定React的元素类型,要将表达式赋值给一个大写开头的标量,这种情况一般会在条件渲染的时候出现。

import React from 'react';
import { PhotoStory, VideoStory } from './stories';

const components = {
  photo: PhotoStory,
  video: VideoStory
};

function Story(props) {
  // 错误!JSX 标签名不能为一个表达式。
  return <components[props.storyType] story={props.story} />;
}

以上demo 使用表达式去输出一个标签,这是不可行的,需要将components[props.storyType]赋值给一个大写开头的变量替换进去才行。

解决:要解决这个问题,我们需要先将类型赋值给大写开头的变量。

import React from 'react';
import { PhotoStory, VideoStory } from './stories';

const components = {
  photo: PhotoStory,
  video: VideoStory
};

function Story(props) {
  // 正确!JSX 标签名可以为大写开头的变量。
  const SpecificStory = components[props.storyType];
  return <SpecificStory story={props.story} />;
}

属性

在jsx中有几种不同的方式来指定属性

使用js表达式

可以传递任何{}包裹的javascript表达式作为一个属性值。

<MyComponent foo={1 + 2 + 3 + 4} />

对于MyComponent来说,props.foo的值为10,是通过表达式1+2+3+4计算出来的。

if语句和for循环在js中不是表达式,因此不能再jsx中直接引用。但是可以将它放在周围的代码中。

function NumberDescriber(props) {
  let description;
  if (props.number % 2 == 0) {
    description = <strong>even</strong>;
  } else {
    description = <i>odd</i>;
  }
  return <div>{props.number} is an {description} number</div>;
}

你可以在相关部分中了解有关 条件渲染循环 的更多信息。

字符串常量

可以将字符串常量作为属性传递,以下的2个jsx是等价的。

<MyComponents message={"hello"} />
<MyComponents message="hello" />

当传递一个字符串常量时,该值会被解析为HTML非转义字符串,所以下面两个 JSX 表达式是相同的:

<MyComponent message="&lt;3" />
<MyComponent message={'<3'} />

以上的这点,了解一下即可。

属性默认为true

如果你没有给属性传值,则他默认为true,因此一下2个jsx表达式是等价的。

<MyTextBox autocomplete />
<MyTextBox autocomplete={true} />

一般情况下,我们不建议这样使用,因为它会与 ES6 对象简洁表示法 混淆。比如 {foo}{foo: foo} 的简写,而不是 {foo: true}。这里能这样用,是因为它符合 HTML 的做法。

扩展属性

如果你已经有了props对象,并且想在jsx中传递他,可以使用...作为扩展操作符来传递整个对象。以下的2个组件是等价的。

function App1() {
  return <Greeting firstName="Ben" lastName="Hector" />;
}

function App2(){
  const props = {firstName:"Ben",lastName="Hector"}
  return <Greeting {...props}>
}

当你构建通用容器时,扩展属性会非常有用。然而,这样做也可能让很多不相关的属性,传递到不需要它们的组件中使代码变得混乱。我们建议你谨慎使用此语法。

子代

在包含开始与结束标签之间的jsx表达式中,标记之间的内容可以作为特殊的参数传递props.children,有几种不同的方法来传递子代。
也就是说props.children指代标签中的内容。

字符串常量

你可以在开始和结束标签之间放入一个字符串,则 props.children就是那个字符串。这对于许多内置 HTML 元素很有用。例如:

<MyComponent>hello world</MyComponent>

这是有效的 JSX,并且 MyComponent 的 props.children 值将会直接是 "hello world!"。因为 HTML 未转义,所以你可以像写 HTML 一样写 JSX:

<div>This is valid HTML &amp; JSX at the same time.</div>

JSX 会移除空行和开始与结尾处的空格。标签邻近的新行也会被移除,字符串常量内部的换行会被压缩成一个空格,所以下面这些都等价:

<div>Hello World</div>

<div>
  Hello World
</div>

<div>
  Hello
  World
</div>

<div>

  Hello World
</div>

jsx

可以通过子代镶嵌嵌套更多的jsx元素,这对于镶嵌组件非常有用。

<MyContainer>
  <MyFirstComponent />
  <MySecondComponent />
</MyContainer>

其中可以混合不同类型的子元素,同时用字符串常量和jsx子元素,这是jsx类似html的另一种形式,这在jsx和html中都是有效的。

<div>
  Here is a list:
  <ul>
    <li>Item 1</li>
    <li>Item 2</li>
  </ul>
</div>

React组件也可以通过数组的形式返回多个元素

render() {
  // 不需要使用额外的元素包裹数组中的元素
  return [
    // 不要忘记 key :)
    <li key="A">First item</li>,
    <li key="B">Second item</li>,
    <li key="C">Third item</li>,
  ];
}

js表达式

可以将任何{}包裹的js表达式作为子代传递,比如,以下的表达式是等价的。

<MyComponent>foo</MyComponent>
<MyComponent>{'foo'}</MyComponent>

这对于渲染任意长度的jsx表达式都很有用。下面将会渲染一个HTML列表。

function Item(props){
    return <li>{props.message}</li>
}

function TodoList(){
    const todos=[
        'first','second','third'
    ]
    return(
        <ul>
            {todos.map(message=><Item key={message} message={message} />)}
        </ul>
    )
}

ReactDOM.render(
    <TodoList />,document.getElementById('root')
)

js表达式可以与其他类型的子代混合使用。这通常对于字符串模板非常有用。

function Hello(props) {
  return <div>Hello {props.addressee}!</div>;
}

函数

在通常情况下,插入jsx中的js表达式被认为是字符串、React元素或者这些内容的列表。然而props.children可以向其他属性一样传递任何的数据,而不仅仅是React元素。

如果你调用自定义组件,就可以使用props.children来获取进行传递。

// Calls the children callback numTimes to produce a repeated component
function Repeat(props) {
  let items = [];
  for (let i = 0; i < props.numTimes; i++) {
    items.push(props.children(i));
  }
  return <div>{items}</div>;
}

function ListOfTenThings() {
  return (
    <Repeat numTimes={10}>
      {(index) => <div key={index}>This is item {index} in the list</div>}
    </Repeat>
  );
}

递给自定义组件的子代可以是任何元素,只要该组件在 React 渲染前将其转换成 React 能够理解的东西。这个用法并不常见,但当你想扩展 JSX 时可以使用。

布尔值、Null 和 Undefined 被忽略

false、null、undefined 和 true 都是有效的子代,但它们不会直接被渲染。下面的表达式是等价的:

<div />

<div></div>

<div>{false}</div>

<div>{null}</div>

<div>{undefined}</div>

<div>{true}</div>

这在根据条件来确定是否渲染React元素时非常有用。以下的JSX只会在showHeader为true时渲染<Header />组件。

<div>
  {showHeader && <Header />}
  <Content />
</div>

相反,如果你想让类似 falsetruenullundefined 出现在输出中,你必须先把它转换成字符串 :

<div>
  My JavaScript variable is {String(myVariable)}.
</div>
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,816评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,729评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,300评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,780评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,890评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,084评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,151评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,912评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,355评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,666评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,809评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,504评论 4 334
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,150评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,882评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,121评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,628评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,724评论 2 351

推荐阅读更多精彩内容

  • 深入JSX date:20170412笔记原文其实JSX是React.createElement(componen...
    gaoer1938阅读 8,055评论 2 35
  • 以下内容是我在学习和研究React时,对React的特性、重点和注意事项的提取、精练和总结,可以做为React特性...
    科研者阅读 8,222评论 2 21
  • 3. JSX JSX是对JavaScript语言的一个扩展语法, 用于生产React“元素”,建议在描述UI的时候...
    pixels阅读 2,810评论 0 24
  • React版本:15.4.2**翻译:xiyoki ** 从根本上说,JSX只是为React.createElem...
    前端xiyoki阅读 3,031评论 0 0
  • 最近看了一本关于学习方法论的书,强调了记笔记和坚持的重要性。这几天也刚好在学习React,所以我打算每天坚持一篇R...
    gaoer1938阅读 1,672评论 0 5