この記事では主に react.js の使用法について説明し、react が思っているほど難しくないことを皆さんに理解してもらいます。それでは、この記事の具体的な内容を見てみましょう
1、Reactはすべてコンポーネント化されています
Reactは、再利用可能なコンポーネントの概念に基づいて設計されています。小さなコンポーネントを定義し、それらを組み合わせて大きなコンポーネントを形成します。
大小に関係なく、たとえ異なるプロジェクトであっても、すべてのコンポーネントは再利用可能です。
React コンポーネントの最も単純な形式は、単なる通常の JavaScript 関数です:
function Button (props) { // 这里返回一个 DOM元素,例如: return <buttontype="submit">{props.label}</button>; } // 将按钮组件呈现给浏览器 ReactDOM.render(<Buttonlabel="Save" />, mountNode)
例 1: 上記のコードを編集し、Ctrl+Enter を押して実行します (翻訳者注: この関数の翻訳は当面利用できません。この機能を使用するには原文を参照してください。以下同様)
括弧ラベル内のボタンについては後ほど説明します。今は心配しないでください。 ReactDOMについても後ほど説明しますが、この例と以下の例をすべてテストしたい場合は上記のrender関数が必要です。 (React が引き継いで制御するのは、ターゲット DOM 要素である ReactDOM.render の 2 番目のパラメーターです)。 jsComplete REPL では、特別な変数 mountNode を使用できます。
例 1 注:
コンポーネント名の最初の文字は大文字で、Buttonとなります。これは、HTML 要素と React 要素の混合を扱うことになるため必要です。小文字の名前は HTML 要素用に予約されています。実際、React コンポーネントに「button」という名前を付けると、ReactDOM がこの関数を無視し、通常の空の HTML ボタンとしてレンダリングすることがわかります。
すべてのコンポーネントは、HTML 要素と同様に、属性のリストを受け取ります。 React では、このリストをプロパティと呼びます。ただし、関数には好きな名前を付けることができます。
上記の Button 関数コンポーネントの戻り出力では、奇妙なことに HTML のように見えるコードを書きました。これは実際には JavaScript や HTML ではなく、正直に言うと React.js でもありません。しかし、非常に人気があるため、React アプリケーションのデフォルトになっています。これは JSX と呼ばれ、JavaScript 拡張機能です。 JSX も妥協です。上記の関数で他の HTML 要素を返してみて、それらがどのようにサポートされるかを確認してください (たとえば、テキスト入力要素を返すなど)。
2、JSXは何を出力しますか?
上記の例1は、次のようにJSXを使わずに純粋なReact.jsで書くことができます:
function Button (props) { return React.createElement( "button", { type: "submit" }, props.label ); } // 要使用 Button,你可以这么做 ReactDOM.render( React.createElement(Button, { label:"Save" }), mountNode );
例2: No J SX反応を書くコンポーネント
Reactトップレベル API では、createElement 関数がメイン関数です。これは、学習する必要がある 7 つの API のうちの 1 つです。 React の API は非常に小さいです。
DOM自体にタグ名で指定された要素を作成する document.createElement 関数があるのと同じように、React の createElement 関数は document.createElement と同じ機能を持つ高度な関数ですが、 React コンポーネントを表す要素。上記の例 2 で Button コンポーネントを使用する場合は、後者を使用します。
document.createElementとは異なり、React の createElement は、作成された要素の子要素を表す 2 番目のパラメーターを受け取った後に動的パラメーターを受け取ります。したがって、createElement は実際にツリーを作成します。
これはその例です: 例 3:React创建元素的 API 上面例子中的一些事情值得注意: InputForm 不是一个 React组件;它仅仅是一个 React 元素。这就是为什么我们可以在ReactDOM.render 中直接使用它并且可以在调用时不使用 React.createElement函数在前两个参数后接收了多个参数。从第3个参数开始的参数列表构成了创建元素的子项列表。 我们可以嵌套 React.createElement调用,因为它是 JavaScript。 当这个元素不需要属性时,React.createElement的第二个参数可以为空或者是一个空对象。 我们可以在 React 组件中混合HTML 元素。你可以将 HTML 元素作为内置的 React组件。 React 的 API试图和 DOM API 一样,这就是为什么我们在 input 元素中使用 className 代替 class 的原因。我们都希望如果 React 的 API 成为 DOM API 本身的一部分,因为,你知道,它要好得多。 上述的代码是当你引入 React 库的时候浏览器是怎样理解的。浏览器不会处理任何 JSX 业务。然而,我们更喜欢看到和使用 HTML,而不是那些 createElement 调用(想象一下只使用document.createElement 构建一个网站!)。这就是 JSX 存在的原因。取代上述调用 React.createElement 的方式,我们可以使用一个非常简单类似于HTML 的语法: 例 4:为什么在 React中 JSX 受欢迎(和例3 相比) 注意上面的几件事: 这不是 HTML 代码。比如,我们仍然可以使用 className 代替 class。 我们仍在考虑怎样让上述的 JavaScript看起来像是 HTML。看一下我在最后是怎样添加的。 我们在上面(例 4)中写的就是 JSX。然而,我们要将编译后的版本(例 3)给浏览器。要做到这一点,我们需要使用一个预处理器将 JSX 版本转换为 React.createElement 版本。 这就是 JSX。这是一种折中的方案,允许我们用类似 HTML 的语法来编写我们的 React 组件,这是一个很好的方法。 “Flux” 在头部作为韵脚来使用,但它也是一个非常受欢迎的应用架构,由 Facebook推广。最出名的是 Redux,Flux 和 React 非常合适。 JSX,可以单独使用,不仅仅适用于 React。 3、 你可以在 JavaScript的任何地方使用 JSX 在 JSX 中,你可以在一对花括号内使用任何 JavaScript 表达式。 例 5:在 JSX中使用 JavaScript 表达式 任何 JavaScript 表达式可以直接放在花括号中。这相当于在 JavaScript 中插入 ${} 模板。 这是 JSX 内唯一的约束:只有表达式。例如,你不能使用 if 语句,但三元表达式是可以的。 JavaScript 变量也是表达式,所以当组件接受属性列表时(不包括 RandomValue组件,props 是可选择的),你可以在花括号里使用这些属性。我们在上述(例 1)的 Button 组件是这样使用的。 JavaScript 对象也是表达式。有些时候我们在花括号中使用 JavaScript对象,这看起来像是使用了两个花括号,但是在花括号中确实只有一个对象。其中一个用例就是将 CSS 样式对象传递给响应中的特殊样式属性: 例 6:一个对象传递特殊的 React样式参数 注意我解构的只是在属性参数之外的信息。这只是 JavaScript。还要注意上面的样式属性是一个特殊的属性(同样,它不是 HTML,它更接近 DOM API)。我们使用一个对象作为样式属性的值并且这个对象定义样式就像我们使用 JavaScript 那样(我们可以这样做)。 你可以在 JSX 中使用 React 元素。因为这也是一个表达式(记住,一个 React 元素只是一个函数调用): 例 7:一个 React元素是一个可以通过 {} 使用的表达式 上述 MaybeError 组件只会在有errorMessage 传入或者另外有一个空的 p 才会显示 ErrorDisplay 组件。React 认为 {true}、 {false} {undefined} 和 {null} 是有效元素,不呈现任何内容。 我们也可以在 JSX 中使用所有的JavaScript 的集合方法(map、reduce 、filter、 concat 等)。因为他们返回的也是表达式: 例 8:在 {}中使用数组 请注意我是如何给出上述 value 属性的默认值的,因为这全部都只是 JavaScript。注意我只是在 p 中输出一个数组表达式。React 是完全可以的。它只会在文本节点中放置每一个加倍的值。 4、 你可以使用 JavaScript类写 React 组件 简单的函数组件非常适合简单的需求,但是有的时候我们需要的更多。React也支持通过使用 JavaScript 类来创建组件。这里 Button 组件(在例 1 中)就是使用类的语法编写的。 例 9:使用 JavaScript类创建组件 类的语法是非常简单的:定义一个扩展的 React.Component类(另一个你需要学习的 React 的顶级 API)。该类定义了一个单一的实例函数 —— render(),并使函数返回虚拟 DOM 对象。每一次我们使用基于类的 Button 组件(例如,通过 ),React 将从这个基于类的组件中实例化对象,并在 DOM 树中使用该对象。 这就是为什么上面的例子中我们可以在 JSX中使用 this.props.label 渲染输出的原因,因为每一个组件都有一个特殊的称为props 的 实例 属性,这让所有的值传递给该组件时被实例化。 由于我们有一个与组件的单个使用相关联的实例,所以我们可以按照自己的意愿定制该实例。例如,我们可以通过使用常规 JavaScript构造函数来构造它: 例 10:自定义组件实例 我们也可以定义类的原型并且在任何我们希望的地方使用,包括在返回的 JSX输出的内部: 例 11:使用类的属性(通过单击保存按钮进行测试) 注意上述例 11 中的几件事情 handleClick 函数使用 JavaScript 新提出的 class-field syntax 语法。这仍然是 stage-2,但是这是访问组件安装实例(感谢箭头函数)最好的选择(因为很多原因)。然而,你需要使用类似 Babel 的编译器解码为 stage-2(或者仅仅是类字段语法)来让上述代码工作。 jsComplete REPL 有预编译功能。 // 错误: onClick={this.handleClick()} // 正确: onClick={this.handleClick} 5、React中的事件:两个重要的区别 当处理 React 元素中的事件时,我们与 DOM API 的处理方式有两个非常重要的区别: 所有 React 元素属性(包括事件)都使用 camelCase 命名,而不是 lowercase。例如是 onClick 而不是 onclick。 我们将实际的 JavaScript 函数引用传递给事件处理程序,而不是字符串。例如是 onClick={handleClick} 而不是onClick="handleClick"。 React 用自己的对象包装 DOM对象事件以优化事件处理的性能,但是在事件处理程序内部,我们仍然可以访问 DOM对象上所有可以访问的方法。React 将经过包装的事件对象传递给每个调用函数。例如,为了防止表单提交默认提交操作,你可以这样做: 例 12:使用包装过的对象 6、每一个 React组件都有一个故事:第 1 部分 以下仅适用于类组件(扩展 React.Component)。函数组件有一个稍微不同的故事。 首先,我们定义了一个模板来创建组件中的元素。 然后,我们在某处使用 React。例如,在 render 内部调用其他的组件,或者直接使用 ReactDOM.render。 然后,React 实例化一个对象然后给它设置 props 然后我们可以通过 this.props 访问。这些属性都是我们在第 2 步传入的。 因为这些全部都是 JavaScript,constructor方法将会被调用(如果定义的话)。这是我们称之为的第一个:组件生命周期方法。 接下来 React 计算渲染之后的输出方法(虚拟 DOM 节点)。 因为这是 React 第一次渲染元素,React将会与浏览器连通(代表我们使用 DOM API)来显示元素。这整个过程称为 mounting。 接下来 React 调用另一个生命周期函数,称为 componentDidMount。我们可以这样使用这个方法,例如:在 DOM 上做一些我们现在知道的在浏览器中存在的东西。在此生命周期方法之前,我们使用的 DOM 都是虚拟的。 一些组件的故事到此结束,其他组件得到卸载浏览器 DOM中的各种原因。在后一种情况发生时,会调用另一个生命周期的方法,componentWillUnmount。 任何 mounted 的元素的状态都可能会改变。该元素的父级可能会重新渲染。无论哪种情况,mounted 的元素都可能接收到不同的属性集。React 的魔力就是这儿,我们实际上需要的正是 React 的这一点!在这一点之前,说实话,我们并不需要 React。 组价的故事还在继续,但是在此之前,我们需要理解我所说的这种状态。 7、React组件可以具有私有状态 以下只适用于类组件。我有没有提到有人叫表象而已的部件 dumb? 状态类是任何 React 类组件中的一个特殊字段。React 检测每一个组件状态的变化,但是为了 React 更加有效,我们必须通过 React 的另一个 API 改变状态字段,这就是我们要学习的另一个 API —— this.setState: 例 13:setState的 API 这可能是最重要的一个例子因为这将是你完全理解 React基础知识的方式。这个例子之后,还有一些小事情需要学习,但从那时起主要是你和你的 JavaScript 技能。 让我们来看一下例 13,从类开始,总共有两个,一个是一个初始化的有初始值为 0 的 clickCounter 对象和一个从 new Date() 开始的 currentTimestamp。 另一个类是 handleClick 函数,在渲染方法中我们给按钮元素传入 onClick 事件。通过使用 setState 的 handleClick 方法修改了组件的实例状态。要注意到这一点。 另一个我们修改状态的地方是在一个内部的定时器,开始在内部的componentDidMount生命周期方法。它每秒钟调用一次并且执行另一个函数调用this.setState。 在渲染方法中,我们使用具有正常读语法的状态上的两个属性(没有专门的 API)。 现在,注意我们更新状态使用两种不同的方式: 通过传入一个函数然后返回一个对象。我们在 handleClick函数内部这样做。 通过传入一个正则对象,我们在在区间回调中这样做。 这两种方式都是可以接受的,但是当你同时读写状态时,第一种方法是首选的(我们这样做)。在区间回调中,我们只向状态写入而不读它。当有问题时,总是使用第一个函数作为参数语法。伴随着竞争条件这更安全,因为 setstate实际上是一个异步方法。 ステータスを更新するにはどうすればよいですか?更新したい値を含むオブジェクトを返します。 setState を呼び出すときは、状態からプロパティを渡すか、何も渡さないことに注意してください。 setState は渡した関数の引数 (戻り値) を既存の状態と実際にマージするため、これは全く問題ありません。そのため、setState を呼び出すときにプロパティを指定しないということは、プロパティを変更したくない (削除はしない) ことを意味します。 8、Reactは反応します Reactの名前は、状態変化の反応に由来しています(反応はありませんが、スケジュールにもあります)。これは冗談ですが、React には Schedule という名前を付ける必要があります。 ただし、コンポーネントの状態が更新されると、私たちが肉眼で観察するのはその更新に対する反応であり、その更新はブラウザ DOM (必要に応じて) に自動的に反映されます。 レンダー関数への入力は 2 つのタイプとして考えてください: 親要素経由で渡されるプロパティ といつでも更新できる内部プライベート状態 レンダリング関数が変更されると、出力も変更される可能性があります。 React はレンダリングの履歴を保存し、以前のものと異なるレンダリングを見つけると、それらの差を計算し、それを DOM 操作で実行される実際の DOM に効果的に変換します。 9、React はあなたのコードです React はブラウザとの通信に使用するプロキシと考えることができます。例として、上記の現在のタイムスタンプの表示を見てみましょう。 p#timestamp 要素を見つけて更新するためにブラウザに手動でアクセスして DOM API オペレーションを毎秒呼び出す必要はなく、コンポーネントの state 属性を変更するだけで、React がブラウザとの通信作業を代わりに実行します。これが React が人気がある本当の理由だと私は信じています。私たちは Mr. Browser (そして React が話す DOM 言語の多くの方言) と話すのが好きではありません。
React は自主的に無料で私たちに渡されます。 10、すべての React コンポーネントにはストーリーがあります: パート 2 コンポーネントの状態がわかったので、その状態が変化するときのプロセスについて学びましょう。最後の概念をいくつか説明します。 コンポーネントの状態が更新されたとき、または親プロセスがコンポーネントに渡したプロパティを変更することを決定したとき、コンポーネントの再レンダリングが必要になる場合があります。 後者の場合、React は別のライフサイクル メソッド、componentWillReceiveProps を呼び出します。 状態オブジェクトまたは渡されたプロパティが変更された場合、Reactは重要な決定を下さなければなりません: コンポーネントを DOM で更新する必要があるか?このため、別の重要なライフサイクル メソッド shouldComponentUpdate が呼び出されます。このメソッドは実際的な問題であるため、レンダリング プロセスを自分でカスタマイズまたは最適化する必要がある場合は、true または false を返してこの質問に答える必要があります。 カスタム shouldComponentUpdate を使用しない場合、ほとんどの場合、React のデフォルト イベントは適切に処理されます。 まず、この時点で別のライフサイクル メソッド、componentWillUpdateが呼び出されます。 React は新しくレンダリングされた出力を計算し、最後にレンダリングされた出力と比較します。 レンダリングされた出力が以前と同じであれば、Reactは何もしません(ミスターブラウザと話す必要はありません)。 何かが異なる場合、前に見たように、React その違いをブラウザに伝えます。 いずれの場合も、アップデーターが発生すると、どのような方法であっても (同じ出力であっても)、React は最終ライフサイクル メソッド、componentDidUpdate を呼び出します。 ライフサイクルメソッドは脱出ハッチです。特別な操作を行わない場合は、これらを使用せずに完全なアプリケーションを作成できます。これらは、アプリケーションで何が起こっているかを分析し、React のパフォーマンスをさらに最適化するのに非常に便利ですUpdate この記事はここで終わります (さらに詳しく知りたい場合は、PHP 中国語 Web サイトReact ユーザー マニュアル 列にアクセスして学習してください) 、ご質問がございましたら、以下にメッセージを残していただけます。 以上がReact.jsの使い方は? React.js の簡単な使い方の紹介 (例付き)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。const InputForm = React.createElement(
"form",
{ target: "_blank", action:"https://google.com/search" },
React.createElement("p",null, "Enter input and click Search"),
React.createElement("input", {className: "big-input" }),
React.createElement(Button, { label:"Search" })
);
// InputForm 使用 Button组件,所以我们需要这样做:
function Button (props) {
return React.createElement(
"button",
{ type: "submit" },
props.label
);
}
// 然后我们可以通过 .render方法直接使用 InputForm
ReactDOM.render(InputForm, mountNode);
const InputForm =
<form target="_blank"action="https://google.com/search">
<p>Enter input and clickSearch</p>
<inputclassName="big-input" name="q" />
<Buttonlabel="Search" />
</form>;
// InputForm “仍然”使用 Button 组件,所以我们也需要这样。
// JXS 或者普通的表单都会这样做
function Button (props) {
// 这里返回一个 DOM元素。例如:
return <buttontype="submit">{props.label}</button>;
}
// 然后我们可以直接通过 .render使用 InputForm
ReactDOM.render(InputForm, mountNode);
const RandomValue = () =>
<p>
{ Math.floor(Math.random() * 100)}
</p>;
// 使用:
ReactDOM.render(<RandomValue />,mountNode);
const ErrorDisplay = ({message}) =>
<p style={ { color: 'red',backgroundColor: 'yellow' } }>
{message}
</p>;
// 使用
ReactDOM.render(
<ErrorDisplay
message="These aren't thedroids you're looking for"
/>,
mountNode
);
const MaybeError = ({errorMessage}) =>
<p>
{errorMessage &&<ErrorDisplay message={errorMessage} />}
</p>;
// MaybeError 组件使用 ErrorDisplay组件
const ErrorDisplay = ({message}) =>
<p style={ { color: 'red',backgroundColor: 'yellow' } }>
{message}
</p>;
// 现在我们使用 MaybeError组件:
ReactDOM.render(
<MaybeError
errorMessage={Math.random() >0.5 ? 'Not good' : ''}
/>,
mountNode
);
const Doubler = ({value=[1, 2, 3]}) =>
<p>
{value.map(e => e * 2)}
</p>;
// 使用下面内容
ReactDOM.render(<Doubler />, mountNode);
class Button extends React.Component {
render() {
return<button>{this.props.label}</button>;
}
}
// 使用(相同的语法)
ReactDOM.render(<Buttonlabel="Save" />, mountNode);
class Button extends React.Component {
constructor(props) {
super(props);
this.id = Date.now();
}
render() {
return <buttonid={this.id}>{this.props.label}</button>;
}
}
// 使用
ReactDOM.render(<Buttonlabel="Save" />, mountNode);
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>
);
}
}
// 使用
ReactDOM.render(<Buttonlabel="Save" />, mountNode);
class Form extends React.Component {
handleSubmit = (event) => {
event.preventDefault();
console.log('Form submitted');
};
render() {
return (
<formonSubmit={this.handleSubmit}>
<buttontype="submit">Submit</button>
</form>
);
}
}
// 使用
ReactDOM.render(<Form />, mountNode);
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 (
<p>
<buttononClick={this.handleClick}>Click</button>
<p>Clicked:{this.state.clickCounter}</p>
<p>Time:{this.state.currentTimestamp.toLocaleString()}</p>
</p>
);
}
}
// 使用
ReactDOM.render(<CounterButton />,mountNode);