react的基本点
2015年09月06日 Jinghuang Network
hk.0731jianzhan.com
1:组件是React的一切
React是围绕可重用组件的概念设计的。 您定义小组件,并将它们放在一起形成大的组件。
小或小的组件都可重复使用,跨不同的项目。
一个React组件(以其简单的形式)是一个简单的JavaScript函数:
// Example 1 // https://jscomplete.com/repl?j=Sy3QAdKHW function Button (props) { // Returns a DOM element here. For example: return <button type="submit">{props.label}</button>;} // To render the Button component to the browser ReactDOM.render(<Button label="Save" />, mountNode)
用于按钮标签的花括号将在下面介绍。 现在不要担心他们。 ReactDOM也将在后面解释,但是如果要测试这个例子和接下来的代码示例,render函数就是你需要的。
ReactDOM.render的参数是React将要接管和控制的目标DOM元素。 在jsComplete REPL中,您就可以使用mountNode变量。
关于示例1的注意事项有以下几点:
组件名称以大写字母开头。因为我们将处理HTML元素和React元素的混合。 小写名称保留给HTML元素。请继续尝试将React组件命名为“button”。 ReactDOM将忽略该函数并呈现常规的空HTML按钮。
每个组件都接收一个属性列表,就像HTML元素一样。 在React中,这个列表叫做props。创建功能组件,你可以通过使用任意名称命名props。
在上面的Button组件的返回中,我们写出了奇怪的HTML。 这既不是JavaScript也不是HTML,不是React.js。 但是,它很受欢迎,成为React应用程序中的默认设置。 它被称为JSX,它是一个JavaScript扩展。 JSX也是妥协! 继续尝试在上面的函数中的其他HTML元素,并查看它们是如何支持的(例如,返回一个文本输入元素)。
2: What the flux is JSX?
上面的示例1可以用的React.js来编写,而不需要JSX,如下所示:
// Example 2 - React component without JSX // https://jscomplete.com/repl?j=HyiEwoYB- function Button (props) { return React.createElement( "button", { type: "submit" }, props.label );} // To use Button, you would do something like ReactDOM.render( React.createElement(Button, { label: "Save" }), mountNode);
上面的示例1可以用的React.js来编写,而不需要JSX,如下所示:
createElement函数是React API中函数。 您需要学习的这个中有7件事情中的1项。 可见ReactApi多么简短。
很像DOM本身有一个document.createElement函数来创建一个由标签名称的元素,React的createElement函数是一个高的函数,可以做类似于document.createElement的功能。 但它也可以用于创建一个表示React组件的元素。 当我们使用上面的例2中的Button组件时,我们这里就是创建了一个React组件。
与document.createElement不同,React的createElement可以接受参数之后的动态参数,以表示创建的元素的后代。 所以createElement实际上创建一个树。
这是一个例子:
/ Example 3 - React’s createElement API // https://jscomplete.com/repl?j=r1GN oiFBb const InputForm = React.createElement( "form", { target: "_blank", action: "https://google.com/search" }, React.createElement("div", null, "Enter input and click Search"), React.createElement("input", { name: "q", className: "input" }), React.createElement(Button, { label: "Search" })); // InputForm uses the Button component, so we need that too: function Button (props) { return React.createElement( "button", { type: "submit" }, props.label );} // Then we can use InputForm directly with .render ReactDOM.render(InputForm, mountN ode);
关于以上例子要注意的几点:
InputForm不是React组件; 它只是一个React元素。 这就是为什么我们直接在ReactDOM.render调用中使用它,而不是使用<InputForm />。
我们可以嵌套React.createElement调用,因为它都是JavaScript。
React.createElement的参数可以是null,也可以是一个空对象,当元素不需要attributes和props时。
我们可以将HTML元素与React组件混合使用。 您可以将HTML元素视为内置的React组件。
React的API尝试尽可能接近DOM API,因此我们为输入元素使用className而不是类。 私以为,我们都希望React的API将成为DOM API本身的一部分。
上面的代码是您在引入React库时了解的内容。 浏览器不用JSX业务。 然而,我们喜欢看HTML并且使用HTML而不是这些createElement调用(想象一下使用document.createElement构建一个网站,我相信你可以的!)。 这就是为什么存在JSX的原因。 我们可以用类似于HTML的语法编写它,而不是用React.createElement调用上面的表单:
// Example 4 - JSX (compare with Example 3) // https://jscomplete.com/repl?j=SJWy3otHW const InputForm = <form target="_blank" action="https://google.com/search"> <div>Enter input and click Search</div> <input name="q" className="input" /> <Button label="Search" /> </form>; // InputForm "still" uses the Button component, so we need that too. // Either JSX or normal form would do function Button (props) { // Returns a DOM element here. For example: return <button type="submit">{props.label}</button>;} // Then we can use InputForm directly with .render ReactDOM.render(InputForm, mountNode);
关于上面的例子注意以下几点
它不是HTML。 例如,我们仍然在使用className而不是类。
我们仍然在考虑将以上HTML作为JavaScript。 看看我在末尾添加了分号。
我们上面写的(例4)是JSX。 然而,我们在浏览器的执行版本是它的编译版本(示例3)。 为了实现这一点,我们需要使用预处理器将JSX版本转换为React.createElement版本。
那就是JSX。 这是一个折中,允许我们以类似于HTML的语法编写我们的React组件,这是一个好的共识。
上面标题中的“Flux”一词被选为韵脚(...),但它也是Facebook流行的受欢迎的应用程序架构的名称。 着名的实现是Redux。
JSX,顺便说一下,可以自己在其他地方使用。 这不是只有在React中才可以使用的。
3: 您可以在JSX中的位置使用JavaScript表达式
在JSX部分中,您可以在一对花括号内使用JavaScript表达式。
// Example 5 - Using JavaScript expressions in JSX // https://jscomplete.com/repl?j=SkNN3oYSW const RandomValue = () => <div> { Math.floor(Math.random() * 100) } </div>; // To use it: ReactDOM.render(<RandomValue />, mountN ode);
JavaScript表达式都可以放在那些花括号内。 这相当于JavaScript模板文字中的$ {}插值语法。
这是JSX中的约束:只有表达式。 所以,你不能使用常规的if语句,但是三元表达式是可以的。
JavaScript变量也是表达式,所以当组件接收到props列表(RandomValue组件没有,props是可选的)时,可以在花括号内使用这些props。 我们在上面的Button组件中这样做了(示例1)。
JavaScript对象也是表达式。 有时候,我们在一个花括号里面使用一个JavaScript对象,这使得它看起来像双花括号,但它实际上只是一个大括号内的一个对象。 一个用例是将CSS样式对象传递给React中的style属性:
// Example 6 - An object passed to the special React style prop // https://jscomplete.com/repl?j=S1Kw2sFHb const ErrorDisplay = ({message}) => <div style={ { color: "red", backgroundColor: "yellow" } }> {message} </div>; // Use it: ReactDOM.render( <ErrorDisplay message="These aren"t the droids you"re looking for" />, mountN ode);
请注意,我如何解析props参数中的message的。 这是JavaScript。 还要注意上面的style属性是一个的属性(再次,它不是HTML,它接近于DOM API)。 我们使用一个对象作为style属性的值。 该对象定义了样式,就像我们使用JavaScript一样(因为确实就是)。
可以在JSX中使用React元素,因为这也是一个表达式。 记住,一个React元素就是一个函数调用:
const MaybeError = ({errorMessage}) => <div> {errorMessage && <ErrorDisplay message={errorMessage} />} </div>; // The MaybeError component uses the ErrorDisplay component: const ErrorDisplay = ({message}) => <div style={ { color: "red", backgroundColor: "yellow" } }> {message} </div>; // N ow we can use the MaybeError component: ReactDOM.render( <MaybeError errorMessage={Math.random() > 0.5 ? "N ot good" : ""} />, mountN ode);
上面的MaybeError组件将只显示ErrorDisplay组件,如果有一个errorMessage字符串传递给它和一个空的div。 React将{true},{false},{undefined}和{null}视为没有呈现内容的元素子元素。
您还可以使用JSX内的集合上的JavaScript方法(map,reduce,filter,concat等)。 再次声明原因是因为它们返回的是表达式:
// Example 8 - Using an array map inside {}// https://jscomplete.com/repl?j=SJ29aiYH- const Doubler = ({value=[1, 2, 3]}) => <div> {value.map(e => e * 2)} </div>;// Use itReactDOM.render(<Doubler />, mountN ode);
请注意,我是如何给valueprops默认值的,因为它全是Javascript。 还要注意,我在div中输出了一个数组表达式,这在React中是可行的。 它将把一个值放在一个文本节点中。
4: 您可以使用JavaScript类编写React组件
简单的功能组件适合简单的需求,但有时我们需要多的功能。 React支持通过JavaScript类语法创建组件。 这是使用类语法编写的Button组件(在示例1中):
// Example 9 - Creating components using JavaScript classes // https://jscomplete.com/repl?j=ryjk0iKHb class Button extends React.Component { render() { return <button>{this.props.label}</button>; }} // Use it (same syntax) ReactDOM.render(<Button label="Save" />, mountN ode);
类语法很简单。 定义一个扩展了React.Component基类的类(需要学习的另一个的React API)。 该类定义一个实例函数render(),该render函数返回虚拟DOM对象。 每次我们使用上面的基于Button类的组件(例如,通过执行<Button ... />),React将从这个基于类的组件中实例化一个对象,并在DOM树中使用该对象。
这就是为什么我们在上面的渲染输出中在JSX中使用this.props.label的原因。 因为每个组件都获得一个称为props的实例属性,该实例属性在实例化时保存传递给该组件的值。
// Example 10 - Customizing a component instance // https://jscomplete.com/repl?j=rko7RsKS- class Button extends React.Component { constructor(props) { super(props); this.id = Date.n ow(); } render() { return <button id={this.id}>{this.props.label}</button>; }} // Use it ReactDOM.render(<Button label="Save" />, mountN ode);
我们还可以定义类属性函数,并在我们想使用的地方使用,包括返回的JSX输出内:
// Example 11 — Using class properties // https://jscomplete.com/repl?j=H1YDCoFSb class Button extends React.Component { clickCounter = 0;handleClick = () => { console.log(`Clicked: ${++this.clickCounter}`); }; render() { return ( <button id={this.id} onClick={this.handleClick}> {this.props.label} </button> ); }} // Use it ReactDOM.render(<Button label="Save" />, mountN ode);
关于例子11有几点需要注意
handleClick函数是使用JavaScript中新建的类字段语法编写的。这种语法仍然属于stage-2,,但由于很多原因,它是访问组件安装实例(由于箭头功能)的选择。 但是,您需要使用像Babel这样的编译器来配置它来理解stage-2,(或类字段语法)来获取上面的代码。 jsComplete REPL具有预配置。
我们还使用相同的类字段语法定义了ClickCounter实例变量。 这允许我们跳过使用类构造函数调用。
当我们将handleClick函数的onClick,React属性的值时,我们没有调用它。 我们把handleClick函数引用传递给出去了。 在这个属性里面调用函数是使用React的错误之一。
// Wrong: onClick={this.handleClick()} // Right: onClick={this.handleClick}
5: React中,两个重要的区别
在React元素中处理时,与DOM API的方式有两个重要的区别:
React元素属性使用camelCase命名,而不是小写。 它是onClick,而不是onclick。
我们传递一个实际的JavaScript函数引用作为处理程序,而不是一个字符串。 它是onClick = {handleClick},而不是onClick =“handleClick”。
使用自己的对象将DOM对象包装起来,以优化处理的性能。 但是在处理程序中,我们仍然可以访问DOM对象上可用的方法。 React将包装的对象传递给每个句柄调用。 例如,为了不让表单从默认提交操作中,您可以执行以下操作:
// Example 12 - Working with wrapped events // https://jscomplete.com/repl?j=HkIhRoKBb class Form extends React.Component { handleSubmit = (event) => { event.preventDefault(); console.log("Form submitted"); }; render() { return ( <form onSubmit={this.handleSubmit}> <button type="submit">Submit</button> </form> ); }} // Use it ReactDOM.render(<Form />, mountNode);
6: React组件都有故事
以下适用于类组件(扩展为React.Component的组件)。 函数组件有一个略有不同的故事。
我们为React定义一个模板,以从组件创建元素。
然后,我们指示React在某处使用它。 例如,在另一个组件的render调用中,或者使用ReactDOM.render。
然后,React实例化一个元素,并给出一组我们可以使用this.props访问的props。 那些props正是我们在上面的步骤2中传递的。
由于它都是JavaScript,所以构造方法将被调用(如果已经定义的话)。 这是我们要说的:组件生命周期方法。
然后React计算render方法(虚拟DOM节点)的输出。
由于这是React渲染元素,React将与浏览器进行通信(代表我们使用DOM API)来显示元素。 这个过程通常被称为挂载。
然后,React调用另一个生命周期方法,称为componentDidMount。 我们可以使用这种方法做一些事情,例如,在DOM上做一些我们现在知道在浏览器中支持处理的东西。 在此生命周期方法之前,我们处理的DOM是虚拟的。
一些组件故事在这里结束。 出于原因,其他组件可以从浏览器DOM中解除挂载。 在后一种情况发生之前,React调用另一个生命周期方法componentWillUnmount。
已挂载元件的状态可能会改变。 该元素的父代可能会重新呈现。 在任一种情况下,安装的元件可能会接收不同的props。 这里的发生了,我们现在开始需要React了! 在此之前,我们不需要做事情
这个组件的故事继续下去,但在之前,我们需要了解我所说的这个状态。
7: React组件有一个私有状态
以下适用于类组件。 有没有人提到有些人把只做展现的组件叫做哑巴?
状态类字段是React类组件中的字段。 React每个组件状态以进行修改。 但是对于React要执行这些操作,我们通过另一个需要学习的React API函数来修改state字段,this.setState:
// Example 13 - the setState API // https://jscomplete.com/repl?j=H1fek2KH- class CounterButton extends React.Component { state = { clickCounter: 0, currentTimestamp: new Date(), }; handleClick = () => { this.setState((prevState) => { return { clickCounter: prevState.clickCounter + 1 }; }); }; componentDidMount() { setInterval(() => { this.setState({ currentTimestamp: new Date() }) }, 1000); } render() { return ( <div> <button onClick={this.handleClick}>Click</button> <p>Clicked: {this.state.clickCounter}</p> <p>Time: {this.state.currentTimestamp.toLocaleString()}</p> </div> ); }} // Use it ReactDOM.render(<CounterButton />, mountNode);
这是了解state重要的例子。 它将完善您对React交互方式的基础知识。 在这个例子之后,还有一些你需要学习的小事情,但是从这一点来看,它主要是你和你的JavaScript技能。
我们来看一下实例13,从类字段开始。 它有两个。 状态字段被初始化为一个对象,该对象包含起始值为0的clickCounter,以及起始值为new Date()的currentTimestamp。
类字段是一个handleClick函数,我们传递给render方法中的button元素的onClick。 handleClick方法使用setState修改此组件实例状态。 注意到这一点。
我们在componentDidMount生命周期方法启动的间隔定时器中修改状态。 它每秒钟打勾并执行调用this.setState。
在render方法中,我们使用了正常读取语法对state两个属性的读取。 没有的API。
现在,请注意,我们使用两种不同的方式新了状态:
传递返回一个对象的函数。 我们handleClick函数中实现了这部分内容。
通过传递一个常规对象。 我们在间隔回调中实现了。
这两种方式都是可以接受的,但是当您同时读取和写入状态时在间隔回调之内,我们只写给状态,而不是读取它。 当两难时,使用函数参数语法。 setState实际上是一个异步方法。
我们如何状态? 我们返回一个包含我们要的值的对象。 注意在两次调用setState中,我们只是从state字段传递一个属性,而不是两者。 这是可以的,因为setState实际上将您传递的内容(函数参数的返回值)与现有状态合并。 因此,在调用setState时不选择属性意味着我们不希望改该属性(而不是删除它)。
8:React是可以响应的
React从它对状态变化做出响应(虽然不是反应性的,而是按计划进行)而得名。 有一个笑话,反应应该被命名为Schedule!
然而,当组件的状态被时,我们用肉眼看到的是React对该做出反应,并自动反映浏览器DOM中的(如果需要)。
将render函数输入视为两者
从父元素得到props
当渲染功能的输入变化时,其输出可能会改变。
React保留了渲染历史的记录,当它看到一个渲染与前一个渲染不同时,它将计算它们之间的差异,并将其转换为在DOM中执行的实际DOM操作。
9: React是你的代理
您可以将React视为我们聘请的与浏览器通信的代理。 以上面的当前时间戳显示为例。 我们不是手动去浏览器并调用DOM API操作p#timestamp元素,而是在组件状态上更改了一个属性,而React代表我们与浏览器进行通信。 我相信这是受欢迎的原因。
10: 每个React组件都有一个故事(第2部分)
现在我们知道一个组件的状态,以及当这个状态改变了的时候,让我们来学习关于该过程的几个概念。
组件可能需要在其状态时重新呈现,或者当其决定传递给组件的props时,该组件可能需要重新呈现
如果后者发生,React会调用另一个生命周期方法componentWillReceiveProps。
如果状态对象或传入props被改,则React有一个重要的决定。 组件应该在DOM中吗? 这就是为什么它在这里调用另一个重要的生命周期方法,shouldComponentUpdate。 这个方法是一个实际的问题,所以如果你需要自己定制或优化渲染过程,你通过返回true或false来回答这个问题。
如果没有customComponentUpdate,React默认是一个好的事情,在大多数情况下好。
React在此时调用另一个生命周期方法componentWillUpdate。 然后React将计算新的渲染输出并将其与渲染的输出进行比较。
如果渲染的输出一样,React不做。
如果存在差异,则React会将这些差异映射到浏览器内。
无论如何,由于过程无论如何(即使输出相同),React会调用的生命周期方法componentDidUpdate。
生命周期方法实际上是舱口。 如果你没有做事情,你可以创建没有他们的完整的应用程序。 他们可以用来方便地分析应用程序中发生的情况,并进一步优化了React新的性能。
Disclaimer: The content on this page is collected and edited by Jinghuang Network for reference only. We do not claim ownership or bear legal responsibility for external materials. If you find any copyright infringement, please contact us with proof, and we will remove the content within 5 working days. For more insights on Global Web Optimization and Global Web Development, please visit our official site (www.0731jianzhan.com).