第一篇:React入门以及学习资料汇总分享
HTML 语言直接写在 JavaScript 语言中,不加任何引号,这就是 JSX 语法。它允许 HTML 与 JavaScript 的混写。
babel-standalone
babel-preset-react
必须只能有一个根节点
遇到 HTML 标签 (以 <
开头) 就用 HTML 规则解析
遇到代码块(以 {
开头),就用 JavaScript 规则解析
JSX 允许直接在模板中插入一个 JavaScript 变量
单标签必须结束 />
基本语法:
const element = Hello, world!
;
function formatName(user) {
return user.firstName + ' ' + user.lastName;
}
const user = {
firstName: 'Harper',
lastName: 'Perez'
};
const element = (
Hello, {formatName(user)}!
);
ReactDOM.render(
element,
document.getElementById('root')
);
function getGreeting(user) {
if (user) {
return Hello, {formatName(user)}!
;
}
return Hello, Stranger.
;
}
class
使用 className
tabindex
使用 tabIndex
for
使用 htmlFor
普通的属性:
const element = ;
在属性中使用表达式:
const element = ;
如果标签是空的,可以使用 />
立即关闭它。
const element = ;
JSX 子节点可以包含子节点:
const element = (
Hello!
Good to see you here.
);
const element = {'this is safe
'}
写法一:
{
// 注释
// ...
}
写法二(单行推荐):
{/* 单行注释 */}
写法三(多行推荐):
{
/*
* 多行注释
*/
}
Babel 会把 JSX 编译为 React.createElement()
函数。
下面两种方式是等价的:
const element = (
Hello, world!
);
const element = React.createElement(
'h1',
{className: 'greeting'},
'Hello, world!'
);
// Note: this structure is simplified
const element = {
type: 'h1',
props: {
className: 'greeting',
children: 'Hello, world'
}
};
JSX 允许直接在模板插入 JavaScript 变量。如果这个变量是一个数组,则会展开这个数组的所有成员。
var arr = [
Hello world!
,
React is awesome
,
];
ReactDOM.render(
{arr},
document.getElementById('example')
);
综上所述,我们可以这样:
var names = ['Alice', 'Emily', 'Kate'];
ReactDOM.render(
{
names.map(function (name) {
return Hello, {name}!
})
}
,
document.getElementById('example')
);
参考文档:https://reactjs.org/docs/dom-elements.html
参考文档:https://reactjs.org/docs/lists-and-keys.html
http://babeljs.io/docs/editors
参考文档:https://reactjs.org/docs/conditional-rendering.html
function UserGreeting(props) {
return Welcome back!
;
}
function GuestGreeting(props) {
return Please sign up.
;
}
function Greeting(props) {
const isLoggedIn = props.isLoggedIn;
if (isLoggedIn) {
return ;
}
return ;
}
ReactDOM.render(
// Try changing to isLoggedIn={true}:
,
document.getElementById('root')
);
function LoginButton(props) {
return (
);
}
function LogoutButton(props) {
return (
);
}
class LoginControl extends React.Component {
constructor(props) {
super(props);
this.handleLoginClick = this.handleLoginClick.bind(this);
this.handleLogoutClick = this.handleLogoutClick.bind(this);
this.state = {isLoggedIn: false};
}
handleLoginClick() {
this.setState({isLoggedIn: true});
}
handleLogoutClick() {
this.setState({isLoggedIn: false});
}
render() {
const isLoggedIn = this.state.isLoggedIn;
let button = null;
if (isLoggedIn) {
button = ;
} else {
button = ;
}
return (
{button}
);
}
}
ReactDOM.render(
,
document.getElementById('root')
);
function Mailbox(props) {
const unreadMessages = props.unreadMessages;
return (
Hello!
{unreadMessages.length > 0 &&
You have {unreadMessages.length} unread messages.
}
);
}
const messages = ['React', 'Re: React', 'Re:Re: React'];
ReactDOM.render(
,
document.getElementById('root')
);
render() {
const isLoggedIn = this.state.isLoggedIn;
return (
The user is {isLoggedIn ? 'currently' : 'not'} logged in.
);
}
render() {
const isLoggedIn = this.state.isLoggedIn;
return (
{isLoggedIn ? (
) : (
)}
);
}
function WarningBanner(props) {
if (!props.warn) {
return null;
}
return (
Warning!
);
}
class Page extends React.Component {
constructor(props) {
super(props);
this.state = {showWarning: true}
this.handleToggleClick = this.handleToggleClick.bind(this);
}
handleToggleClick() {
this.setState(prevState => ({
showWarning: !prevState.showWarning
}));
}
render() {
return (
);
}
}
ReactDOM.render(
,
document.getElementById('root')
);
参考文档:https://reactjs.org/docs/handling-events.html
<a href="#" onclick="console.log('The link was clicked.'); return false">
Click me
a>
function ActionLink() {
function handleClick(e) {
e.preventDefault();
console.log('The link was clicked.');
}
return (
Click me
);
}
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// This binding is necessary to make `this` work in the callback
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(prevState => ({
isToggleOn: !prevState.isToggleOn
}));
}
render() {
return (
);
}
}
ReactDOM.render(
,
document.getElementById('root')
);
箭头函数:
class LoggingButton extends React.Component {
// This syntax ensures `this` is bound within handleClick.
// Warning: this is *experimental* syntax.
handleClick = () => {
console.log('this is:', this);
}
render() {
return (
);
}
}
更简单的方式:
class LoggingButton extends React.Component {
handleClick() {
console.log('this is:', this);
}
render() {
// This syntax ensures `this` is bound within handleClick
return (
);
}
}
class:
classNames:
style:
参考文档:https://reactjs.org/docs/forms.html
React 允许将代码封装成组件(component),然后像插入普通 HTML 标签一样,在网页中插入这个组件。
render
方法props
获取
props
this.props
class ShoppingList extends React.Component {
render() {
return (
Shopping List for {this.props.name}
- Instagram
- WhatsApp
- Oculus
);
}
}
// Example usage:
本质:
return React.createElement('div', {className: 'shopping-list'},
React.createElement('h1', /* ... h1 children ... */),
React.createElement('ul', /* ... ul children ... */)
);
EcmaScript 5 构造函数:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
EcmaScript 6 Class:
class Welcome extends React.Component {
render() {
return Hello, {this.props.name}
;
}
}
this.props.children
参考文档:https://reactjs.org/docs/react-api.html#reactchildren
this.props
对象的属性与组件的属性一一对应,但是有一个例外,就是 this.props.children
属性。
它表示组件的所有子节点。
this.props.children
的值有三种可能:如果当前组件没有子节点,它就是 undefined
;如果有一个子节点,数据类型是 object
;如果有多个子节点,数据类型就是 array
。所以,处理 this.props.children
的时候要小心。
React 提供一个工具方法 React.Children
来处理 this.props.children
。我们可以用 React.Children.map
来遍历子节点,而不用担心 this.props.children
的数据类型是 undefined
还是 object
。
参考文档:https://reactjs.org/docs/state-and-lifecycle.html
参考文档:https://reactjs.org/docs/state-and-lifecycle.html
完整生命周期 API:https://reactjs.org/docs/react-component.html#the-component-lifecycle
参考文档:https://reactjs.org/docs/typechecking-with-proptypes.html
组件的属性可以接受任意值,字符串、对象、函数等等都可以。有时,我们需要一种机制,验证别人使用组件时,提供的参数是否符合要求。
示例:
import PropTypes from 'prop-types';
class Greeting extends React.Component {
render() {
return (
Hello, {this.props.name}
);
}
}
Greeting.propTypes = {
name: PropTypes.string
};
参考文档:https://reactjs.org/docs/typechecking-with-proptypes.html#default-prop-values
示例:
class Greeting extends React.Component {
render() {
return (
Hello, {this.props.name}
);
}
}
// Specifies the default values for props:
Greeting.defaultProps = {
name: 'Stranger'
};
// Renders "Hello, Stranger":
ReactDOM.render(
,
document.getElementById('example')
);
或者:
class Greeting extends React.Component {
static defaultProps = {
name: 'stranger'
}
render() {
return (
Hello, {this.props.name}
)
}
}
组件的数据来源,通常是通过 Ajax 请求从服务器获取,可以使用 componentDidMount
方法设置 Ajax 请求,等到请求成功,再用 this.setState
方法重新渲染 UI 。
参考文档:https://reactjs.org/docs/refs-and-the-dom.html
组件并不是真实的 DOM 节点,而是存在于内存之中的一种数据结构,叫做虚拟 DOM (virtual DOM)。只有当它插入文档以后,才会变成真实的 DOM 。根据 React 的设计,所有的 DOM 变动,都先在虚拟 DOM 上发生,然后再将实际发生变动的部分,反映在真实 DOM上,这种算法叫做 DOM diff ,它可以极大提高网页的性能表现。
但是,有时需要从组件获取真实 DOM 的节点,这时就要用到 ref
属性。
示例:
class CustomTextInput extends React.Component {
constructor(props) {
super(props);
this.focusTextInput = this.focusTextInput.bind(this);
}
focusTextInput() {
// Explicitly focus the text input using the raw DOM API
this.textInput.focus();
}
render() {
// Use the `ref` callback to store a reference to the text input DOM
// element in an instance field (for example, this.textInput).
return (
{ this.textInput = input; }} />
);
}
}
下载模板:
git clong https://github.com/tastejs/todomvc-app-template.git --depth=1 todomvc-react
安装依赖:
cd todomvc-react
npm install
安装 react
开发环境依赖:
npm install --save babel-standalone react react-dom
https://github.com/facebook/react-devtools