一、創(chuàng)建項(xiàng)目
npm v5.2.0引入的一條命令(npx)谤狡,引入這個(gè)命令的目的是為了提升開發(fā)者使用包內(nèi)提供的命令行工具的體驗(yàn)。
舉例:使用create-react-app創(chuàng)建一個(gè)react項(xiàng)目。
老方法:
npm install -g create-react-app
create-react-app my-app
npx方式:
npx create-react-app my-app
這條命令會臨時(shí)安裝 create-react-app 包,命令完成后create-react-app 會刪掉宏怔,不會出現(xiàn)在 global 中。下次再執(zhí)行畴椰,還是會重新臨時(shí)安裝臊诊。
npx 會幫你執(zhí)行依賴包里的二進(jìn)制文件。
舉例來說斜脂,之前我們可能會寫這樣的命令:
npm i -D webpack
./node_modules/.bin/webpack -v
如果你對 bash 比較熟抓艳,可能會寫成這樣:
npm i -D webpack
`npm bin`/webpack -v
有了 npx,你只需要這樣:
npm i -D webpack
npx webpack -v
也就是說 npx 會自動(dòng)查找當(dāng)前依賴包中的可執(zhí)行文件帚戳,如果找不到玷或,就會去 PATH 里找。如果依然找不到销斟,就會幫你安裝庐椒!
npx 甚至支持運(yùn)行遠(yuǎn)程倉庫的可執(zhí)行文件:
npx github:piuccio/cowsay hello
再比如 npx http-server 可以一句話幫你開啟一個(gè)靜態(tài)服務(wù)器!(第一次運(yùn)行會稍微慢一些)
npx http-server
指定node版本來運(yùn)行npm scripts:
npx -p node@8 npm run build
主要特點(diǎn):
1蚂踊、臨時(shí)安裝可執(zhí)行依賴包,不用全局安裝笔宿,不用擔(dān)心長期的污染犁钟。
2、可以執(zhí)行依賴包中的命令泼橘,安裝完成自動(dòng)運(yùn)行涝动。
3、自動(dòng)加載node_modules中依賴包炬灭,不用指定$PATH醋粟。
4、可以指定node版本、命令的版本米愿,解決了不同項(xiàng)目使用不同版本的命令的問題厦凤。
Yarn是什么?
“Yarn是由Facebook育苟、Google较鼓、Exponent 和 Tilde 聯(lián)合推出了一個(gè)新的 JS 包管理工具 ,正如官方文檔中寫的违柏,Yarn 是為了彌補(bǔ) npm 的一些缺陷而出現(xiàn)的博烂。”這句話讓我想起了使用npm時(shí)的坑了:
-
npm install
的時(shí)候巨慢漱竖。特別是新的項(xiàng)目拉下來要等半天禽篱,刪除node_modules,重新install的時(shí)候依舊如此馍惹。 - 同一個(gè)項(xiàng)目谆级,安裝的時(shí)候無法保持一致性。由于package.json文件中版本號的特點(diǎn)讼积,下面三個(gè)版本號在安裝的時(shí)候代表不同的含義肥照。
"5.0.3",
"~5.0.3",
"^5.0.3"
“5.0.3”表示安裝指定的5.0.3版本,“~5.0.3”表示安裝5.0.X中最新的版本勤众,“^5.0.3”表示安裝5.X.X中最新的版本舆绎。這就麻煩了,常常會出現(xiàn)同一個(gè)項(xiàng)目们颜,有的同事是OK的吕朵,有的同事會由于安裝的版本不一致出現(xiàn)bug。
- 安裝的時(shí)候窥突,包會在同一時(shí)間下載和安裝努溃,中途某個(gè)時(shí)候,一個(gè)包拋出了一個(gè)錯(cuò)誤阻问,但是npm會繼續(xù)下載和安裝包梧税。因?yàn)閚pm會把所有的日志輸出到終端,有關(guān)錯(cuò)誤包的錯(cuò)誤信息就會在一大堆npm打印的警告中丟失掉称近,并且你甚至永遠(yuǎn)不會注意到實(shí)際發(fā)生的錯(cuò)誤第队。
帶著這些坑,我開始了解Yarn的優(yōu)勢及其解決的問題刨秆。
Yarn的優(yōu)點(diǎn)凳谦?
- 速度快 。速度快主要來自以下兩個(gè)方面:
- 并行安裝:無論 npm 還是 Yarn 在執(zhí)行包的安裝時(shí)衡未,都會執(zhí)行一系列任務(wù)尸执。npm 是按照隊(duì)列執(zhí)行每個(gè) package家凯,也就是說必須要等到當(dāng)前 package 安裝完成之后,才能繼續(xù)后面的安裝如失。而 Yarn 是同步執(zhí)行所有任務(wù)绊诲,提高了性能。
- 離線模式:如果之前已經(jīng)安裝過一個(gè)軟件包岖常,用Yarn再次安裝時(shí)之間從緩存中獲取驯镊,就不用像npm那樣再從網(wǎng)絡(luò)下載了。
- 安裝版本統(tǒng)一:為了防止拉取到不同的版本竭鞍,Yarn 有一個(gè)鎖定文件 (lock file) 記錄了被確切安裝上的模塊的版本號板惑。每次只要新增了一個(gè)模塊,Yarn 就會創(chuàng)建(或更新)yarn.lock 這個(gè)文件偎快。這么做就保證了冯乘,每一次拉取同一個(gè)項(xiàng)目依賴時(shí),使用的都是一樣的模塊版本晒夹。npm 其實(shí)也有辦法實(shí)現(xiàn)處處使用相同版本的 packages裆馒,但需要開發(fā)者執(zhí)行 npm shrinkwrap 命令。這個(gè)命令將會生成一個(gè)鎖定文件丐怯,在執(zhí)行 npm install 的時(shí)候喷好,該鎖定文件會先被讀取,和 Yarn 讀取 yarn.lock 文件一個(gè)道理读跷。npm 和 Yarn 兩者的不同之處在于梗搅,Yarn 默認(rèn)會生成這樣的鎖定文件,而 npm 要通過 shrinkwrap 命令生成 npm-shrinkwrap.json 文件效览,只有當(dāng)這個(gè)文件存在的時(shí)候液斜,packages 版本信息才會被記錄和更新净当。
- 更簡潔的輸出:npm 的輸出信息比較冗長。在執(zhí)行 npm install <package> 的時(shí)候杆兵,命令行里會不斷地打印出所有被安裝上的依賴始鱼。相比之下娜扇,Yarn 簡潔太多:默認(rèn)情況下逗物,結(jié)合了 emoji直觀且直接地打印出必要的信息方库,也提供了一些命令供開發(fā)者查詢額外的安裝信息。
- 多注冊來源處理:所有的依賴包沼本,不管他被不同的庫間接關(guān)聯(lián)引用多少次噩峦,安裝這個(gè)包時(shí),只會從一個(gè)注冊來源去裝抽兆,要么是 npm 要么是 bower, 防止出現(xiàn)混亂不一致。
- 更好的語義化: yarn改變了一些npm命令的名稱族淮,比如 yarn add/remove辫红,感覺上比 npm 原本的 install/uninstall 要更清晰凭涂。
Yarn和npm命令對比
npm | yarn |
---|---|
npm install | yarn |
npm install react --save | yarn add react |
npm uninstall react --save | yarn remove react |
npm install react --save-dev | yarn add react --dev |
npm update --save | yarn upgrade |
Yarn提供了豐富的命令使你可以對Yarn包進(jìn)行許多操作,包括安裝贴妻、管理切油、發(fā)布等。
所有可用的命令都按照字母先后順序列在此處名惩,其中最常用的有:
-
yarn add
:為當(dāng)前正在開發(fā)的包新增一個(gè)依賴包澎胡; -
yarn init
:初始化包; -
yarn install
:安裝package.json
文件里定義的所有依賴包娩鹉; -
yarn publish
:發(fā)布一個(gè)包到包管理器攻谁; -
yarn remove
:從當(dāng)前包里移除一個(gè)未使用的包。
npm i yarn -g
yarn start
下面的圖片可知弯予,打印出了訪問該項(xiàng)目的兩種方式(IP或者localhost)
Yarn更換源
二、集成ant-design
在使用react項(xiàng)目中锈嫩,不可避免的要使用螞蟻金服出品的ant-desgin前端UI組件受楼,ant-desgin推薦使用 craco (一個(gè)對 create-react-app 進(jìn)行自定義配置的社區(qū)解決方案),對 create-react-app 的默認(rèn)配置進(jìn)行自定義呼寸。
https://ant.design/docs/react/use-with-create-react-app-cn
這是 create-react-app 生成的默認(rèn)目錄結(jié)構(gòu)艳汽。
├── README.md
├── package.json
├── public
│ ├── favicon.ico
│ └── index.html
├── src
│ ├── App.css
│ ├── App.js
│ ├── App.test.js
│ ├── index.css
│ ├── index.js
│ └── logo.svg
└── yarn.lock
現(xiàn)在從 yarn 或 npm 安裝并引入 antd。
$ yarn add antd
驗(yàn)證antd效果
修改 src/App.js
对雪,引入 antd 的按鈕組件河狐。
import React from 'react';
import { Button } from 'antd';
import './App.css';
const App = () => (
<div className="App">
<Button type="primary">Button</Button>
</div>
);
export default App;
修改 src/App.css
,在文件頂部引入 antd/dist/antd.css
慌植。
@import '~antd/dist/antd.css';
好了甚牲,現(xiàn)在你應(yīng)該能看到頁面上已經(jīng)有了 antd 的藍(lán)色按鈕組件,接下來就可以繼續(xù)選用其他組件開發(fā)應(yīng)用了蝶柿。其他開發(fā)流程你可以參考 create-react-app 的官方文檔丈钙。
我們現(xiàn)在已經(jīng)把 antd 組件成功運(yùn)行起來了!
高級配置
這個(gè)例子在實(shí)際開發(fā)中還有一些優(yōu)化的空間交汤,比如無法進(jìn)行主題配置雏赦。
此時(shí)我們需要對 create-react-app 的默認(rèn)配置進(jìn)行自定義,這里我們使用 craco (一個(gè)對 create-react-app 進(jìn)行自定義配置的社區(qū)解決方案)芙扎。
現(xiàn)在我們安裝 craco 并修改 package.json
里的 scripts
屬性星岗。
$ yarn add @craco/craco
/* package.json */
"scripts": {
- "start": "react-scripts start",
- "build": "react-scripts build",
- "test": "react-scripts test",
+ "start": "craco start",
+ "build": "craco build",
+ "test": "craco test",
}
然后在項(xiàng)目根目錄創(chuàng)建一個(gè) craco.config.js
用于修改默認(rèn)配置。
/* craco.config.js */
module.exports = {
// ...
};
自定義主題與啟用less
antd 的樣式使用了 Less 作為開發(fā)語言戒洼,并定義了一系列全局/組件的樣式變量俏橘,你可以根據(jù)需求進(jìn)行相應(yīng)調(diào)整。
以下是一些最常用的通用變量圈浇,所有樣式變量可以在 這里 找到寥掐。
@primary-color: #1890ff; // 全局主色
@link-color: #1890ff; // 鏈接色
@success-color: #52c41a; // 成功色
@warning-color: #faad14; // 警告色
@error-color: #f5222d; // 錯(cuò)誤色
@font-size-base: 14px; // 主字號
@heading-color: rgba(0, 0, 0, 0.85); // 標(biāo)題色
@text-color: rgba(0, 0, 0, 0.65); // 主文本色
@text-color-secondary: rgba(0, 0, 0, 0.45); // 次文本色
@disabled-color: rgba(0, 0, 0, 0.25); // 失效色
@border-radius-base: 2px; // 組件/浮層圓角
@border-color-base: #d9d9d9; // 邊框色
@box-shadow-base: 0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 6px 16px 0 rgba(0, 0, 0, 0.08),
0 9px 28px 8px rgba(0, 0, 0, 0.05); // 浮層陰影
按照 配置主題 的要求靴寂,自定義主題需要用到類似 less-loader 提供的 less 變量覆蓋功能。我們可以引入 craco-less 來幫助加載 less 樣式和修改變量召耘。
首先把 src/App.css
文件修改為 src/App.less
百炬,然后修改樣式引用為 less 文件。
/* src/App.js */
- import './App.css';
+ import './App.less';
/* src/App.less */
- @import '~antd/dist/antd.css';
+ @import '~antd/dist/antd.less';
然后安裝 craco-less
并修改 craco.config.js
文件如下污它。
$ yarn add craco-less
const CracoLessPlugin = require('craco-less');
module.exports = {
plugins: [
{
plugin: CracoLessPlugin,
options: {
lessLoaderOptions: {
lessOptions: {
modifyVars: { '@primary-color': '#1DA57A' },
javascriptEnabled: true,
},
},
},
},
],
};
這里利用了 less-loader 的 modifyVars
來進(jìn)行主題配置剖踊,變量和其他配置方式可以參考 配置主題 文檔。修改后重啟 yarn start
衫贬,如果看到一個(gè)綠色的按鈕就說明配置成功了德澈。
antd 內(nèi)建了深色主題和緊湊主題,你可以參照 使用暗色主題和緊湊主題 進(jìn)行接入祥山。
同樣圃验,你可以使用 react-app-rewired 和 customize-cra 來自定義 create-react-app 的 webpack 配置。
ejec
你也可以使用 create-react-app 提供的 yarn run eject 命令將所有內(nèi)建的配置暴露出來缝呕。不過這種配置方式需要你自行探索澳窑,不在本文討論范圍內(nèi)。
public/index.html
使用create-react-app創(chuàng)建一個(gè)簡單的react項(xiàng)目,會在項(xiàng)目的根目錄下生成一個(gè)入口文件index.js,其內(nèi)容大致如下:
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
上述代碼中,document.getElementById("root")這句就是把根組件掛載在根頁面中,該頁面位于項(xiàng)目的根目錄public/index.html,其內(nèi)容大致如下:
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
</body>
上述代碼中,<div id="root"></div>和document.getElementById("root")相對應(yīng).
App.js布局
<Layout>
<Sider>Sider</Sider>
<Layout>
<Header>Header</Header>
<Content>Content</Content>
<Footer>Footer</Footer>
</Layout>
</Layout>
搜索使用API
查看API使用
引入使用包的部分插件
import {HomeOutlined, ProjectOutlined, AppstoreAddOutlined, PicCenterOutlined, TeamOutlined, ShopOutlined,FileAddOutlined} from '@ant-design/icons'
import {Layout, Menu} from "antd";
const {Sider} = Layout;
const {SubMenu} = Menu;
這里需要注意的是{}里面的大小寫需要注意供常,比如const {SubMenu} = Menu;里面的SubMenu摊聋,寫成了Submenu,并不會報(bào)錯(cuò)栈暇,但是編譯運(yùn)行的時(shí)候麻裁,
改成SubMenu重新編譯即可。
這里其實(shí)可以先寫const {} = Menu;然后在輸入SubMenu的時(shí)候會有提示的源祈,這樣可以避免輸入錯(cuò)誤
基于react-router-dom實(shí)現(xiàn)路由模塊
yarn add react-router-dom
index.js <React.StrictMode> 報(bào)錯(cuò)
在使用了SubMenu之后煎源,點(diǎn)擊二級菜單會有警告,如下香缺,去掉嚴(yán)苛模式即可
index.js <React.StrictMode> 替換為<BrowserRouter>
import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter} from 'react-router-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>
,
document.getElementById('root')
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
App.js 配置導(dǎo)航路由
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
確定路由位置
<Switch>
<Route path="/about">
<About />
</Route>
<Route path="/topics">
<Topics />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
創(chuàng)建頁面組件
index.js
import React from 'react';
import './index.less';
export default class Index extends React.Component{
render() {
return <div className='add'>
category Add
</div>;
}
}
index.less
.add{
background-color: brown;
}
App.js 導(dǎo)入界面引用
import Home from './page/index';
import User from './page/user/index';
import AddCategory from './page/category/add/index';
import Category from './page/category/index';
import AddConfig from './page/config/add/index';
import Config from './page/config/index';
App.js 添加界面路由
import './App.less';
import React from "react";
import {Layout} from "antd";
import DrawerMenu from "./Component/DrawerMenu";
import Header from "./Component/Header";
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
import Home from './page/index';
import User from './page/user/index';
import AddCategory from './page/category/add/index';
import Category from './page/category/index';
import AddConfig from './page/config/add/index';
import Config from './page/config/index';
const {Content,Footer}=Layout;
class App extends React.Component{
state = {
title:'首頁',
collapsed: false
};
render() {
const {collapsed, title} = this.state;
return (
<Layout className='App'>
<DrawerMenu collapsed={collapsed} />
<Layout>
<Header title={title} toggle={(collapsed) => {
this.setState({collapsed});
}}/>
<Content className='App-content'>
<Switch>
<Router path='/' component={Home}/>
<Router path='/category' component={Category}/>
<Router path='/category-add' component={AddCategory}/>
<Router path='/config' component={Config}/>
<Router path='/config-add' component={AddConfig}/>
<Router path='/user' component={User}/>
</Switch>
</Content>
<Footer className='App-footer'>Yatsar美容儀管理后臺 @2020 Created by
<a herf="https://www.baidu.com"> 享維</a>
</Footer>
</Layout>
</Layout>
);
}
}
export default App;
完成跳轉(zhuǎn)
跳轉(zhuǎn)主要在左側(cè)的抽屜菜單欄(DrawerMenu.js)點(diǎn)擊實(shí)現(xiàn)切換邏輯
withRouter 高階組件使用
import { withRouter } from "react-router";
···
//withRouter是react-router的一個(gè)高階組件手销,獲取history
//render時(shí)會把match,location和history傳入props
export default withRouter(Index);
react-router 的history實(shí)現(xiàn)跳轉(zhuǎn)路由
封裝路由跳轉(zhuǎn)
引入react-native-event-bus图张,主要解決頁面跳轉(zhuǎn)之后的數(shù)據(jù)交互和更新
yarn add react-native-event-bus
發(fā)送導(dǎo)航消息
EventBus.getInstance().fireEvent(ROUTE_CHANGE, {goto: route});
import EventBus from "react-native-event-bus";
export const RouteConfig={
home:{
key:'home',
title:'首頁',
pathname: '/'
},
user:{
key:'user',
title: '用戶管理',
pathname: '/user'
},
category:{
key:'category',
title:'商品類別',
pathname: '/category'
},
addCategory:{
key:'addCategory',
title:'添加商品類別',
pathname: '/category-add'
},
configList:{
key:'configList',
title:'配置列表',
pathname: '/config'
},
configAdd:{
key:'configAdd',
title:'添加配置',
pathname: '/config-add'
}
};
export const ROUTE_CHANGE = 'routeChange';
export default class NavigationUtil{
static goto(route, history){
const {pathname} = route;
if (!history || !pathname) {
console.log('history && pathname cannot be null.')
}
//發(fā)送導(dǎo)航消息
EventBus.getInstance().fireEvent(ROUTE_CHANGE, {goto: route});
return params => {
history.push({
pathname,
...(params || {})
})
}
}
}
實(shí)現(xiàn)表格和數(shù)據(jù)分頁
效果展示
Popconfirm
通過 filterDropdown 自定義的列篩選功能锋拖,并實(shí)現(xiàn)一個(gè)搜索列的示例。
https://ant.design/components/table-cn/#components-table-demo-custom-filter-panel
react-highlight-words
多種布局
警告彈窗
react-native-event-bus
驗(yàn)證項(xiàng)目是否正常
后臺springboot打包之后祸轮,war包放到服務(wù)器的tomcat的webapps目錄
查看當(dāng)前tomcat服務(wù)的端口號
這里沒有修改的話兽埃,默認(rèn)是-1,既端口號是8080
baseurl為本地适袜,webapp的war包解壓后的文件夾名字為demo-0.0.1柄错。既服務(wù)器地址為http://localhost:8080/demo-0.0.1 所以前端代碼對應(yīng)的api請求地址的baseurl應(yīng)該相對應(yīng)
export const url = "http://127.0.0.1:8080/demo-0.0.1";
對應(yīng)swagger網(wǎng)址為
http://localhost:8080/demo-0.0.1/swagger-ui.html
請求某個(gè)一接口,查看url
http://127.0.0.1:8080/demo-0.0.1與上面的相對應(yīng)
打開前端界面