今天咱們將要建立一個 Confirm 的對話框組件,相似alert對話框,有標題,內容,確認和取消按鈕。組件完成後的效果以下圖所示:javascript
本篇文章主要包含如下內容:css
本示例咱們將使用 create-react-app 建立項目,這篇文章《「 React TS3 專題」從建立第一個 React TypeScript3 項目開始》有介紹過,這裏咱們快速熟悉下。html
一、建立項目前端
打開控制檯,經過如下命令建立咱們的 React TS3 項目:java
npx create-react-app my-components --typescript
複製代碼
二、安裝tslint依賴node
接下來,爲了保證項目代碼質量,咱們安裝 tslint 的相關依賴:react
cd my-components
npm install tslint tslint-react tslint-config-prettier --save-dev
複製代碼
三、而後添加 tslint.json 文件,配置相關規則typescript
{
"extends": ["tslint:recommended", "tslint-react", "tslint-config-prettier"],
"rules": {
"ordered-imports": false,
"object-literal-sort-keys": false,
"no-debugger": false,
"no-console": false,
},
"linterOptions": {
"exclude": [
"config/**/*.js",
"node_modules/**/*.ts",
"coverage/lcov-report/*.js"
]
}
}
複製代碼
四、運行項目npm
接下來安裝相關依賴,並啓動項目:json
npm install
npm start
複製代碼
五、修改樣式
打開 app.css 文件,咱們進行一些樣式調整其頭部的高度,修改部分以下:
...
.App-logo {
animation: App-logo-spin infinite 20s linear;
height: 20vmin;
}
.App-header {
background-color: #282c34;
min-height: 40vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
...
複製代碼
一、建立 Confirm.tsx 文件
咱們會在 src 目錄下看到 App.tsx 文件,這是項目中爲咱們默認建立的組件,使用的是函數的方式建立組件,這裏先不作介紹,接下來的文章會有介紹。咱們先用類的聲明方式建立一個單獨的組件,在 src 目錄建立一個 Confirm.tsx 文件。初始化的內容結構以下:
import * as React from "react";
class Confirm extends React.Component {
}
export default Confirm;
複製代碼
二、添加 render 方法
接下來咱們添加 render 方法
...
class Confirm extends React.Component {
public render() {
return (
);
}
}
...
複製代碼
三、實現 render 方法:
接下來咱們實現上述的 render 方法,這裏主要定義了組件的樣式佈局:
import * as React from "react";
class Confirm extends React.Component {
public render() {
return (
<div className="confirm-wrapper confirm-visible">
<div className="confirm-container">
<div className="confirm-title-container">
<span>This is where our title should go</span>
</div>
<div className="confirm-content-container">
<p>This is where our content should go</p>
</div>
<div className="confirm-buttons-container">
<button className="confirm-cancel">Cancel</button>
<button className="confirm-ok">Okay</button>
</div>
</div>
</div>
);
}
}
複製代碼
是否是以爲內容部分很像html, 在React裏稱JSX。做你會發現樣式屬性是 className 並非咱們熟悉的 class ,這是 JSX 語法所特有的。
四、 在 App.tsx 引入 Confirm 組件
import Confirm from "./Confirm";
...
<div className="App">
<header className="App-header">
...
</header>
<Confirm />
</div>
...
複製代碼
五、定義 Confirm.css 的樣式
因爲組件沒有樣式,還過於醜陋,接下來在 src 目錄新建 Confirm.css 文件,咱們來美化下咱們的組件,代碼以下:
.confirm-wrapper {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: gray;
opacity: 0;
visibility: hidden;
transform: scale(1.1);
transition: visibility 0s linear 0.25s, opacity 0.25s 0s, transform 0.25s;
z-index: 1;
}
.confirm-visible {
opacity: 1;
visibility: visible;
transform: scale(1);
transition: visibility 0s linear 0s, opacity 0.25s 0s, transform 0.25s;
}
.confirm-container {
background-color: #fff;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border-radius: 0.2em;
min-width: 300px;
}
.confirm-title-container {
font-size: 1.3em;
padding: 10px;
border-top-left-radius: 0.2em;
border-top-right-radius: 0.2em;
}
.confirm-content-container {
padding: 0px 10px 15px 10px;
}
.confirm-buttons-container {
padding: 5px 15px 10px 15px;
text-align: right;
}
.confirm-buttons-container button {
margin-left: 10px;
min-width: 80px;
line-height: 20px;
border-style: solid;
border-radius: 0.2em;
padding: 3px 6px;
cursor: pointer;
}
.confirm-cancel {
background-color: #fff;
border-color: #848e97;
}
.confirm-cancel:hover {
border-color: #6c757d;
}
.confirm-ok {
background-color: #848e97;
border-color: #848e97;
color: #fff;
}
.confirm-ok:hover {
background-color: #6c757d;
border-color: #6c757d;
}
複製代碼
而後在 Confirm.tsx 中引入 Confirm.css :
import"./Confirm.css";
複製代碼
六、啓動應用
咱們經過 npm start 啓動咱們的應用程序,效果以下:
上一小節,咱們知道了JSX有點像HTML,容許咱們在JavaScript代碼(或TS3)中相似HTML同樣進行使用,其實 React 使用 JSX 來替代常規的 JavaScript。
JSX 是一個看起來很像 XML 的 JavaScript 語法擴展。接下來咱們來了解下在解釋器的編譯下最終會轉換成什麼。
一、使用 https://babeljs.io/repl 在線工具
使用這款在線工具,咱們將相似的 相似 HTML 的 JSX 內容轉換成 JavaScript 的語法結構,示例以下:
如上圖所示咱們能夠看出,咱們代碼最終會轉換成 React.createElement 方法進行聲明,這個方法包含了三個參數標籤屬性(例如span,div等),第二就是標籤相關的屬性,好比能夠是className,第三個參數就是子元素屬性,用來進行標籤嵌套的。
二、接下來在外層添加div
爲了讓結構更加複雜,咱們在外層添加div, 代碼以下:
<div className="confirm-title-container">
<span>This is where our title should go</span>
</div>
複製代碼
使用在線工具進行轉換,代碼以下:
React.createElement(
"div",
{ className: "confirm-title-container" },
React.createElement(
"span",
null,
"This is where our title should go"
)
);
複製代碼
三、接下來定義屬性
好比爲組件自定義屬性,結構以下:
const props = {
title: "React and TypeScript"
};
<div className="confirm-title-container">
<span>{props.title}</span>
</div>
複製代碼
使用在線工具進行轉換,代碼以下:
var props = {
title: "React and TypeScript"
};
React.createElement(
"div",
{ className: "confirm-title-container" },
React.createElement(
"span",
null,
props.title
)
);
複製代碼
四、使用三元運算符,定義默認屬性
const props = {};
<div className="confirm-title-container">
<span>{props.title ? props.title : "React and TypeScript"}</span>
</div>
複製代碼
使用在線工具轉換,代碼以下:
var props = {};
React.createElement(
"span",
null,
props.title ? props.title : "React and TypeScript"
)
複製代碼
JSX 就介紹到這裏,咱們清楚了相似HTML結構的JSX都會轉換成javascript的原生結構,爲何不能使用class而使用className,筆者介紹到這裏,你應該明白了吧,由於 class 是 javascript 的關鍵詞 ES6的類聲明部分。
組件的意義就是可以複用,上一小節,咱們把組件的標題,內容固定寫死了,接下來咱們來看看在 TS3 項目裏咱們是如何使用組件屬性的。
一、定義 TS3 類型屬性接口
咱們先來用 TS3 的方式定義接口類型,咱們在 Confirm.tsx 文件裏實現以下定義:
interface IProps {
title: string;
content: string;
}
複製代碼
二、接着將接口類型在類組件實現
經過添加到類的實現中,實現代碼以下:
class Confirm extends React.Component<IProps>
複製代碼
有過TS基礎的人,一眼就能看出 React.Component 是泛型類。泛型類規定了咱們傳入的接口的數據類型,能夠靈活進行定義。
軟件工程中,咱們不只要建立一致的定義良好的API,同時也要考慮可重用性。 組件不只可以支持當前的數據類型,同時也能支持將來的數據類型,這在建立大型系統時爲你提供了十分靈活的功能。 在像C#和Java這樣的語言中,可使用泛型來建立可重用的組件,一個組件能夠支持多種類型的數據。 這樣用戶就能夠以本身的數據類型來使用組件。
三、接下來定義組件的動態類型屬性
咱們將使用 this.props.propName 定義組件的動態屬性,按照以下代碼進行修改 Confirm.tsx 文件:
...
<div className="confirm-title-container">
<span>{this.props.title}</span>
</div>
<div className="confirm-content-container">
<p>{this.props.content}</p>
</div>
...
複製代碼
四、 Confirm.tsx 文件的最終代碼
import * as React from "react";
import './Confirm.css';
interface IProps {
title: string;
content: string;
}
class Confirm extends React.Component<IProps> {
public render() {
return (
<div className="confirm-wrapper confirm-visible">
<div className="confirm-container">
<div className="confirm-title-container">
<span>{this.props.title}</span>
</div>
<div className="confirm-content-container">
<p>{this.props.content}</p>
</div>
<div className="confirm-buttons-container">
<button className="confirm-cancel">Cancel</button>
<button className="confirm-ok">Okay</button>
</div>
</div>
</div>
);
}
}
export default Confirm;
複製代碼
五、 接下來修改 App.tsx 文件
因爲咱們修改了 Confirm.tsx 文件,讓屬性接受動態傳值,咱們須要在 App.tsx 文件中定義屬性內容,示例代碼以下:
<Confirm
title="React and TypeScript"
content="Are you sure you want to learn React and TypeScript?"
/>
export default Confirm;
複製代碼
咱們保存文件,你就會看到
一、咱們調用相關API時,有必傳參數和可選參數。咱們定義組件屬性時,也能夠這樣,有些屬性是必須填寫,有的可沒必要。接着咱們來定義確認按鈕文字和否認按鈕文字這些屬性是可選的,咱們來修改 Confirm.tsx 中的接口定義,示例以下:
interface IProps {
title: string;
content: string;
cancelCaption?: string;
okCaption?: string;
}
複製代碼
?: 的意思就是可選屬性參數的意思,咱們能夠能夠在調用組件時不用包含此屬性
二、將可選屬性在 Confirm.tsx 進行定義
<div className="confirm-buttons-container">
<button className="confirm-cancel">
{this.props.cancelCaption}
</button>
<button className="confirm-ok">
{this.props.okCaption}
</button>
</div>
複製代碼
三、保存文件
接下來爲了驗證可選屬性會不會形成錯誤,暫時不在 App.tsx 文件中的 Confirm 組件調用中添加新屬性,咱們來保存 Confirm.tsx 文件,瀏覽器的效果以下:
沒有報錯,能正常運行,因爲沒有給按鈕默認文字參數定義值,咱們的按鈕很難看,由於沒有高度。接下來咱們來給可選屬性定義值。
初始化組件時,咱們能夠給組件的屬性定義默認值,這裏就使用到了 defaultProps 靜態對象屬性。
一、聲明靜態對象屬性
經過靜態對象屬性的方式,咱們進行初始化可選參數的默認值,修改後的 Confirm.tsx 示例以下:
class Confirm extends React.Component<IProps> {
public static defaultProps = {
cancelCaption: "Cancel",
okCaption: "Okay"
};
public render() { ... }
}
複製代碼
保存 Confirm.tsx 文件,咱們就會看到瀏覽器的變化:
二、修改默認屬性的值
若是你想修改默認屬性的值,咱們能夠修改 App.tsx 文件,添加可選屬性便可:
<Confirm
title="React and TypeScript"
content="Are you sure you want to learn React and TypeScript?"
cancelCaption="No way"
okCaption="Yes please!"
/>
複製代碼
保存 App.tsx 文件,你就會看到瀏覽器會刷新變化,效果以下圖:
具備默認值的可選屬性的組件更易於使用,讓咱們的組件更加靈活。
今天的章節就分享到這裏,咱們一塊兒學習瞭如何使用 TS3 的方式建立組件,定義屬性和其屬性的默認值,接下來的文章裏,筆者將給你們介紹如何用 TS3 的方式定義組件事件。
更多精彩內容,請微信關注「前端達人」公衆號!