发布于:2021-02-01 15:50:20
0
125
0
在上一篇关于从头开始学习React的博客文章中,我开始通过ReactJS.org的教程进行工作。我通过复制和粘贴代码构建了我的第一个应用程序……但是它起作用了!今天,我希望了解一些我运行的代码。让我们开始吧。
这一点我想我明白了。React.Component
是一个基本组件类,我们创建了一个扩展它的ShoppingList
类。我猜组件需要有一个render()
方法,它返回一些HTML元素来呈现。这个创建了一个带有className
属性的——这与HTMLclass
属性类似吗?--它包含一个标题(<h1>)和一个无序列表(<ul>),其中列出了Mark想要购买的所有公司。
我猜,this.props.name
访问this
的props
变量,我想它引用了ShoppingList
类的实例。它访问name
,这是在示例中的类XML标记中定义的。如果您可以任意定义这样的属性,那么这种语法非常酷。如果我们不把一个name
传给ShoppingList
呢?代码是否抛出错误?或者只渲染{this.props.name}
应该在的地方?
“当我们的数据更改时,React将有效地更新和重新呈现我们的组件。”
所以它是一个反应式编程框架,就像我想的。这是有道理的,因为它的名字。
“这里,ShoppingList是一个反应组件类,或者反应组件类型。组件接受名为props
(properties的缩写)的参数,并通过render
方法返回要显示的视图层次结构。“
这或多或少是我的想法,但我不明白“视图层次”是什么意思。教程中说,上面的代码块看起来很像HTML,也可以写成:
React.createElement("div", { className: "shopping-list" },
React.createElement("h1", null, "Shopping List for ", props.name),
React.createElement("ul", null,
React.createElement("li", null, "Instagram"),
React.createElement("li", null, "WhatsApp"),
React.createElement("li", null, "Oculus")
)
);
这让我想起了JavaFX与没有FXML的区别。使用FXML构建javagui时,标记更像XML。如果没有它,它看起来更像上面的代码块,其中的函数和属性是使用点(.)操作符访问的。“API参考中对createElement
进行了更详细的描述”,教程中说,因此我点击了该链接,希望找到一些规范的代码:
文件看起来真不错。很容易理解。I thnik[props]
是属性列表吗?但是,当我们在上面的代码块中使用它时,我们用大括号({className: 'shopping-list'}
)将第二个参数发送到createElement
。当我们把[...children]
的变量列表传递给createElement
时,它并没有用大括号括起来。。。我有点糊涂了。也许有两种名单?一个是单子,一个是词典(或地图)?
因此,我们可以从较小的组件中逐个构建应用程序,在较大的组件中使用它们。下一步是检查我在上一个条目中复制和粘贴的JavaScript代码:
import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; class Square extends React.Component { render() { return ( <button className="square"> {/* TODO */} </button> ); } } class Board extends React.Component { renderSquare(i) { return <Square />; } render() { const status = 'Next player: X'; return ( <div> ...
这看起来不言自明。如教程所述,我们有一个Square
类和一个Board
类,它们为tic-tac-toe游戏呈现九个方块。我猜有些事情还没完成,我得去编码了。
……没错。下一步是填两个小东西,我们尝试一下
renderSquare(i) { return <Square />; }
至
renderSquare(i) { return <Square value={i} /> }
并改变
{/* TO-DO */}
至
{this.props.value}
这将传递要在按钮上呈现的正方形的“值”。我更改此代码并再次运行npm start
。同样,它需要非常长的时间来渲染。但它确实有用。。。
…所以这是一件事。
祝贺你!您刚刚“传递了一个道具”从父级Board到子级Square组件。传递道具是信息如何在React应用程序中流动,从父类到子类。
接下来我们要做的是在Square
中的button
中添加一个onClick
方法,它将打开一个JavaScriptalert()
框。我在几年前的JavaScript体验中见过这类东西,所以它们对我来说不是很难。
我们要做的下一件事是用“arrow函数”替换onClick
函数,因为它们显然是在JavaScript中调用的。我认为大多数其他编程语言将它们称为“lambda函数”:
onClick={function() { alert('click'); }}
…变成…
onClick={() => alert('click')}
省去了一点打字。本教程一定要注意,我们需要向onClick
传递一个函数。如果我们只写…
onClick={alert('click')}
…然后每次组件重新渲染时都会触发警报。这大概不是我们想要的。
接下来,我们将state
添加到Square
类中,这样它就可以“记住”它是否被点击了。我认为,这类似于大多数OOP语言中的实例/成员变量。看起来我们可以在类定义中的constructor
函数中设置React对象
class Square extends React.Component { constructor(props) { super(props); this.state = { value: null }; } }
这里有两件事:
这个Square
类显然是用super()
调用父类的构造函数(React.Component
),将props
传递给父类构造函数。
教程实际上在null
后面有一个逗号,我假设它是一个输入错误
在JavaScript类中,定义子类的构造函数时,始终需要调用super
。所有具有constructor
调用的React组件类都应该以super(props)
调用开始。
看起来super(props)
在任何子类的constructor
中都是必需的。我想知道它是否一定是构造器的第一行,就像Java。。。?上面的摘录有点模棱两可。
然后,我们使用setState()
更改button
的onClick
以更改按钮的状态,这似乎很简单。
onClick={() => alert('click')}
更改为
onClick={() => this.setState({value: 'X'})}
这听起来像是一种被动依赖。如果一个对象更新而其他对象依赖于它,那么这些依赖对象也会更新。
我要做的最后一件事是安装React Developer Tools Chrome扩展,以便在浏览器中检查我的React代码:
我已经开始明白React是怎么工作的了。看到像类、构造函数和lambda函数这样熟悉的东西让我更加自信,这是我能够很容易学会的东西。到目前为止,我基本上只是在类固醇上做了些什么,所以我希望这个框架能做得更多。我期待着做一些很酷的互动网页!
作者介绍