一篇包含了react所有基本点的文章
去年,我写了一本关于学习React.js的小书,原来是大约100页。 今年我要挑战自己,把它归纳为一篇文章。 本文不会涵盖什么是React,或者为什么要学习它。 相反,这是面向已经熟悉JavaScript并熟悉DOM API基础知识的人,对React.js的基础知识的介绍。 以下所有代码示例均标示为参考。 它们纯粹是为了提供概念而写的例子。 他们大多数可以写得更好一些。 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也将在后面解释,但是如果要测试这个例子和接下来的代码示例,
关于示例1的注意事项有以下几点:
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,如下所示:
很像DOM本身有一个 与 这是一个例子: / Example 3 - React’s createElement API // https://jscomplete.com/repl?j=r1GNoiFBb 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",props.label ); } // Then we can use InputForm directly with .render ReactDOM.render(InputForm,mountNode); 关于以上例子要注意的几点:
上面的代码是您在引入React库时了解的内容。 浏览器不处理任何JSX业务。 然而,我们人类喜欢看HTML并且使用HTML而不是这些 // 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); 关于上面的例子注意以下几点
我们上面写的(例4)是JSX。 然而,我们在浏览器的执行版本是它的编译版本(示例3)。 为了实现这一点,我们需要使用预处理器将JSX版本转换为 那就是JSX。 这是一个折中,允许我们以类似于HTML的语法编写我们的React组件,这是一个很好的共识。
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 />,mountNode); 任何JavaScript表达式都可以放在那些花括号内。 这相当于JavaScript模板文字中的 这是JSX中唯一的约束:只有表达式。 所以,你不能使用常规的if语句,但是三元表达式是可以的。 JavaScript变量也是表达式,所以当组件接收到 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" />,mountNode ); 请注意,我如何仅解析 甚至可以在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>; // Now we can use the MaybeError component: ReactDOM.render( <MaybeError errorMessage={Math.random() > 0.5 ? 'Not good' : ''} />,mountNode ); 上面的 您还可以使用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 it ReactDOM.render(<Doubler />,mountNode); 请注意,我是如何给 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" />,mountNode); 类语法很简单。 定义一个扩展了React.Component基类的类(需要学习的另一个顶级的React API)。 该类定义一个唯一实例函数render(),该render函数返回虚拟DOM对象。 每次我们使用上面的基于Button类的组件(例如,通过执行<Button ... />),React将从这个基于类的组件中实例化一个对象,并在DOM树中使用该对象。 这就是为什么我们在上面的渲染输出中在JSX中使用 // Example 10 - Customizing a component instance // https://jscomplete.com/repl?j=rko7RsKS- class Button extends React.Component { constructor(props) { super(props); this.id = Date.now(); } render() { return <button id={this.id}>{this.props.label}</button>; } } // Use it ReactDOM.render(<Button label="Save" />,mountNode); 我们还可以定义类属性函数,并在我们想使用的地方使用,包括返回的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" />,mountNode); 关于例子11有几点需要注意
// Wrong: onClick={this.handleClick()} // Right: onClick={this.handleClick} 5: React的事件中,两个最重要的区别在React元素中处理事件时,与DOM API的方式有两个非常重要的区别:
使用自己的对象将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的组件)。 函数组件有一个略有不同的故事。
7: React组件有一个私有状态以下也仅适用于类组件。 有没有人提到有些人把只做展现的组件叫做哑巴? 状态类字段是任何React类组件中的特殊字段。 React监视每个组件状态以进行更改。 但是对于React要有效地执行这些操作,我们必须通过另一个需要学习的React API函数来更改state字段, // 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); 这是了解 我们来看一下实例13,从类字段开始。 它有两个。 特殊状态字段被初始化为一个对象,该对象包含起始值为0的 第二个类字段是一个 我们在 在render方法中,我们使用了正常读取语法对state两个属性的读取。 没有特殊的API。 现在,请注意,我们使用两种不同的方式更新了状态:
这两种方式都是可以接受的,但是当您同时读取和写入状态时,第一个是首选的(我们这样做)。 在间隔回调之内,我们只写给状态,而不是读取它。 当两难时,始终使用第一个函数参数语法。 它更加安全,因为 我们如何更新状态? 我们返回一个包含我们要更新的值的对象。 注意在两次调用 8:React是可以响应的React从它对状态变化做出响应的事实(虽然不是反应性的,而是按计划进行)而得名。 有一个笑话,反应应该被命名为Schedule! 然而,当任何组件的状态被更新时,我们用肉眼看到的是React对该更新做出反应,并自动反映浏览器DOM中的更新(如果需要)。 将render函数输入视为两者
当渲染功能的输入变化时,其输出可能会改变。 React保留了渲染历史的记录,当它看到一个渲染与前一个渲染不同时,它将计算它们之间的差异,并将其有效地转换为在DOM中执行的实际DOM操作。 9: React是你的代理您可以将React视为我们聘请的与浏览器通信的代理。 以上面的当前时间戳显示为例。 我们不是手动去浏览器并调用DOM API操作来每秒查找和更新p#timestamp元素,而是在组件状态上更改了一个属性,而React代表我们与浏览器进行通信。 我相信这是真正受欢迎的真正原因。 我们讨厌浏览器(和所说的DOM语言的很多方言),React自愿为我们做所有的谈话,免费! 10: 每个React组件都有一个故事(第2部分)现在我们知道一个组件的状态,以及当这个状态改变了一些魔法的时候,让我们来学习关于该过程的最后几个概念。
生命周期方法实际上是舱口。 如果你没有做任何事情,你可以创建没有他们的完整的应用程序。 他们可以用来非常方便地分析应用程序中发生的情况,并进一步优化了React更新的性能。 根据以上学到的东西(或其中的一部分,真的),您就可以开始创建一些有趣的React应用程序。 如果您渴望了解更多信息,请访问我们的Plactsight的React.js课程入门: 翻译自All the fundamental React.js concepts,jammed into this single Medium article 关注我的公众号,更多优质文章定时推送
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |