初识React JSXHello, JSX!Hello, JSX! 1 + 1 == {1 + 1}. today is {new Date()}Hello, {formatName(user)}!Hello, Stranger.Hello!{title} Hello, world!

reactjs.png

今天给大家伙推荐一篇前端文章,以及作者谦谦君子,网名magicly,2010年毕业于北大,获信息管理学士学位和计算机软件学士学位,毕业之后先后在酷我音乐,人人游戏,腾讯等知名互联网公司工作,之后在成都一家创业公司担任CTO,带过一年多的团队。从前到后,网页设计、微信公众号、小程序、后端接口、数据库设计优化、运维脚本、数据统计分析等都做过,使用过Java、JS、Scala、Python、Bash、C++、Rust等语言,算不上精通,但也远非只会写Hello World。最近关注大前端(包括Node.js, React, React Native, Electron, Web Workers, WebAssembly, WebGL, Three.js, D3.js等)以及深度学习算法等。
 
JSX
 
JSX即Javascript Extension,是在js语言上做的扩展,是为了在js里面更方便地书写html而开发。
 
以下即是最简单的一段JSX。
 
const hi =

Hello, JSX!

嵌入JS表达式
 
JSX里面可以很容易地嵌入JS表达式,比如:
 

const hi = 

Hello, JSX! 1 + 1 == {1 + 1}. today is {new Date()}


JSX也是表达式
 
而JSX本身也是一个表达式,会被Babel等编译成普通的JS对象,所以任何可以使用对象的地方都可以使用JSX,比如if判断,for循环里面,赋值给变量,作为函数参数传递或者返回值返回。比如:
 

function getGreeting(user) {
if (user) {
return

Hello, {formatName(user)}!

;
}
return

Hello, Stranger.

;
}

指定属性
 
JSX跟html很像(其实就是为了方便使用html才发明了JSX),所以支持指定属性。比如:
 

const img = this is a photo.

注意,不要使用引号把{}包起来。
 
子元素
 
JSX可以包含子元素(就跟html标签一样),如果没有子元素可以直接用/>来结束标签。
 

const element = (

Hello!


Good to see you here.



);

注意JSX其实是JS,所以各种命名等都习惯用JS常用的camelCase风格,并且由于class是JS的关键字,所以标签里面要用className。
 
避免XSS
 
JSX会帮你做正确的escape,避免受到XSS攻击。
 

const title = response.potentiallyMaliciousInput;
// This is safe:
const element =

{title}

;

所以如果title里面有标签<>,则会被转义为<>,如果你确保要插入的html没有问题(比如就是你自己生成的),你可以使用dangerouslySetInnerHTML属性插入未被转义的html内容:
 

const element = 
Dangerous!'}} />

注意这里是两个{}包起来哦, 因为外面一层是JSX里面写JS表达式, 里面一层是JS对象本身。
 
JSX的内部表示
 
Babel会把JSX编译成React.createElement()调用,如下两者是完全等同的:
 

const element = (


Hello, world!


);
const element = React.createElement(
'h1',
{className: 'greeting'},
'Hello, world!'
);

React.createElement()会做一些检查(比如props类型等)来减少bug,然后生产如下的对象:
 

// Note: this structure is simplified
const element = {
type: 'h1',
props: {
className: 'greeting',
children: 'Hello, world'
}
};

这些对象叫“React elements”,可以把它看成是对想要展现在屏幕上的内容描述。React读取这些对象,然后用它们构造DOM节点,并保持状态一致。
 
如果没有子元素的话,可以直接使用闭标签, 比如:
 

a pic

会被翻译成:
 

React.createElement(  'img',
{src: 'x.jpg', alt: 'a pic'}, null)

你可以使用在线Babel编译器来查看JSX具体编译成什么样的JS。
 
必须import React
 
因为JSX是编译成React.createElement,所以React必须在JSX文件中被import,否则会编译报错。比如下面的例子,虽然没有直接引用React,但是也需要import进来。这是初学者常犯的一个错误,经常出现在stateless component文件中, 因为container component里面需要显示地extends React.Component。
 

import React from 'React';
import CustomButton from './CustomButton';

function WarningButton() {
// return React.createElement(CustomButton, {color: 'red'}, null);
return ;
}

自定义的组件必须大写开头
 
小写字母开头的组件是built-in的组件,比如

或者等。如果你定义了一个小写字母开头的组件,那也可以, 不过在用在JSX之前,必须赋值给一个大写字母开头的变量。感觉有点奇怪, 所以不建议这样用,记住定义组件的时候就大写字母开头好了。
 

import React from 'react';

// Wrong! This is a component and should have been capitalized:
function hello(props) {
// Correct! This use of
is legitimate because div is a valid HTML tag:
return
Hello {props.toWhat}
;
}

function HelloWorld() {
// Wrong! React thinks is an HTML tag because it's not capitalized:
return ;

// 可以这样修复
//const Hello = hello;
//return ;
}

最好是定义的时候就定义成大写字母开头的:
 

import React from 'react';

// Correct! This is a component and should be capitalized:
function Hello(props) {
// Correct! This use of
is legitimate because div is a valid HTML tag:
return
Hello {props.toWhat}
;
}

function HelloWorld() {
// Correct! React knows is a component because it's capitalized.
return ;
}

JSX Type用.表达式
 
如果你只有一个moduleexport了很多React components,那么可以用.表达式直接访问,比如:
 

import React from 'react';

const MyComponents = {
DatePicker: function DatePicker(props) {
return
Imagine a {props.color} datepicker here.
;
}
}

function BlueDatePicker() {
return ;
}

运行时候动态选择组件类型
 
React组件的类型不能是一个表达式。如果需要根据运行时的状态(比如props的某个值)来渲染不同的组件类型, 可以先把表达式赋值给某个大写字母开头的变量。
 

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

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

function Story(props) {
// Wrong! JSX type can't be an expression.
return [props.storyType] story={props.story} />;
}

这样才可以:
 

function Story(props) {
// Correct! JSX type can be a capitalized variable.
const SpecificStory = components[props.storyType];
return ;
}

JSX的props
 
JSX中props的值可以是很多种类型。
 
JS表达式
 


字符串
 
下面两种写法是一样的, 当然我们一般用第一种,因为简单啊!
 



不指定值默认是true
 
下面两者等价,不过官方说不推荐第一种,因为容易与ES6 object shorthand的写法{autocomplete}表达的是{autocomplete: autocomplete}混淆,官方提供这种写法只是为了跟HTML保持一致。
 



展开object
 
如果父组件传递的props你想全部传递给子组件,用…展开object操作符会很方便,这个也是ES6的新特性Spread syntax。
 

function App1(props) {
return ;
}

function App2(props) {
return ;
}


不过这个功能要慎用,我见过很多人不管父组件传递过来的props包含多少个属性,统统都直接{…props}传递给子组件,而其实父组件传递过来的props可能有10个属性,而子组件只需要1个。而且这样写也看不出来子组件具体需要那几个参数,所以如果不是特别多的话,最好还是显示地写出来传递的props值。记住:
 
Explicit is better than implicit.。
 
子组件
 
JSX中在开标签和闭标签之间的内容会通过props.children传递给组件,值的类型有很多种。
 
字符串
 
Hello, React!
上述写法ComponentA中可以通过props.children拿到字符串Hello, React!。字符串是unescaped的,所以<>需要转义之后传递<>。
JSX会把下面这些空白去掉:
 
每行开始和结尾的空白
空行会去掉
挨着标签的换行会去掉
字符串中间的很多换行会合并成一个空格
字符串中间的空格不会去除,不过HTML显示的时候本身多个空格只会显示一个
所以下面这几种都是一样的, 大家可以合理利用空白来增强代码的阅读性。
 
 

   
Hello World



Hello World



Hello

World




Hello World

JSX组件
 
跟HTML一样,JSX组件可以嵌套,不同种类的子组件也可以混用,比如:
 


Here is a list:

  • Item 1

  • Item 2


sth...

JS表达式
 
比如:
 

foo

{'foo'}

{1 + 2 * 3}

这种方式用来循环渲染列表的时候很适合,如:
 

function Item(props) {
return
  • {props.message}
  • ;
    }

    function TodoList() {
    const todos = ['finish doc', 'submit pr', 'nag dan to review'];
    return (

      {todos.map((message) => )}

    );
    }

    函数!!!
     
    JS里面函数是第一等公民,也是可以像数字、字符串一样传递的。当然传递一个函数拿来显示会很奇怪(试一下,发现不会渲染,除非调用toString()转化为String),所以一般传递过去的函数会被调用进行一些转换,转化为React可以渲染的东西。
     

    // 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
    {items}
    ;
    }

    function ListOfTenThings() {
    return (

    {(index) =>
    This is item {index} in the list
    }

    );
    }

    Booleans, Null, Undefined会被忽略
     
    false, null, undefined, 以及true都是合法的子元素,但是不会被渲染出来。下面这些JSX渲染出来对的都是一样的: 空元素!
     





    {false}


    {null}


    {undefined}


    {true}

    这样做条件渲染就比较方便了,下面这样写的话只有showHeader为true的时候

    才会被渲染:
     


    {showHeader &&
    }

    注意有些所谓的falsy value,比如0是会被React渲染的。所以下面的例子中,如果messages是空的话,是会显示0的。
     


    {props.messages.length &&

    }

    可以把&&之前的表达式变成boolean来修复:
     


    {props.messages.length > 0 &&

    }

    如果确实需要显示false, null, undefined以及true的话,需要转化为String。
     

    value is {String(true)}
    value is {'' + null}
    value is {`${undefined}`}

    Rerfers
     
    https://facebook.github.io/rea … .html
    https://facebook.github.io/rea … .html

    评论




    原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/256782.html

    (0)
    上一篇 2022年5月19日
    下一篇 2022年5月19日

    相关推荐

    发表回复

    登录后才能评论