前沿
一孝偎、什么是組件
component,構(gòu)建的功能和外觀相同挤聘。由于瀏覽器和js對組件支持度不一轰枝,很長時(shí)間內(nèi),組件無法像積木一樣搭建成網(wǎng)頁组去。
2014 React框架發(fā)布鞍陨,為組件提供了一套可行方案〈勇。基于React框架實(shí)現(xiàn)的組件可以完成網(wǎng)站的快速搭建诚撵。
二缭裆、Ant Design
Ant Design基于React開發(fā),不僅是一套組件砾脑,包括一套設(shè)計(jì)規(guī)范和理念幼驶。Ant Design想要帶給客戶的,不僅僅是功能韧衣,還是美觀和良好的客戶體驗(yàn)
三盅藻、React 介紹
由Facebook公司推出的一套前端框架,它的核心理念是將網(wǎng)頁應(yīng)用看成一個(gè)組件構(gòu)成的狀態(tài)機(jī)(state machine)畅铭,狀態(tài)的變化導(dǎo)致了 UI 的變化氏淑。框架比較簡單硕噩,但是需要使用配套工具假残,所以學(xué)習(xí)React不僅僅是學(xué)習(xí)框架,而是學(xué)習(xí)一整套R(shí)eact技術(shù)棧炉擅。
四辉懒、umi介紹
配合使用編輯打包工具,Umi
第一章 基礎(chǔ)知識(shí)
一谍失、前端開發(fā)的演變
1眶俩、靜態(tài)頁面階段
流程:瀏覽器請求、生成靜態(tài)頁面快鱼、發(fā)送到瀏覽器? ?框架一般都是后端的mvc
2颠印、ajax階段
不僅是展示還可以管理和互動(dòng)。流程:獲取數(shù)據(jù)抹竹、處理數(shù)據(jù)线罕、展示數(shù)據(jù)
3.前端mvc階段
前端MVC框架,只有MV窃判,沒有C钞楼。MVVC框架,View model(數(shù)據(jù)處理)代替Controller
4.spa階段
前端可以讀寫數(shù)據(jù)袄琳、切換視圖窿凤、用戶交互,網(wǎng)頁即應(yīng)用跨蟹。SPA(single-page application)。開發(fā)模板橘沥,轉(zhuǎn)變成開發(fā)應(yīng)用窗轩。
主流:Vue、Angular座咆、React(適配Redux架構(gòu))等
二痢艺、初始化項(xiàng)目
1.安裝node.js
2.安裝cnpm仓洼,進(jìn)行包管理
npm install -g cnpm --registry=https://registry.npm.taobao.org
3.安裝 umi 依賴
mkdir antd-course
cd antd-course?
cnpm init -y
cnpm install umi --save-dev
4.初始化 umi 的配置
在 umi 中,大量的使用了配置和約定來幫助你快速開發(fā)代碼堤舒。
首先創(chuàng)建配置文件色建。配置文件被約定為config/config.js。(推薦使用VS Code)
在 umi 中舌缤,你也可以簡單的使用.umirc.js來作為配置文件箕戳。當(dāng)然它和config/config.js是二選一的。更多說明可以參考 umi 的文檔国撵。
config/config.js中初始化的內(nèi)容如下:? ??
export default {};
一開始它只是 export 了一個(gè)默認(rèn)的空的對象{}陵吸,并沒有什么作用,但是在后面我們會(huì)用到介牙。
我們所說的頁面是指由一個(gè)獨(dú)立路由對應(yīng)的 UI 界面壮虫,關(guān)于路由你后續(xù)可以在《路由配置》中了解更多。在這一章節(jié)中你只需要知道對于這個(gè)例子环础,就是指我們期望通過瀏覽器訪問/helloworld的時(shí)候可以得到一個(gè)顯示hello world的頁面囚似。
5.新建一個(gè)src目錄
它用來存放項(xiàng)目的除了配置以及單測以外的主要代碼。
在 umi 中线得,約定的存放頁面代碼的文件夾是pages饶唤,是復(fù)數(shù),不過如果你喜歡單數(shù)的話你配置項(xiàng)中你可以添加singular為true來讓page變?yōu)榧s定的文件夾框都。在本課程中我們使用單數(shù)來作為約定目錄搬素。所以你需要修改配置文件為
export?default?{
????singular:?true,
};
6.創(chuàng)建一個(gè)頁面組件
新建src/page/HelloWorld.js文件,代碼如下:
export default () => {
? return <div>hello world</div>;
}
7.通過 umi啟動(dòng)代碼
首先需要在package.json中的scripts里面添加兩個(gè)命令:
{
? "scripts": {
+? "dev": "umi dev",
+? "build": "umi build"
? }
}
scripts中定義的命令魏保,可以在項(xiàng)目根目錄中通過cnpm run [scriptname]來運(yùn)行熬尺。接下來請執(zhí)行:
cnpm run dev
如果順利,項(xiàng)目將會(huì)運(yùn)行起來谓罗。你將會(huì)在命令行中看到如下的日志:
8.瀏覽器打開
復(fù)制日志中的地址粱哼,比如http://localhost:8001/(這里的端口可能會(huì)因?yàn)楸徽加没蛘咂渌蚨煌垍⒖寄愕臋C(jī)器中實(shí)際打印出來的地址)檩咱。并在后面加上helloworld的路徑后(比如http://localhost:8001/helloworld)在瀏覽器中打開揭措,然后你將會(huì)看到:
9.可使用配置式路由
除了約定式的路由,你也可以使用配置式的路由刻蚯。至于使用哪種路由取決于你的喜好绊含,這不是本課程的重點(diǎn)。在本課程中為了讓開發(fā)者更好的理解路由組件嵌套炊汹,我們會(huì)使用配置式的路由躬充。
要使用配置式的路由,你需要在配置文件config/config.js中添加如下配置:
export default {
? routes: [{
? ? path: '/',
? ? component: './HelloWorld',
? }],
}
其中 component 是一個(gè)字符串,它是相對于page目錄的相對路徑充甚。在上面的配置中我們將路由的路徑配置成為了?/以政,這樣訪問http://localhost:8000/首頁就能看到hello world了。
當(dāng)有了 routes 的配置之后 umi 就不會(huì)再執(zhí)行約定式對應(yīng)的路由邏輯了伴找,而是直接使用通過配置聲明的路由盈蛮。關(guān)于路由的更多信息可以參考《路由配置》這一章節(jié)的說明。
? 添加 umi-plugin-react 插件
umi 是一個(gè)可插拔的企業(yè)級(jí) react 應(yīng)用框架技矮,它的很多功能都是通過插件實(shí)現(xiàn)抖誉。尤其是 umi 官方的umi-plugin-react這個(gè)插件集成了常用的一些進(jìn)階的功能,為了后面的課程需要穆役,我們需要添加該插件集到項(xiàng)目中寸五。
首先通過cnpm install umi-plugin-react --save-dev來安裝該插件集。然后在配置文件config/config.js中引入該插件:
????plugins:?[
????????['umi-plugin-react',?{
??????????//?這里暫時(shí)還沒有添加配置耿币,該插件還不會(huì)有作用梳杏,我們會(huì)在后面的課程按照需求打開相應(yīng)的配置
????????}],
????],
插件添加后,可能會(huì)無法執(zhí)行cnpm run build淹接,原因Path must be a string.(解決辦法:react版本不夠十性,升級(jí)cnpm install --save react@16.13.0)
? .gitignore
cnpm 安裝的依賴會(huì)被默認(rèn)安裝到項(xiàng)目的node_modules目錄下。這個(gè)目錄通常是不需要提交到代碼倉庫中的塑悼。如果你使用的是 git 來作為代碼的管理工具劲适,那么你可以添加.gitignore文件到項(xiàng)目根目錄中,避免將不必要的代碼提交到 git 倉庫中厢蒜。
.gitignore如下:
node_modules
dist
.umi
其中.umi是 umi 在開發(fā)過程中產(chǎn)生的臨時(shí)入口文件霞势,便于開發(fā)調(diào)試,同樣也不需要提交到代碼倉庫中斑鸦。dist是構(gòu)建出來的產(chǎn)物愕贡,通常也不需要提交。
我們建議你可以在本地通過 git 管理起你的代碼巷屿,方便在后面的課程中更好的操作你的代碼固以。
git init
git add -A
git commit -m 'init'
10、構(gòu)建和部署
你可以通過cnpm run build來構(gòu)建出最終的產(chǎn)物嘱巾,執(zhí)行該命令后會(huì)生成最終的 HTML憨琳、CSS 和 JS 到dist目錄下。它們是瀏覽器可以直接識(shí)別并運(yùn)行的代碼旬昭,這樣你就可以將它們部署到你想要的服務(wù)器上了篙螟。
需要注意的是,如果你直接用瀏覽器打開 HTML 那是無法正確展示的问拘,因?yàn)橹苯哟蜷_無法識(shí)別出 HTML 引入的 JS 和 CSS 的路徑闲擦。你需要確保的的 HTML 在一個(gè) HTTP 的 web 容器中慢味,并保證對應(yīng)的頁面的訪問路徑正確。比如使用serve:
cnpm install serve -g
serve ./dist
三墅冷、第一個(gè)組件
1、組件是什么
按照功能劃分或油,一張網(wǎng)頁可以由多個(gè)互相獨(dú)立的功能單位組成寞忿,這種功能單位就叫做“組件”(component)。比如顶岸,典型的網(wǎng)頁分成頁頭腔彰、內(nèi)容、頁尾三個(gè)部分辖佣,就可以寫成三個(gè)組件:Header霹抛、Content、Footer卷谈。這些組件拼裝在一起杯拐,就構(gòu)成了一張頁面。
組件內(nèi)部還可以包含下一級(jí)的組件世蔗。比如端逼,“文章”組件內(nèi)部可以包含“表單”組件,“表單”組件內(nèi)部又可以包含“按鈕”組件污淋。
組件的好處有很多顶滩,下面是其中幾點(diǎn)。
有利于細(xì)化 UI 邏輯寸爆,不同的組件負(fù)責(zé)不同的功能點(diǎn)礁鲁。
有利于代碼復(fù)用,多個(gè)頁面可以使用同樣的組件赁豆。
有利于人員分工仅醇,不同的工程師負(fù)責(zé)不同的組件。
React 的核心概念就是組件歌憨。這個(gè)框架的主要功能着憨,就是定義了一套編寫和使用組件的規(guī)范。本節(jié)開頭的那段代碼务嫡,就是定義了一個(gè)最簡單的組件甲抖。
export default () => {
? return <div>hello world</div>;
}
上面代碼采用 ES6 模塊格式,默認(rèn)輸出一個(gè)箭頭函數(shù)心铃。這個(gè)函數(shù)執(zhí)行后准谚,返回了一段 JSX 代碼(后文介紹),代表 hello world 區(qū)塊去扣。這就是最簡單的 React 組件的寫法柱衔。
2.JSX語法
第一次接觸 React 的用戶樊破,都會(huì)有一個(gè)共同的疑問,為什么 JavaScript 代碼里面可以直接插入 HTML 代碼唆铐。這難道不會(huì)報(bào)錯(cuò)嗎哲戚?
回答是如果你把上面的代碼,放到 JavaScript 引擎里面運(yùn)行艾岂,確實(shí)會(huì)報(bào)錯(cuò)顺少。因?yàn)檫@種語法不是 JavaScript,而是 React 為了方便開發(fā)者自創(chuàng)的 JSX 語法王浴。
JSX 可以被 Babel 轉(zhuǎn)碼器轉(zhuǎn)為正常的 JavaScript 語法脆炎。上面的 JSX 語法轉(zhuǎn)碼后的結(jié)果如下。
exports.default=function() {returnReact.createElement("div",null,"hello world"? );};
兩種寫法一比較氓辣,就會(huì)發(fā)現(xiàn)對于復(fù)雜的 UI 組件來說秒裕,JSX 更易寫也更易讀。所以钞啸,幾乎所有的 React 開發(fā)者都使用 JSX 語法几蜻。
JSX 語法的特點(diǎn)就是,凡是使用 JavaScript 的值的地方爽撒,都可以插入這種類似 HTML 的語法入蛆。
constelement=<h1>Hello,world!</h1>;
兩個(gè)注意點(diǎn)。
一是所有 HTML 標(biāo)簽必須是閉合的硕勿,如果寫成<h1>Hello就會(huì)報(bào)錯(cuò)哨毁。
如果是那種沒有閉合語法的標(biāo)簽,必須在標(biāo)簽尾部加上斜杠源武,比如<img src="" />扼褪。
二是任何 JSX 表達(dá)式,頂層只能有一個(gè)標(biāo)簽粱栖,也就是說只能有一個(gè)根元素话浇。下面的寫法會(huì)報(bào)錯(cuò)。
// 報(bào)錯(cuò)constelement=<h1>hello</h1><h1>world</h1>;// 不報(bào)錯(cuò)constelement=<div><h1>hello</h1><h1>world</h1></div>;
上面代碼中闹究,第一種寫法會(huì)報(bào)錯(cuò)幔崖,因?yàn)楦氐奈恢糜袃蓚€(gè)并列的<h1>標(biāo)簽。在它們外面再包一層渣淤,就不會(huì)報(bào)錯(cuò)了赏寇。
一般來說,HTML 原生標(biāo)簽都使用小寫价认,開發(fā)者自定義的組件標(biāo)簽首字母大寫嗅定,比如<MyComponent/>。
JSX 語法允許 HTML 與 JS 代碼混寫用踩。
constelement=(<h1>Hello, {formatName(user)}!</h1>);
上面代碼中渠退,<h1>標(biāo)簽的文字內(nèi)容部分嵌入了 JS 代碼忙迁。每次生成的文本,取決于函數(shù)formatName(user)執(zhí)行的結(jié)果碎乃。
可以看到姊扔,JSX 語法的值的部分,只要使用了大括號(hào){}梅誓,就表示進(jìn)入 JS 的上下文旱眯,可以寫入 JS 代碼。
3.React 組件語法
雖然輸出 JSX 代碼的函數(shù)就是一個(gè) React 組件证九,但是這種寫法只適合那些最簡單的組件。更正式共虑、更通用的組件寫法愧怜,要使用 ES6 類(class)的語法。
import React from 'react';
class ShoppingList extends React.Component {
? render() {
? ? return (
? ? ? <div className="shopping-list">
? ? ? ? <h1>Shopping List for {this.props.name}</h1>
? ? ? ? <ul>
? ? ? ? ? <li>Instagram</li>
? ? ? ? ? <li>WhatsApp</li>
? ? ? ? ? <li>Oculus</li>
? ? ? ? </ul>
? ? ? </div>
? ? );
? }
}
export default ShoppingList;
上面代碼定義了一個(gè) ShoppingList 組件妈拌。自定義的組件必須繼承React.Component這個(gè)基類拥坛,然后必須有一個(gè)render方法,給出組件的輸出尘分。
使用 React 組件也很簡單猜惋,引入這個(gè)組件以后,就可以直接使用培愁。假定上面的組件腳本叫做shoppinglist.js著摔,那么使用它的代碼如下。
import React from 'React';
import ShoppingList from './shoppinglist.js';
class Content extends React.Component {
? render() {
? ? return (
? ? ? <ShoppingList name="張三" />
? ? );
? }
}
export default Content;
上面代碼中定续,我們新建了一個(gè)Content組件谍咆,里面使用了ShoppingList組件。注意私股,由于這個(gè)組件除了name參數(shù)摹察,沒有其他內(nèi)容,所以可以寫成<ShoppingList name="張三"/>這種直接閉合的形式倡鲸。否則供嚎,可以寫成下面的形式。
class Content extends React.Component {
? render() {
? ? return (
? ? ? <ShoppingList name="張三">
? ? ? ? {/* 插入的其他內(nèi)容 */}
? ? ? </ShoppingList>
? ? );
? }
}
4.組件的參數(shù)
組件內(nèi)部峭状,所有參數(shù)都放在this.props屬性上面克滴。如通過this.props.name就可以拿到傳入的值(張三)。
<h1>Shopping List for {this.props.name}</h1>
5.組件的狀態(tài)
除了接受外部參數(shù)宁炫,組件內(nèi)部也有不同的狀態(tài)偿曙。React 規(guī)定,組件的內(nèi)部狀態(tài)記錄在this.state這個(gè)對象上面羔巢。
6.生命周期方法
組件的運(yùn)行過程中望忆,存在不同的階段罩阵。React 為這些階段提供了鉤子方法,允許開發(fā)者自定義每個(gè)階段自動(dòng)執(zhí)行的函數(shù)启摄。這些方法統(tǒng)稱為生命周期方法(lifecycle methods)稿壁。
class Clock extends React.Component {
? constructor(props) {
? ? super(props);
? ? this.state = {date: new Date()};
? }
? componentDidMount() {
? }
? componentWillUnmount() {
? }
? componentDidUpdate() {
? }
? render() {
? ? return (
? ? ? <div>
? ? ? ? <h1>Hello, world!</h1>
? ? ? ? <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
? ? ? </div>
? ? );
? }
}
上面代碼中,componentDidMount()歉备、componentWillUnmount()和componentDidUpdate()就是三個(gè)最常用的生命周期方法傅是。其中,componentDidMount()會(huì)在組件掛載后自動(dòng)調(diào)用蕾羊,componentWillUnmount()會(huì)在組件卸載前自動(dòng)調(diào)用喧笔,componentDidUpdate()會(huì)在 UI 每次更新后調(diào)用(即組件掛載成功以后,每次調(diào)用 render 方法龟再,都會(huì)觸發(fā)這個(gè)方法)书闸。