今天给大家伙推荐一篇前端文章,以及作者谦谦君子,网名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) {
returnHello, {formatName(user)}!
;
}
returnHello, Stranger.
;
}
指定属性
JSX跟html很像(其实就是为了方便使用html才发明了JSX),所以支持指定属性。比如:
const img =
注意,不要使用引号把{}包起来。
子元素
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节点,并保持状态一致。
如果没有子元素的话,可以直接使用闭标签, 比如:
会被翻译成:
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 ofis legitimate because div is a valid HTML tag:
returnHello {props.toWhat};
}
function HelloWorld() {
// Wrong! React thinksis 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 ofis legitimate because div is a valid HTML tag:
returnHello {props.toWhat};
}
function HelloWorld() {
// Correct! React knowsis a component because it's capitalized.
return;
}JSX Type用.表达式
如果你只有一个moduleexport了很多React components,那么可以用.表达式直接访问,比如:
import React from 'react';
const MyComponents = {
DatePicker: function DatePicker(props) {
returnImagine 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)如何修复使用 Python ORM 工具 SQLAlchemy 时的常见陷阱上一篇 2022年5月19日PostgreSQL 入门下一篇 2022年5月19日