[react]-第9課
Webコンポーネント
Webコンポーネントは、カスタムコンポーネントを作成する標準です.
カスタマイズされたHTML構造、カプセル化されたスタイル、独自のプロパティ、メソッドなどは、データム構成部品によって定義できます.
構成部品の条件
必要な技術仕様
技術仕様説明Custom elementsカスタムHTML要素を定義します.Shadow DOM要素の内部に非表示DOMを作成するために使用されます.CSS Scoping要素シャドウDOMの内部にのみ適用されるスタイルを宣言します.Event retargetingコンポーネントを開発環境に適合させるために使用される.
カスタム要素
独自のプロパティ(メソッドを含む)やイベントなどを使用して、クラスで説明されているカスタムHTML要素を作成できます.
カスタム要素が定義されている場合は、
<div>
などの他のHTML標準要素と同じ内容を使用できます.웹 컴포넌트 예시
class EuidInput extends HTMLElement {
constructor() {
// 요소가 생성될 때 호출된다.
// HTMLElement를 확장하여 super()가 반드시 필요!
super();
// 섀도우 돔 트리를 연결하고 이에 대한 참조 반환
// mode: open은 루트 외부의 자바스크립트에서 접근을 가능하게 해줌
this.attachShadow({ mode: 'open' });
}
connectedCallback() {
// 요소가 문서에 추가될 때 이 메서드 호출
// 요소가 반복적으로 추가/제거될 경우 수차례 호출
}
disconnectedCallback() {
// 요소가 문서에서 제거될 때 브라우저는 이 메소드를 호출
// 요소가 반복적으로 추가/제거될 경우 수차례 호출
}
// static 메서드
static get observedAttributes() {
return [
/* 변경을 관찰할 속성 이름 배열 */
];
}
// React와 같이 속성이 변경됨에 따라 callback으로 관리
attributeChangedCallback(name, oldValue, newValue) {
// observedAttributes()에 등록된 속성 중 값이 변경되면 호출
}
adoptedCallback() {
// 요소가 새 문서로 이동되면 호출
// document.adoptNode에서 발생하며, 거의 사용되지 않는다.
}
// 사용자가 정의한 속성 및 메서드를 작성할 수 있습니다.
// ...
}
ブラウザで認識できるデータム要素の名前とクラスを定義します.customElements.define('euid-input', EuidInput);
クラスは、defineで定義されたときに小文字케밥 케이스
として定義されることが多い必要があります.HTMLドキュメントでCustom要素を使用する場合は、次のように記述します.
<euid-input />
JavaScriptを使用してカスタム要素を作成することもできます.const euidInputNode = document.createElement('euid-input');
Webコンポーネントの動的インストール
<script>
// [미션]
// 위에 HTML로 작성된 euid-counter 커스텀 요소를 프로그래밍 방식으로 생성한 후,
// .demo 요소 내부에 마운트 하여 컴포넌트를 렌더링 합니다.
// 컴포넌트가 존재한다면? 컴포넌트를 렌더링 하자.
let componentName = 'euid-counter';
customElements.whenDefined(componentName).then(() => {
const createdCustomElement = document.createElement(componentName);
createdCustomElement.setAttribute('min', 1);
createdCustomElement.setAttribute('count', 3);
createdCustomElement.setAttribute('max', 10);
document.querySelector('.demo:last-of-type').append(createdCustomElement);
});
</script>
名前付き要素が定義されている場合、whenDefinedメソッドは解析のプロセスを返します.したがって、euid-counter
というカスタム要素が定義されている場合、上記のコードなどのコンポーネントが作成され、.demo
クラスの最後に動的にマウントされます.ただし、この過程で
static get obsetvedAttributes
メソッドとattributeChangedCallback
が存在しない場合、ボタンをクリックして値を変更するとminとmaxの値を超え、内部のカウント値が変更されます.EunidCounter/index.js
// [미션]
// 프로그래밍 방식으로 업데이트 된 속성을 감지하여
// 각 속성 값을 컴포넌트의 props에 업데이트 합니다.
// 속성 관찰
static get observedAttributes() {
return ['min', 'max', 'step', 'count'];
}
// 속성 관찰 후 이것들을 props에 값을 넣어줌
attributeChangedCallback(name, oldValue, newValue) {
this.props[name] = newValue;
}
上記のコードを作成して、プロパティを観察するpropsを設定します.これらのプロパティに変更がある場合は、値をattributeChangedCallback
に変更します.コンテナ構成部品(ステータスあり)
コンテナ構成部品とは?
Reactが提供する構成部品タイプのクラス構成部品をコンテナ構成部品として使用
これとは反対の用語->表現素子(以前は関数型素子)ですが、react hooksでstateを得ることができます.
これにより、構成部品の役割をプレゼンテーションとコンテナに分離し、それぞれ独自の責任を負い、構成部品の重複使用性を向上させ、デバッグを簡素化します.
Reactの主なタスクは、アプリケーションのステータスを取得し、DOMノードに変換することです。
クラス構成部品は、インスタンスメンバー(Property)であり、転送属性(Props)とステータス(State)を持つ関数構成部品とは異なります.
注意:https://ko.reactjs.org/docs/react-component.html#instance-properties
構成部品を再レンダリングすると、関数構成部品は関数ボディを再実行しますが、クラス構成部品は
render
メソッドのみを再実行します.prop vs. state
propは外部(親)から受信して使用するため、値を読み取り専用で更新することはできません.
stateは変更可能なデータ(ステータス)であり、更新が必要な構成部品はステータスを設定することで使用できます.この場合、stateは素子が所有するローカルデータであり、適用範囲は現在の素子である.
実際の操作
cra(create-act-app)による環境の構成
npx create-react-app .
のreportWebVitals
ファイルは後で配備され、-->WebVitalsを使用してレポートされます.// static method (sync)
import reportWebVitals from './reportWebVitals';
これは同期方式なのでdynamic importでasync方式に変更します.import('./reportWebVitals')
.then(({ default: reportWebVitals }) => reportWebVitals(console.log))
.catch(({ message }) => console.error(message));
Web Vitalsに関する次の情報を表示できます.
これは構築後に使用されるので、
process.env
はproduction
で使用!index.js
// React 앱은 Node.js 환경에서 컴파일 되므로
// process.env를 사용할 수 있다.
const { NODE_ENV: devOrProdMode } = process.env;
// 빌드 할 때만, reportWebvitals 모듈 동적 호출
if (devOrProdMode.includes('production')) {
// dynamic import (async)
// reportWebVitals();
import('./reportWebVitals')
.then(({ default: reportWebVitals }) => reportWebVitals(console.log))
.catch(({ message }) => console.error(message));
}
ヘッドの作成
import React from 'react';
import { ReactComponent as ReactLogo } from '../../assets/logo.svg';
// stateful component
export class AppHeader extends React.Component {
constructor(props) {
super(props);
// 컴포넌트 상태 설정
this.state = {
brand: {
label: 'React',
className: 'App-logo',
},
description: '',
learnLink: {
className: 'App-link',
href: 'https://reactjs.org',
text: 'Learn React',
isExternal: true,
},
};
}
render() {
const {
brand: { label, className },
learnLink,
} = this.state;
return (
<header className='App-header'>
<ReactLogo title={label} className={className} />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className={learnLink.className}
href={learnLink.href}
target={learnLink.isExternal && '_blank'}
rel={learnLink.isExternal && 'noopener noreferrer'}
>
{learnLink.text}
</a>
</header>
);
}
}
ステータスconstructor
は、上記のthis.state
の内部で定義することができるが、constructor
を必要とせずにクラスフィールドを使用して定義することができる.export class AppHeader extends React.Component {
...
// 이렇게 되면 constructor 생략 가능!
// 컴포넌트 상태 설정
this.state = {
brand: {
label: 'React',
className: 'App-logo',
},
description: '',
learnLink: {
className: 'App-link',
href: 'https://reactjs.org',
text: 'Learn React',
isExternal: true,
},
};
クラスフィールドは標準ではありませんが、コンパイル中にBabelで処理され、すぐに使用できます.Webを開くと以下の画面が表示され、reactive dev tool拡張がインストールされている場合は、
Component
タブに入り、isExternal
という状態のチェックボタンを押して、状態に応じて画面を変更することができます.上のHighlight updatewhen~を選択すると、画面で再レンダリングするときに、より容易に認識できます.
AppHeader.js
...
// stateful component
export class AppHeader extends React.Component {
// 컴포넌트 상태 설정
this.state = {
...
description: 'Edit <code>src/App.js</code> and save to reload.',
};
render() {
const {
brand: { label, className },
description,
learnLink,
} = this.state;
return (
...
<p>{description}</p>
...
);
...
下図に示すように、AppHeader
を作成すると、description
の<code>
タグがJSXによって直接文字列に入ります.したがって、以下の方法で作成すればよい.
getDescription() {
return ['Edit', ' ', <code key='appEntryFile'>src/App.js</code>, ' ', 'and save to reload.'];
}
専用のプラグインがあるそうです.クラス構成部品ステータスの更新
クラスでは
setState()
をステータス変更方法として使用します.注意:https://ko.reactjs.org/docs/react-component.html#setstate
setState()に渡されるupdaterは、関数タイプを設定し、コールバック関数を2番目のパラメータとして渡すこともできます.(クラスインスタンスメソッドも使用可能)
コールバックsetStateの2番目のパラメータが必要なのは、setStateの起動方式が非同期であるため、コールバック関数はすべての状態が安定して更新された後に実行されるからです.
constructor
からsetStateメソッドを呼び出すのは意味がなく、render
部分でステータスを更新することは絶対にできません.反応状態が変化すると、render
を再び呼び出して画面に描画するため、無限ループに陥るからです.クラス構成部品のライフサイクル
一般的なライフサイクル
// 라이프 사이클 메서드
// 명령형 프로그래밍
// 컴포넌트가 실제 DOM에 마운트 된 이후 실행
componentDidMount() {
console.log('컴포넌트가 실제 DOM에 마운트 된 이후 실행');
// DOM 노드에 접근 가능 여부
console.log('componentDidmount', document.querySelector('.App-header'));
// 컴포넌트 상태 업데이트 (시간의 흐름에 따라 제어)
setTimeout(() => {
console.log('1000ms 지남', this); // 여기서 this는 컴포넌트 인스턴스
}, 1000);
}
ライフサイクル後にdomにアクセスし、アクセス可能なWebを作成できます.コマンドプログラミングを使用してメンテナンスを行うか、アクセス性を遵守する必要がある場合に使用するライフサイクルメソッドコンポーネントDidmountとコンポーネントDidUpdate.
その後更新する場合は3種類あります.
jQueryを反応器に適用してみる
yarn add jquery
モジュールとしてロードされているため、グローバルに定義されていません.
ComponentDidmountでJクエリーコードを記述する
// jQuery를 사용해 명령형 프로그래밍
$('.App-header').animate(
{
opacity: 0.1,
},
{
duration: 1000,
}
);
適用するかどうかを確認できます.親コンポーネント
App
をクラスコンポーネントに置き換えて、コンポーネントWillMountの実行手順を表示します.import './App.css';
import { Component } from 'react';
// stateless component(presentational) -> stateful component
// functional -> class
export default class App extends Component {
state = {
isShowHeader: true,
};
render() {
return (
<div className='App'>
{this.state.isShowHeader ? this.props.children : '이런... 자식 노드가 없습니다.'}
</div>
);
}
}
コンポーネントDidUpdateステータスの確認注意:https://ko.reactjs.org/docs/react-component.html#componentdidupdate
componentDidUpdate(prevProps, prevState) {
console.log('컴포넌트가 업데이트 되었습니다!!');
console.log('이전 props 또는 state', { props: prevProps, state: prevState });
console.log('현재 props 또는 state', { props: this.props, state: this.state });
}
非アクティブライフサイクル
getDerivedStateFromProps
static getDerivedStateFromProps(props, state) {
// 이 안에서 this 인스턴스에 접근 X
// 반환하는 것은 컴포넌트의 상태에 합성할 파생 상태(객체)
return {
count: props.count ?? 100,
};
}
getDerivedStateFromProps-->静的メソッドはアクセスできないため、パラメータを使用してアクセスする必要があります派生ステータスを作成する必要があります
1.propsによるステータスの更新
2.propsとstateを比較してステータスを更新する
craに絶対パスを設定する
注意:https://create-react-app.dev/docs/importing-a-component/#absolute-imports
Webpackでの絶対パスの設定
注意:https://webpack.kr/configuration/resolve/#resolvealias
昇格state
shouldComponentUpdate実習
注意:https://ko.reactjs.org/docs/lifting-state-up.html#gatsby-focus-wrapper
shouldComponentUpdate(nextProps, nextState) {
// 조건 확인 (비교)
// props, state(with derivedState)
// console.log('현재 props 또는 state', this.props, this.state);
// console.log('다음 props 또는 state', nextProps, nextState);
// 부모로부터 전달 받은 props의 brand.label 값이 바뀌면
// 컴포넌트 렌더링을 하지 않는다.
if (nextProps.brand.label !== this.props.brand.label) {
// render() 미실행
console.log('부모 컴포넌트의 리 렌더링 요청을 묵살한다.');
return false;
}
// 상황 1.
// 이전 props와 다음 props의 차이가 없다.
// 굳이 재조정 알고리즘에 의해 다시 렌더링 될 필요가 없다.
// render() 실행
return true;
}
shouldComponentUpdate()-->パフォーマンスの最適化にのみ使用します.レンダリングを防止するために使用すると、エラーが発生します.元々持っていたブランドlabelを親ステータスupに昇格させ、親ステータスupに渡し、親ステータスからpropsを受信して条件に従って処理できます.
参考資料:https://ko.reactjs.org/docs/react-component.html#shouldcomponentupdate
getShanpShotBeforeUpdate
アニメーションUIで人気があります
特に、チャットアプリケーションを実装するときにこの機能を作成しない場合、ユーザインタフェースは少し歪んだ方法で実行されます.
getSnapshotBeforeUpdate(prevProps, prevState) {
// DOM 노드에 접근 후, 정보 값을 읽기
// 읽은 정보 값을 스냅샷 반환
// snapshot (꼭 object가 아닐 수도 있음)
return {
name: 'this is snapshot',
version: '0.1.2',
};
}
注意:https://ko.reactjs.org/docs/react-component.html#getsnapshotbeforeupdateReference
この問題について([react]-第9課), 我々は、より多くの情報をここで見つけました https://velog.io/@hustle-dev/React-9일차-수업テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol