提示:以下是本篇文章正文内容,下面案例可供参考
你可以直接使用静态文件CDN的React CDN 库,地址如下
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<!-- 生产环境中不建议使用 -->
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
也可以使用官方提供的 CDN地址:
<script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
<!-- 生产环境中不建议使用 -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
第一个实例:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello React!</title>
<script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="example"></div>
<script type="text/babel">
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('example')
);
</script>
</body>
</html>
搭建本地环境
npx create-react-app my-app
参考链接: https://react.docschina.org/tutorial/tutorial.html#setup-option-2-local-development-environment
JSX 在 React 中是可选的,开发人员也经常使用这种语法
JSX 是一个基于 JavaScript + XML 的一个扩展语法。它可以作为值使用;但并不是字符串,也不是HTML;它可以配合JavaScript表达式一起使用
const App = (
<div>
<h1>前端学习</h1>
</div>
)
⚠ 注意:JSX 只能有一个顶级父元素
let name = '前端';
const App = (
<div>
<h1>{ name }</h1>
</div>
)
if/for/while这些都是语句,JSX不支持语句
<h1>{ if(true) {...} }</h1> ❌
<div>
{ /* 注释 */}
</div>
const App = (
<div class="box1"></div>
) ❌
const App = (
<div className="box1"></div>
) ✔
const App = (
<div style={{ width:'100px' }}>
</div>
)
// 这里的两个 '{{ }}',外部的大括号表示的是前面说的表达式语法中的大括号,
// 里面的大括号是表示对象的大括号
let skin = { width: '100px' }
let id = '0001';
const App = (<div id="{id}"></div>); ❌
const App = (<div id={id}></div>); ✔
前提:html文件引入了react 库 或者 搭建了本地环境
function HelloComponent(props) {
return <h1>Hello { props.name }</h1>
或者
return(
<h1>Hello { props.name }</h1>
)
}
ReactDOM.render(
<HelloComponent />,
document.getElementById('root')
)
无状态的创建形式使代码的可读性更好,并且减少了大量冗余的代码,精简只有一个render方法,大大的增强了编写一个组件的便利,除此之外无状态组件还有以下几个显著的特点:
① 组件不会被实例化,整体渲染性能得到提升
因为组件被精简成一个render方法的函数来实现的,由于是无状态组件,所以无状态组件就不会再有组件实例化的过程,无实例化过程也就不需要分配多余的内存,从而性能得到一定的提升。
② 组件不能访问 this
对象
无状态组件由于没有实例化过程,所以无法访问组件this中的对象,例如:this.ref
、this.state
等均不能访问。若想访问就不能使用这种形式来创建组件。
③ 组件无法访问生命周期的方法
因为无状态组件是不需要组件生命周期管理和状态管理,所以底层实现这种形式的组件时是不会 实现组件的生命周期方法。所以无状态组件是不能参与组件的各个生命周期管理的。
④ 无状态组件只能访问输入的props,同样的props会得到同样的渲染结果,不会有副作用
无状态组件被鼓励在大型项目中尽可能以简单的写法来分割原本庞大的组件,未来React也会这种面向无状态组件在譬如无意义的检查和内存分配领域进行一系列优化,所以,只要有可能,尽量使用无状态组件。
这种方式已经被淘汰,所以不做过多介绍。
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
value: 0
}
}
render() {
return(
<div></div>
)
}
}
ReactDOM.render(
<App />,
document.getElementById('root')
)
无状态组件内部其实是可以使用 ref 功能的,虽然不能通过通过 this.refs
访问到,但是可以通过将 ref 内容保存到无状态组件内部的一个本地变量中获取到
例如下面这段代码可以使用ref来获取组件挂载到dom中后所指向的dom元素
function HelloComponent(props) {
let ref;
return(
<div>
<div ref={ (node) => ref=node }>
...
</div>
</div>
)
}
当不需要使用状态 state 和 访问 this 对象的时候建议使用无状态函数式组件定义;
如果含有状态,需要访问this对象,则推荐使用 React.Component
组件,从概念上类似于 JavaScript 函数。它接受任意的入参(即 “props”),并返回用于描述页面展示内容的 React 元素。
// 函数组件
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
// class 组件
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
一般使用到 state,我们应该用 class 组件
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
总结
// 2. 异步解释
this.setState((state, props) => ({
counter: state.counter + props.increment
}));
或者
this.setState(function(state, props) {
return {
counter: state.counter + props.increment
};
});
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
//componentDidMount()方法会在组件已经被渲染到 DOM 中后运行
componentDidMount() {
this.timerID = setInterval(
() => this.tick(),
1000
);
}
//componentDidMount()方法会在组件从 DOM 中移除时运行
componentWillUnmount() {
clearInterval(this.timerID);
}
tick() {
this.setState({
date: new Date()
});
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
function ActionLink() {
function handleClick(e) {
e.preventDefault();
console.log('The link was clicked.');
}
return (
<a href="#" onClick={handleClick}>
Click me
</a>
);
}
总结
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// 为了在回调中使用 `this`,这个绑定是必不可少的
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(state => ({
isToggleOn: !state.isToggleOn
}));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
ReactDOM.render(
<Toggle />,
document.getElementById('root')
);
总结
为了在回调中使用 this
方式① :在 constructor 中改变 this 指向
this.handleClick = this.handleClick.bind(this)
方式②:使用箭头函数
<button onClick={ () => this.handleClick }></button>
向事件处理程序传递参数
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
上述两种方式是等价的,分别通过箭头函数和 Function.prototype.bind 来实现。
在这两种情况下,React 的事件对象 e 会被作为第二个参数传递。如果通过箭头函数的方式,事件对象必须显式的进行传递,而通过 bind 的方式,事件对象以及更多的参数将会被隐式的进行传递。
可参考官方文档:https://react.docschina.org/docs/conditional-rendering.html
可参考官方文档:https://react.docschina.org/docs/lists-and-keys.html
在 HTML 中,表单元素(如、 和 )之类的表单元素通常自己维护 state,并根据用户输入进行更新。而在 React 中,可变状态(mutable state)通常保存在组件的 state 属性中,并且只能通过使用 setState() 来更新。
我们可以把两者结合起来,使 React 的 state 成为“唯一数据源”。渲染表单的 React 组件还控制着用户输入过程中表单发生的操作。被 React 以这种方式控制取值的表单输入元素就叫做“受控组件”。
class NameForm extends React.Component {
constructor(props) {
super(props);
this.state = {value: ''};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
handleSubmit(event) {
alert('提交的名字: ' + this.state.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
名字:
<input type="text" value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="提交" />
</form>
);
}
}
总结
event.target.value
获取受控组件的值可参考官方文档:https://react.docschina.org/docs/lifting-state-up.html
function FancyBorder(props) {
return (
<div className={'FancyBorder FancyBorder-' + props.color}>
{props.children}
</div>
);
}
function WelcomeDialog() {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
Welcome
</h1>
<p className="Dialog-message">
Thank you for visiting our spacecraft!
</p>
</FancyBorder>
);
}
少数情况下,你可能需要在一个组件中预留出几个“洞”。这种情况下,我们可以不使用 children,而是自行约定:将所需内容传入 props,并使用相应的 prop。
function SplitPane(props) {
return (
<div className="SplitPane">
<div className="SplitPane-left">
{props.left}
</div>
<div className="SplitPane-right">
{props.right}
</div>
</div>
);
}
function App() {
return (
<SplitPane
left={
<Contacts />
}
right={
<Chat />
} />
);
}
function Dialog(props) {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
{props.title}
</h1>
<p className="Dialog-message">
{props.message}
</p>
</FancyBorder>
);
}
function WelcomeDialog() {
return (
<Dialog
title="Welcome"
message="Thank you for visiting our spacecraft!" />
);
}
时间旅行,即保存历史记录
可参考官方文档:https://react.docschina.org/tutorial/tutorial.html#adding-time-travel