1. React フレームワークの概要
-
導入
BS と組み合わせた CS:
React
このVue
タイプのフレームワークは、サーバーの機能の一部をクライアントに転送します。CS
と を組み合わせますBS
。クライアントはサーバーに一度リクエストするだけで済み、サーバーはすべての js コードをクライアントに返し、すべての対話型操作はサーバーに依存しなくなります。クライアントは、json
サーバーからのデータが必要な場合にのみ通信を使用し、それ以外の場合はjs
操作を使用したり、データを一時的に保存したりするため、サーバーへの負荷が大幅に軽減されます。 -
反応機能
○ 仮想 DOM ツリー
React
をシミュレートすることでDOM
、 との相互作用が最小限に抑えられますDOM
。Webページのツリーを完全にコピーし、DOM
仮想DOM
ツリーをメモリ上に置きます。○ データドリブン
仮想
DOM
ツリーを維持します。一部のノードが変更されたことが判明した場合、元のDOM
ツリー (Web ページ上に表示されるすべての領域) を必ずしも変更する必要はありません。たとえば、特定のブランチが変更される可能性がある場合、仮想ツリーは最初に変更されます。これらのノードは、元のノードと比較されます。実際に変更されるノードのみが変更されます。
○JSXファイルインタラクティブなユーザー インターフェイスを構築するには、
JSX
.JSX
の完全バージョンは、JavaScript
コンポーネントの作成を大幅に簡素化する構文拡張機能です。参照をサポートしHTML
、子コンポーネントのレンダリングを容易にします。これは基本的に、書き込みショートカットのセットですReact
。いくつかのルールを使用すると、createElement
ソース コードがより読みやすく、わかりやすくなります。まずjsxファイルを書きます、実行時には書き込んだjsx
ファイルがjsxファイルにコンパイルされjs
、コンパイル後js
ブラウザ上で実行されます。 -
リアクション機能
React
主に構築用の言語フレームワークを一般化および最適化しますUI
。React
ここでは、レンダリングに役立つ宣言コードUI
、静的HTML DOM
要素、動的変数、対話型アプリケーション コンポーネントなど、さまざまなタイプのパラメーターを渡すことができ、優れたパフォーマンスとシンプルなコード ロジックを備えています。
2. 構成環境
Git Bash
Git bashのインストールダウンロード リンク
Git Bash インストール チュートリアルNode.js
Nodejsのインストールダウンロード リンク
Nodejs インストール チュートリアルcreate-react-app
インストールを開きGit Bash
、次のコマンドを直接入力して実行しますnpm i -g create-react-app
- React App という名前の React プロジェクトを作成し、
ターゲット ディレクトリ (プロジェクトを保存するディレクトリ) を右クリックして Git Bash を開き、次のコマンドを実行します。create-react-app react-app # react-app可以替换为其它名称
- プロジェクトを開始し
、ディレクトリに入り、react-app レイヤーに入り、Git Bash を開いて次のコマンドを入力します。npm start # 启动应用
3. コンポーネント
コンポーネントはクラスに似ており、いくつかの HTML、データ、イベント関数を 1 つのコンポーネントに結合します。
-
コンポーネントの定義: コンポーネントを定義した後、コンポーネントをレンダリングする必要があります。index.js はすべての js のエントリ ポイントであり、React コンポーネントとコンポーネント コンポーネントを導入します。
// box.js 文件 import React, { Component } from 'react'; // 快捷键:imrc // 引入React原因:将jsx编译为js // 通过React.createElement() class Box extends Component { // 快捷键:CC state = { } //局部变量 // component类的函数,用来返回当前组件最后的渲染html结构 // render方法只能返回一个标签及所包含内容 render() { return ( <h1> Hello world</h1> ); } } export default Box;
// index.js 文件 import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css'; import 'bootstrap/dist/css/bootstrap.css'; // 引入bootstrap库 import Box from './components/box'; // 引入box const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <React.StrictMode> <Box /> // Box组件,见box.js </React.StrictMode> );
-
React Fragment の導入と使用:
(1)
render()
このメソッドはラベルとその内容を 1 つだけ返すことができるため、複数の並列ラベルを返したい場合は、それらを 1 つのラベルに含める必要があります。
(2)コンポーネントをReact.Fragment
使用すると、追加の要素を作成せずにメソッドが複数の要素を返すことができDOM
ます。追加のタグを追加せずにサブリストをグループ化できるようにします。render()
Fragments
DOM
コンポーネントを定義するときは、
return
最も外側のパッケージをdiv
ページにレンダリングしたくない場合が多いため、Fragment
コンポーネントを使用する必要があると理解されています。class Box extends Component { state = { } render() { return ( <React.Fragment> <h1> Hello world</h1> <button>left</button> <button>right</button> </React.Fragment> ); } }
-
jsxでjsタグやhtmlタグを記述する場合、タグは
jsx
どこにでも定義できますhtml
が、タグでコードを記述する場合はタグで囲む必要がjsx
あり、式のみ記述できることに注意してください。html
js
{}
{}
render() { return ( <React.Fragment> <h1>{ this.toString()}</h1> // html 标签内写js <button className="btn btn-primary">left</button> <button>right</button> </React.Fragment> ); } toString(){ return `x: ${ this.state.x}`; // 或者 // const {x} = this.state; //ES6写法相当于const xxx = this.state.xxx // return `x:${x}`; }
-
スタイルを設定する
cssスタイル用のjsxファイル配下のhtmlタグにクラス名を設定する場合は、
class =" "
のように記述する必要がありますclassName
。jsx上ではhtmlタグとjs文が混在しているため、クラスを書くと実際のjs内の同名のクラスと競合する可能性があります。className
return ( <React.Fragment> <h1>{ this.toString()}</h1> <button className="btn btn-primary m-2">left</button> <button className="btn btn-success m-2">right</button> </React.Fragment> // m-2 为 bootstrap 中 margin=2 的简写方式 );
style
render() { return ( <React.Fragment> // style样式:第一层{}代表里面是表达式,第二层{}代表里面是对象,即样式变量的内容 <div style={ { width: "50px", height: "50px", backgroundColor: "pink", color: "white", textAlign: "center", lineHeight: "50px", borderRadius: "5px", }}>{ this.toString()}</div> <button className="btn btn-primary m-2">left</button> <button className="btn btn-success m-2">right</button> </React.Fragment> ); }
に相当:
styles = { width: "50px", height: "50px", backgroundColor: "pink", // css中所有 - 命名均改为驼峰命名法 } render() { return ( // 标签内 style={this.styele} 即可 <React.Fragment> <div style={ this.styles}>{ this.toString()}</div> <button className="btn btn-primary m-2">left</button> <button className="btn btn-success m-2">right</button> </React.Fragment> ); }
-
データドリブンなスタイルの変化
style
(ローカル変数) 値にstate
関連付けられ、state
その値を変更することで変更されますstyle
。ローカル変数が変更されると、インターフェイス実装を通じてこの値の影響を受けるすべてのコンポーネントが変更されます。state = { x: 1, } getStyles() { let styles = { width: "50px", height: "50px", backgroundColor: "pink", color: "white", textAlign: "center", lineHeight: "50px", borderRadius: "5px", margin: '5px', }; if (this.state.x === 0){ styles.backgroundColor = 'orange'; // 数据驱动改变style } return styles; }
render() { return ( // 直接调用 getStyles()函数 <React.Fragment> <div style={ this.getStyles()}>{ this.toString()}</div> <button className="btn btn-primary m-2">left</button> <button className="btn btn-success m-2">right</button> </React.Fragment> ); }
-
レンダーリスト
map
機能を利用するトラバーサル クラスの記述方法では、変更された要素をすばやく見つけられる
key
ように、タグ要素ごとに一意の属性を定義する必要があります。React
DOM
class Box extends Component { state = { x: 1, colors: ['red','green','blue'], // 定义渲染列表,这里用来修改div元素内容 } render() { return ( <React.Fragment> { this.state.colors.map(color => ( <div key={ color}>{ color}</div> // 这里建立div并将内容赋值为上述列表 ))} </React.Fragment> ); } }
-
条件付きレンダリング
A && B && C ...
: 前から後ろに、 の最初false
の式を返します。(すべてが true の場合、最後の true 式を返します)
A || B || C ...
: 前から後ろに、最初のtrue
式を返します。(すべてが false の場合、最後の false 式が返されます。)つまり、利用原理
逻辑表达式
は次のとおりです短路
。render() { return ( <React.Fragment> { this.state.colors.length === 0 && <p> No colors</p>} // 即当 colors 有元素时无操作, 即当 colors 无元素时显示 No color { this.state.colors.map(color => ( <div key={ color}>{ color}</div> ))} </React.Fragment> ); }
-
バインドイベント
eq は
button
イベントをボタンにバインドします。class Box extends Component { handleClickLeft(){ console.log("click left",this); } handleClickRight(){ console.log("click right",this); } render() { //仅仅是绑定函数,而不是在渲染时就将返回值传过来,因此handleClickleft不加() return ( <React.Fragment> <div style={ this.getStyles()}>{ this.toString()}</div> <button onClick={ this.handleClickLeft} className="btn btn-primary m-2">left</button> <button onClick={ this.handleClickRight} className="btn btn-success m-2">right</button> </React.Fragment> } }
このとき、出力はクラスでは
this
なく、.Box
undifind
メソッド内でこれを引き続き Box クラスに所属させる方法:
// メソッド 1: アロー関数 (推奨)
// メソッド 2: バインド関数コードは以下のように表示されます。
handleClickLeft=()=>{ // 法一:箭头函数 console.log("click left",this); } handleClickRight(){ console.log("click right",this); } render() { return ( <React.Fragment> <div style={ this.getStyles()}>{ this.toString()}</div> <button onClick={ this.handleClickLeft} className="btn btn-primary m-2">left</button> <button onClick={ this.handleClickRight.bind(this)} className="btn btn-success m-2">right</button> </React.Fragment> // 法二:bind函数 ); }
-
stateの値を変更します
this.state.x を直接指定します - ページ div の表示される x 値には影響しません。
状態内の x の変更がレンダリング関数に影響を与えたい場合は、setState() 関数を使用する必要があります (re-div によって div を変更します)。 render) x 値) の呼び出しclass Box extends Component { state = { x: 1, } handleClickLeft = () => { this.setState({ // setState() 函数 x: this.state.x - 1 }); } handleClickRight = () => { this.setState({ // setState() 函数 x: this.state.x + 1 }); } render() { return ( <React.Fragment> <div style={ this.getStyles()}>{ this.toString()}</div> <button onClick={ this.handleClickLeft} className="btn btn-primary m-2">left</button> <button onClick={ this.handleClickRight} className="btn btn-success m-2">right</button> </React.Fragment> ); } }
-
ボタンを使用して CSS プロパティを変更します。
state
特定のスタイルの属性に値を割り当て、スタイルstate
を変更するボタンを使用して値を変更します。css
class Box extends Component { state = { x: 10, // state值 } handleClickLeft = () => { this.setState({ x: this.state.x - 10 // setState() 修改 state值, 重新调用 render() 函数 }); } handleClickRight = () => { this.setState({ x: this.state.x + 10 // setState() 修改 state值,重新调用 render() 函数 }); } render() { return ( <React.Fragment> <div style={ this.getStyles()}>{ this.toString()}</div> <button onClick={ this.handleClickLeft} className="btn btn-primary m-2">left</button> <button onClick={ this.handleClickRight} className="btn btn-success m-2">right</button> </React.Fragment> ); } getStyles() { let styles = { width: "50px", height: "50px", backgroundColor: "pink", color: "white", textAlign: "center", lineHeight: "50px", borderRadius: "5px", margin: '5px', marginLeft: this.state.x, // state值赋值给 css 属性值 }; if (this.state.x === 0){ styles.backgroundColor = 'orange'; } return styles; } }
-
イベント関数にパラメータを追加する
handleClickRight = (step) => { this.setState({ x: this.state.x + step }); }
handleClickRightTmp = () => { return this.handleClickRight(50); }
render() { return ( <React.Fragment> <div style={ this.getStyles()}>{ this.toString()}</div> <button onClick={ this.handleClickLeft} className="btn btn-primary m-2">left</button> <button onClick={ this.handleClickRightTmp} className="btn btn-success m-2">right</button> </React.Fragment> ); }
handleClickRight()
関数をアロー匿名関数として記述することは、次と同等です。render() { // 绑定了一个调用含参 函数 handleClickLeft =(step)=>{ } 的匿名函数 return ( <React.Fragment> <div style={ this.getStyles()}>{ this.toString()}</div> <button onClick={ ()=>this.handleClickLeft(10)} className="btn btn-primary m-2">left</button> <button onClick={ ()=>this.handleClickRight(10)} className="btn btn-success m-2">right</button> </React.Fragment> ); }
要約すると、Box コンポーネントを構築する手順は次のとおりです。
- 変数を定義して
state
データ駆動型にしますstyle
。 - パラメーターを使用して handleClickLeft =(step)=>{ } 関数を構築し、
setState()
その関数を使用してstate
値を変更します。
调用setState()能够重新加载 render 函数,才可以对里面的 div 显示进行修改
- 記述した関数をボタンのクリック イベントにバインドします
onClick
。
这里绑定了一个调用含参函数 handleClickLeft =(step)=>{ } 的匿名函数,()=>this.handleClickRight(10)
class Box extends Component { // 1. 定义 state,并使得数据驱动style state = { x: 10, } // 2. 通过 handleClickLeft =(step)=>{ } 带参函数 与 setState() 改变state值 // 并能够重新加载 render 函数来对里面的 div 显示进行操作 handleClickLeft = (step) => { this.setState({ x: this.state.x - step }); } handleClickRight = (step) => { this.setState({ x: this.state.x + step }); } render() { // 3. 给事件绑定函数:通过 render 函数里,按钮事件绑定函数。 // 绑定了一个调用含参函数 handleClickLeft =(step)=>{ } 的匿名函数 return ( <React.Fragment> <div style={ this.getStyles()}>{ this.toString()}</div> <button onClick={ ()=>this.handleClickLeft(10)} className="btn btn-primary m-2">left</button> <button onClick={ ()=>this.handleClickRight(10)} className="btn btn-success m-2">right</button> </React.Fragment> ); } getStyles() { let styles = { width: "50px", height: "50px", backgroundColor: "pink", color: "white", textAlign: "center", lineHeight: "50px", borderRadius: "5px", margin: '5px', marginLeft: this.state.x, // 数据驱动 style }; if (this.state.x === 0){ styles.backgroundColor = 'orange'; } return styles; } }
4. コンポーネントコンポーネントの組み合わせと相互作用
-
【複合コンポーネント】コンポーネントの構成
上記で定義した複数の
Box
コンポーネントを組み合わせてBoxes
コンポーネントを形成し、属性
値の転送を完了します。
<注:多个相同子组件时,每个子组件需要有唯一 key 值
>○複数のコンポーネント
Boxes
を含むクラスコンポーネントを作成するBox
import React, { Component } from 'react'; import Box from './box'; class Boxes extends Component { // 1. 设置 state 变量,包括 Box 组件的唯一 key 值与 x 坐标值。 state = { boxes:[ { id: 1, x: 10}, { id: 2, x: 10}, { id: 3, x: 100}, { id: 4, x: 10}, { id: 5, x: 10}, ] } // 2. render 函数返回多个 box 组件,通过 map 列表,逐一建立并赋值多个 Box 组件 // 将 box.id 赋值给组件唯一 key,将 box.x 赋值给 Box 组件的 x render() { return ( <React.Fragment> { this.state.boxes.map((box)=>( <Box key = { box.id} // id x = { box.x} // 这里会自动找到 Box 组件里的 x 赋值并存储在 props 中 // 但仅仅是修改了x,并不会改变前端的显示 /> ))} </React.Fragment> ); } } export default Boxes;
[注意] React コンポーネント間の通信は
props
属性を介して行われます。たとえば、親コンポーネントが子コンポーネントにデータを渡す必要がある場合、コンポーネントが子コンポーネントをレンダリングするときに、子コンポーネントのプロパティ パラメータとしてデータを直接渡します。 。○ 状態値の受け渡し:に渡された定義済みの属性値
props
を返します。Boxes
Box
state
class Box extends Component { state = { // props类似于state,存储除key以外属于 box 的所有属性 // Boxes 建立的 Box 赋值的 x 存到了 props 里 // 通过 props 传递给了每个 Box x: this.props.x, } handleClickLeft = (step) => { this.setState({ x: this.state.x - step }); } handleClickRight = (step) => { this.setState({ x: this.state.x + step }); } render() { return ( <React.Fragment> <div style={ this.getStyles()}>{ this.toString()}</div> <button onClick={ ()=>this.handleClickLeft(10)} className="btn btn-primary m-2">left</button> <button onClick={ ()=>this.handleClickRight(10)} className="btn btn-success m-2">right</button> </React.Fragment> ); } getStyles() { let styles = { width: "50px", height: "50px", backgroundColor: "pink", color: "white", textAlign: "center", lineHeight: "50px", borderRadius: "5px", margin: '5px', marginLeft: this.state.x, }; if (this.state.x === 0){ styles.backgroundColor = 'orange'; } return styles; } toString(){ return `x: ${ this.state.x}`; } } export default Box;
○ラベル転送:
props
追加Boxes
したBox.children
サブラベルをBox
// Boxes.jsx文件 render() { return ( <React.Fragment> { this.state.boxes.map((box)=>( <Box key = { box.id} x = { box.x}> <p>Box :</p> // 将 Box 的闭合标签写为双标签 <div>{ box.id}</div> // 可在 Box 标签内增加其它标签,属性名为 Box.children </Box> // 并存储到了 props 中 ))} </React.Fragment> ); }
// Box.jsx 文件 render() { console.log(this.props); return ( <React.Fragment> { this.props.children[0]} // 通过 props 所存储的 children 将增加的标签传递给Box <div style={ this.getStyles()}>{ this.toString()}</div> <button onClick={ ()=>this.handleClickLeft(10)} className="btn btn-primary m-2">left</button> <button onClick={ ()=>this.handleClickRight(10)} className="btn btn-success m-2">right</button> </React.Fragment> ); }
○ メソッド渡し 1: React 子コンポーネントが親コンポーネントのメソッドを呼び出します。
Box
子コンポーネントがBoxes
親コンポーネントのメソッドを呼び出すときも、 を渡しますprops
。Box
コンポーネント内でイベントがトリガーされた後onClick
、対応する値がBoxes
コンポーネント内で削除されます。つまり、ラベル内のラベルを呼び出すメソッドです。key
Box
Box
Boxes
// Boxes.jsx 文件 // 1. Boxes.jsx 文件中写删除的方法 handleDelete = (id) => { // filter: boxes列表的元素依次判断,若表达式为true则留下,否则删掉 // 即若id不等留下来,相等删除 const newboxes = this.state.boxes.filter( (x)=>(x.id !== id) ); this.setState({ boxes: newboxes }) } render() { if(this.state.boxes.length === 0){ return <div className='alert alert-dark'>没有元素可以删除了!!!</div> } return ( // 2. 将所写删除方法定义为标签的 onDelete 属性传递给 Box(会存储在 props中) <React.Fragment> { this.state.boxes.map((box)=>( <Box key = { box.id} id={ box.id} x = { box.x} onDelete = { this.handleDelete}> <p>Box :</p> <div>{ box.id}</div> </Box> ))} </React.Fragment> ); }
// Box.jsx 文件 render() { return ( <React.Fragment> { this.props.children[0]} <div style={ this.getStyles()}>{ this.toString()}</div> <button onClick={ ()=>this.handleClickLeft(10)} className="btn btn-primary m-2">left</button> <button onClick={ ()=>this.handleClickRight(10)} className="btn btn-success m-2">right</button> // 3. Box 调用 Boxes 的删除方法 : // Box 中的 Button 的 onClick 事件,绑定匿名函数来调用含参的删除方法 <button onClick={ ()=>this.props.onDelete(this.props.id)} className='btn btn-danger m-2'> Delete </button> </React.Fragment> ); }
○ メソッドの受け渡し 2: React 親コンポーネントが子コンポーネントのメソッドを呼び出します。
(サブコンポーネント メソッドは 1 つだけ呼び出すことができ、リスト サブコンポーネントは呼び出すことができません)
// 父组件 class Boxes extends Component { // 1. Boxes 父组件中写入 setChildRef = (ref) => { this.ChildRef = ref; } // 3. Boxes 父组件中写调用 Box 子组件的方法 handleReset = () =>{ this.ChildRef.handleRE() } render() { return ( <React.Fragment> // 4. 将父组件方法绑定onClick单击事件中,即可实现单击调用子组件的方法 <button onClick={ this.handleReset} className='btn btn-primary'> Clear </button> { this.state.boxes.map((box)=>( // 2. Boxes 父组件的 Box 子组件标签内增加 ref 属性,并将 setChildRef 传递过来 <Box key = { box.id} ref={ this.setChildRef} id={ box.id} x = { box.x} onDelete = { this.handleDelete}> <p>Box :</p> <div>{ box.id}</div> </Box> ))} </React.Fragment> ); } }
// 子组件 class Box extends Component { state = { x: this.props.x, } // 子组件中被调用的方法 handleRE = () =>{ this.setState({ x: 0 }); } render() { return ( <React.Fragment> ...... </React.Fragment> ); } }