極客園PC-第4章 文章列表
阿新 • • 發佈:2022-03-24
文章列表功能
card元件與麵包屑導航
- card元件,文件:https://ant.design/components/card-cn/
import { Card } from 'antd'
export default class ArticleList extends Component {
render() {
return (
<div className="articleList">
<Card title="麵包屑導航">我是內容</Card>
</div>
)
}
}
- 麵包屑導航的使用
export default class ArticleList extends Component { render() { return ( <div className={styles.root}> <Card title={ <Breadcrumb> <Breadcrumb.Item> <Link to="/home">首頁</Link> </Breadcrumb.Item> <Breadcrumb.Item>文章列表</Breadcrumb.Item> </Breadcrumb> } > 內容 </Card> </div> ) } }
搜尋表單基本結構
- 複製表單的基本結構到元件中
- 修改表單結構
<Card title={ <Breadcrumb separator="/"> <Breadcrumb.Item> <Link to="/home">首頁</Link> </Breadcrumb.Item> <Breadcrumb.Item>文章列表</Breadcrumb.Item> </Breadcrumb> } > <Form> <Form.Item label="狀態" name="username"> <Input /> </Form.Item> <Form.Item label="頻道" name="password"> <Input.Password /> </Form.Item> <Form.Item label="日期" name="password"> <Input.Password /> </Form.Item> <Form.Item> <Button type="primary" htmlType="submit"> 篩選 </Button> </Form.Item> </Form> </Card>
- 狀態的基本結構
<Form initialValues={{ status: null }}>
<Form.Item label="狀態" name="status">
<Radio.Group>
<Radio value={null}>全部</Radio>
<Radio value={0}>草稿</Radio>
<Radio value={1}>待稽核</Radio>
<Radio value={2}>稽核通過</Radio>
<Radio value={3}>稽核失敗</Radio>
</Radio.Group>
</Form.Item>
- 下拉框結構
<Form.Item label="頻道" name="password">
<Select placeholder="請選擇頻道" style={{ width: 200 }}>
<Option value="jack">Jack</Option>
<Option value="lucy">Lucy</Option>
<Option value="Yiminghe">yiminghe</Option>
</Select>
</Form.Item>
- 日期選擇基本結構
import { Card, Breadcrumb, Form, Button, Radio, Select, DatePicker } from 'antd'
const { RangePicker } = DatePicker
<Form.Item label="日期" name="password">
<RangePicker />
</Form.Item>
日期中文處理
在index.js中
import React from 'react'
import ReactDOM from 'react-dom'
// 在 index.js 中匯入 antd 的樣式檔案
import 'antd/dist/antd.css'
import './index.css'
import { ConfigProvider } from 'antd'
import 'moment/locale/zh-cn'
import locale from 'antd/lib/locale/zh_CN'
import App from './App'
ReactDOM.render(
<ConfigProvider locale={locale}>
<App />
</ConfigProvider>,
document.getElementById('root')
)
頻道資料管理
- 封裝介面
import request from 'utils/request'
/*
獲取所有的頻道
*/
export const getChannels = () => {
return request.get('/channels')
}
- 傳送請求獲取資料
import { getChannels } from 'api/channel'
state = {
channels: [],
}
async getChannelList() {
const res = await getChannels()
this.setState({
channels: res.data.channels,
})
}
componentDidMount() {
this.getChannelList()
}
- 渲染頻道資料
<Select placeholder="請選擇頻道" style={{ width: 200 }}>
{this.state.channels.map((item) => (
<Option value={item.id} key={item.id}>
{item.name}
</Option>
))}
</Select>
表格基本結構
- 基本結構
import {
Card,
Breadcrumb,
Form,
Button,
Radio,
Select,
DatePicker,
Table,
Tag,
Space,
} from 'antd'
render() {
const columns = [
{
title: 'Name',
dataIndex: 'name',
key: 'name',
render: (text) => <a>{text}</a>,
},
{
title: 'Age',
dataIndex: 'age',
key: 'age',
},
{
title: 'Address',
dataIndex: 'address',
key: 'address',
},
{
title: 'Tags',
key: 'tags',
dataIndex: 'tags',
render: (tags) => (
<>
{tags.map((tag) => {
let color = tag.length > 5 ? 'geekblue' : 'green'
if (tag === 'loser') {
color = 'volcano'
}
return (
<Tag color={color} key={tag}>
{tag.toUpperCase()}
</Tag>
)
})}
</>
),
},
{
title: 'Action',
key: 'action',
render: (text, record) => (
<Space size="middle">
<a>Invite {record.name}</a>
<a>Delete</a>
</Space>
),
},
]
const data = [
{
key: '1',
name: 'John Brown',
age: 32,
address: 'New York No. 1 Lake Park',
tags: ['nice', 'developer'],
},
{
key: '2',
name: 'Jim Green',
age: 42,
address: 'London No. 1 Lake Park',
tags: ['loser'],
},
{
key: '3',
name: 'Joe Black',
age: 32,
address: 'Sidney No. 1 Lake Park',
tags: ['cool', 'teacher'],
},
]
return (
<div className="articleList">
<Card title={`根據篩選條件共查詢到${0}條資料`}>
<Table dataSource={data} columns={columns} />
</Card>
</div>
)
}
獲取文章列表資料
- 封裝介面
import request from 'utils/request'
/**
* 獲取文章列表
* @param {*} params
* @returns
*/
export const getArticles = (params) => {
return request({
url: '/mp/articles',
method: 'get',
params,
})
}
- 傳送請求獲取文章列表資料
state = {
channels: [],
articles: [],
total: 0,
}
async getChannelList() {
const res = await getChannels()
this.setState({
channels: res.data.channels,
})
}
async getArticleList() {
const res = await getArticles()
this.setState({
articles: res.data.results,
total: res.data.total_count,
})
}
componentDidMount() {
this.getChannelList()
this.getArticleList()
}
渲染表格資料
- 修改columns
const columns = [
{
title: '封面',
dataIndex: 'name',
},
{
title: '標題',
dataIndex: 'title',
},
{
title: '狀態',
dataIndex: 'status',
},
{
title: '釋出時間',
dataIndex: 'pubdate',
},
{
title: '閱讀數',
dataIndex: 'read_count',
},
{
title: '評論數',
dataIndex: 'comment_count',
},
{
title: '點贊數',
dataIndex: 'like_count',
},
{
title: '操作',
},
]
- 封面處理
{
title: '封面',
dataIndex: 'cover',
render(data) {
const { images, type } = data
if (type === 0) {
return (
<Image width={200} preview={false} height={150} src={defaultImg} />
)
}
return (
<Image width={200} height={150} src={images[0]} fallback={defaultImg} />
)
},
},
- 狀態處理
// 通過物件來優化if/switch
// 使用方式:articleStatus[0] => { text: '草稿', color: '' }
const articleStatus = {
0: { text: '草稿', color: 'gold' },
1: { text: '待稽核', color: 'lime' },
2: { text: '稽核通過', color: 'green' },
3: { text: '稽核失敗', color: 'red' },
}
{
title: '狀態',
dataIndex: 'status',
render: (data) => {
const tagObj = articleStatus[data]
return <Tag color={tagObj.color}>{tagObj.text}</Tag>
},
},
- 操作功能
{
title: '操作',
render() {
return (
<Space>
<Button
type="primary"
shape="circle"
icon={<EditOutlined />}
></Button>
<Button
type="primary"
shape="circle"
danger
icon={<DeleteOutlined />}
></Button>
</Space>
)
},
},
key屬性處理
<Card title={`根據篩選條件共查詢到${this.state.total}條資料`}>
<Table
rowKey="id"
dataSource={this.state.articles}
columns={columns}
/>
</Card>
分頁功能
- 使用分頁元件
<Card title={`根據篩選條件共查詢到${this.state.total_count}條資料`}>
<Table
rowKey="id"
dataSource={results}
columns={columns}
pagination={{
position: ['bottomCenter'],
current: page,
pageSize: per_page,
total: total_count,
// 每頁大小 或者 頁碼 改變時,觸發的事件
onChange: this.changePage,
}}
/>
</Card>
- 提供changePage事件
changePage = async (page, pageSize) => {
console.log(page)
const res = await getArticles({
page,
per_page: this.state.articles.per_page,
})
this.setState({
articles: res.data,
})
}
獲取表單的值進行篩選
- 給表單註冊事件
<Form initialValues={{ status: -1 }} onFinish={this.onFinish}>
- 給表單元素提供name屬性
<Form.Item label="狀態" name="status">
<Radio.Group>
<Radio value={-1}>全部</Radio>
<Radio value={0}>草稿</Radio>
<Radio value={1}>待稽核</Radio>
<Radio value={2}>稽核通過</Radio>
<Radio value={3}>稽核失敗</Radio>
</Radio.Group>
</Form.Item>
<Form.Item label="頻道" name="channel_id">
<Select placeholder="請選擇頻道" style={{ width: 200 }}>
{this.state.channels.map((item) => (
<Option value={item.id} key={item.id}>
{item.name}
</Option>
))}
</Select>
</Form.Item>
<Form.Item label="日期" name="date">
<RangePicker />
</Form.Item>
- 傳送請求,獲取資料
onFinish = async (values) => {
console.log(values)
// 傳送請求,獲取資料
const params = {}
// 處理狀態
if (values.status !== -1) {
params.status = values.status
}
// 處理頻道
if (values.channel_id) {
params.channel_id = values.channel_id
}
// 處理日期
if (values.date) {
params.begin_pubdate = values.date[0].format('YYYY-MM-DD')
params.end_pubdate = values.date[1].format('YYYY-MM-DD')
}
params.page = 1
const res = await getArticles(params)
console.log(res.data)
this.setState({
articles: res.data,
})
}
時間的優化
// 處理日期
if (values.date) {
params.begin_pubdate = values.date[0]
.startOf('day')
.format('YYYY-MM-DD HH:mm:ss')
params.end_pubdate = values.date[1]
.endOf('day')
.format('YYYY-MM-DD HH:mm:ss')
}
修改分頁bug
changePage = async (page, pageSize) => {
const res = await getArticles({
...this.params,
page,
per_page: this.state.articles.per_page,
})
this.setState({
articles: res.data,
})
}
onFinish = async (values) => {
console.log(values)
// 傳送請求,獲取資料
const params = {}
// 處理狀態
if (values.status !== -1) {
params.status = values.status
}
// 處理頻道
if (values.channel_id) {
params.channel_id = values.channel_id
}
// 處理日期
if (values.date) {
params.begin_pubdate = values.date[0]
.startOf('day')
.format('YYYY-MM-DD HH:mm:ss')
params.end_pubdate = values.date[1]
.endOf('day')
.format('YYYY-MM-DD HH:mm:ss')
}
params.page = 1
this.params = params
const res = await getArticles(params)
console.log(res.data)
this.setState({
articles: res.data,
})
}
刪除功能
- 註冊點選事件
<Button
type="primary"
shape="circle"
danger
icon={<DeleteOutlined />}
onClick={() => this.handleDelete(data.id)}
></Button>
- 準備彈窗
handleDelete = (id) => {
confirm({
title: '溫馨提示?',
icon: <ExclamationCircleOutlined />,
content: '你確定要刪除文章嗎',
onOk() {
// 傳送請求進行刪除
},
})
}
- 封裝介面進行刪除
/**
* 刪除文章
* @param {*} id
* @returns
*/
export const delArticle = (id) => {
return request({
url: `/mp/articles/${id}`,
method: 'delete',
})
}
- 刪除功能完成
handleDelete = (id) => {
confirm({
title: '溫馨提示?',
icon: <ExclamationCircleOutlined />,
content: '你確定要刪除文章嗎',
onOk: async () => {
// 傳送請求進行刪除
await delArticle(id)
this.getArticleList(this.params)
},
})
}
釋出文章
基本結構準備
- 麵包屑
import React, { Component } from 'react'
import { Card, Breadcrumb } from 'antd'
import { Link } from 'react-router-dom'
export default class ArticleList extends Component {
render() {
return (
<div className="ArticleList">
<Card
title={
<Breadcrumb separator=">">
<Breadcrumb.Item>
<Link to="/home">首頁</Link>
</Breadcrumb.Item>
<Breadcrumb.Item>釋出文章</Breadcrumb.Item>
</Breadcrumb>
}
></Card>
</div>
)
}
}
- 表單
import { Card, Breadcrumb, Form, Input, Radio, Space, Button } from 'antd'
<Form labelCol={{ span: 4 }} initialValues={{ type: 0 }}>
<Form.Item label="標題" name="title">
<Input placeholder="請輸入文章標題" style={{ width: 400 }} />
</Form.Item>
<Form.Item label="頻道" name="channel_id">
頻道元件
</Form.Item>
<Form.Item label="封面">
<Form.Item name="type">
<Radio.Group onChange={this.changeImageType}>
<Radio value={0}>無圖</Radio>
<Radio value={1}>單圖</Radio>
<Radio value={3}>三圖</Radio>
{/* <Radio value={-1}>自動</Radio> */}
</Radio.Group>
</Form.Item>
圖片上傳元件
</Form.Item>
<Form.Item label="內容" name="content">
文章內容
</Form.Item>
<Form.Item wrapperCol={{ offset: 4 }}>
<Space>
<Button size="large" type="primary" htmlType="submit">
釋出文章
</Button>
<Button size="large">存入草稿</Button>
</Space>
</Form.Item>
</Form>
- 給表單註冊事件
<Form
labelCol={{ span: 4 }}
initialValues={{ type: 0 }}
onFinish={this.onFinish}
>
onFinish = (values) => {
console.log(values)
}
頻道元件封裝
- 基礎封裝
import { Component } from 'react'
import { Select } from 'antd'
import { getChannels } from 'api/channel'
const { Option } = Select
class Channel extends Component {
state = {
channels: [],
}
componentDidMount() {
this.getChannles()
}
// 獲取頻道列表資料的方法
async getChannles() {
const res = await getChannels()
this.setState({
channels: res.data.channels,
})
}
render() {
const { channels } = this.state
return (
<Select placeholder="請選擇文章頻道">
{channels.map((item) => (
<Option key={item.id} value={item.id}>
{item.name}
</Option>
))}
</Select>
)
}
}
export default Channel
- 使用頻道元件
import Channel from 'components/Channel'
<Form.Item label="頻道" name="channel_id">
<Channel></Channel>
</Form.Item>
- 讓頻道元件受控
參考文件:https://ant-design.gitee.io/components/form-cn/#components-form-demo-customized-form-controls
render() {
const { channels } = this.state
const { value, onChange } = this.props
return (
<Select
placeholder="請選擇文章頻道"
style={{ width: 200 }}
value={value}
onChange={onChange}
>
{channels.map((item) => (
<Option key={item.id} value={item.id}>
{item.name}
</Option>
))}
</Select>
)
}
文章內容處理
- 使用react-quill富文字編輯器 https://github.com/zenoamaro/react-quill
import ReactQuill from 'react-quill';
import 'react-quill/dist/quill.snow.css';
<Form.Item label="內容" name="content">
<ReactQuill
theme="snow"
placeholder="請輸入文章內容..."
></ReactQuill>
</Form.Item>
- 注意:必須提供預設值,不然會報錯
- 提供樣式
.publish {
:global {
.ql-editor {
min-height: 300px;
}
}
}
圖片上傳元件
- 基本結構
import {
Card,
Breadcrumb,
Form,
Input,
Radio,
Space,
Button,
Upload,
} from 'antd'
import { PlusOutlined } from '@ant-design/icons'
<Upload listType="picture-card">
<PlusOutlined></PlusOutlined>
</Upload>
- 設定圖片預設顯示
<Upload
listType="picture-card"
name="image"
fileList={this.state.fileList}
>
<PlusOutlined></PlusOutlined>
</Upload>
state = {
// 存放上傳的檔案列表
fileList: [
{
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
},
{
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
},
],
}
- 圖片上傳功能, 需要提供name和action引數
<Upload
listType="picture-card"
name="image"
action={`${baseURL}upload`}
onChange={this.uploadImages}
fileList={this.state.fileList}
>
<PlusOutlined></PlusOutlined>
</Upload>
- 獲取上傳成功的圖片地址
uploadImages = ({ file, fileList }) => {
this.setState({
fileList,
})
}
控制圖片的上傳數量
- 控制type的切換
state = {
// 存放上傳的檔案列表
fileList: [],
type: 0,
}
<Radio.Group onChange={this.changeImageType}>
<Radio value={0}>無圖</Radio>
<Radio value={1}>單圖</Radio>
<Radio value={3}>三圖</Radio>
</Radio.Group>
changeImageType = (e) => {
this.setState({
type: e.target.value,
})
}
- 根據type控制圖片的顯示
{this.state.type !== 0 && (
<Upload
listType="picture-card"
name="image"
action={`${baseURL}upload`}
onChange={this.uploadImages}
fileList={this.state.fileList}
>
<PlusOutlined></PlusOutlined>
</Upload>
)}
- 控制圖片的上傳資料
{this.state.type !== 0 && (
<Upload
listType="picture-card"
name="image"
action={`${baseURL}upload`}
onChange={this.uploadImages}
fileList={this.state.fileList}
>
{this.state.fileList.length < this.state.type && (
<PlusOutlined></PlusOutlined>
)}
</Upload>
)}
圖片預覽功能
圖片格式校驗
表單校驗功能
- 表單基本校驗
<Form.Item
label="標題"
name="title"
rules={[{ required: true, message: '請輸入文章標題' }]}
>
<Input placeholder="請輸入文章標題" style={{ width: 400 }} />
</Form.Item>
<Form.Item
label="頻道"
name="channel_id"
rules={[{ required: true, message: '請選擇文章頻道' }]}
>
<Channel></Channel>
</Form.Item>
<Form.Item label="封面">
<Form.Item name="type">
<Radio.Group onChange={this.changeImageType}>
<Radio value={1}>單圖</Radio>
<Radio value={3}>三圖</Radio>
<Radio value={0}>無圖</Radio>
{/* <Radio value={-1}>自動</Radio> */}
</Radio.Group>
</Form.Item>
<div className="upload-list">
{this.state.type !== 0 && (
<Upload
listType="picture-card"
name="image"
action={`${baseURL}upload`}
onChange={this.uploadImages}
fileList={this.state.fileList}
>
{this.state.fileList.length < this.state.type && (
<PlusOutlined></PlusOutlined>
)}
</Upload>
)}
</div>
</Form.Item>
<Form.Item
label="內容"
name="content"
rules={[{ required: true, message: '請輸入文章內容' }]}
>
<ReactQuill
theme="snow"
placeholder="請輸入文章內容..."
></ReactQuill>
</Form.Item>
- 圖片長度的校驗
onFinish = async (values) => {
// 圖片校驗
if (this.state.type !== this.state.fileList.length) {
return message.warn('上傳的圖片數量不對')
}
}
傳送請求-新增文章
- 封裝介面
/**
* 傳送請求新增文章
* @param {*} data
* @returns
*/
export const addArticle = (data) => {
return request({
url: '/mp/articles',
method: 'post',
data,
})
}
- 傳送請求-處理資料並且新增文章
onFinish = async (values) => {
console.log(values)
// 處理資料,新增文章
const images = this.state.fileList.map((item) => {
if (item.url) {
return item.url
}
return item.response.data.url
})
const res = await addArticle({
...values,
cover: {
type: values.type,
images,
},
})
message.success('新增文章成功')
this.props.history.push('/home/list')
}
存入草稿功能
- 修改介面
/**
* 傳送請求新增文章
* @param {*} data
* @returns
*/
export const addArticle = (data, draft = false) => {
return request({
url: '/mp/articles?draft=' + draft,
method: 'post',
data,
})
}
- 註冊點選事件
<Button size="large" onClick={this.addDraft}>
存入草稿
</Button>
- 提供事件
onFinish = async (values) => {
this.save(values, false)
}
save = async (values, draft) => {
// 圖片校驗
if (this.state.type !== this.state.fileList.length) {
return message.warn('上傳的圖片數量不對')
}
// 處理資料,新增文章
const images = this.state.fileList.map((item) => {
if (item.url) {
return item.url
}
return item.response.data.url
})
await addArticle(
{
...values,
cover: {
type: values.type,
images,
},
},
draft
)
message.success('新增文章成功')
this.props.history.push('/home/list')
}
addDraft = async () => {
// 獲取表單的資料
const values = await this.formRef.current.validateFields()
this.save(values, true)
}
修改功能
配置修改文章的路由
- 給修改按鈕註冊點選事件
<Button
type="primary"
shape="circle"
icon={<EditOutlined />}
onClick={() => this.handleEdit(data.id)}
/>
// 修改
handleEdit = (id) => {
this.props.history.push(`/home/publish/${id}`)
}
- 配置修改文章的路由
{/* 新增 */}
<Route
exact
path="/home/publish"
component={ArticlePublish}
></Route>
{/* 修改的路由 */}
<Route
path="/home/publish/:id"
component={ArticlePublish}
></Route>
資料回顯-獲取資料
思路
- 在元件中判斷能夠通過params獲取到id值,如果能夠獲取到id,說明是修改,如果獲取不到id說明是新增
- 我們根據是否是新增可以修改對應的文字。【釋出文章】或者【修改文章】
- 封裝介面,用於獲取文章的詳情資訊
- 傳送請求,獲取文章的詳細資訊
- 獲取位址列的id值
state = {
// 文章的封面型別
type: 1,
// 用於控制上傳的圖片以及圖片的顯示
fileList: [],
showPreview: false,
previewUrl: '',
// 編輯的id
+ id: this.props.match.params.id,
}
- 根據是否有id值,控制文字的顯示
{id ? '編輯文章' : '釋出文章'}
- 封裝介面,獲取文章詳情
/**
* 獲取文章詳情資訊
* @param {*} id
* @returns
*/
export const getArticleById = (id) => {
return request.get(`/mp/articles/${id}`)
}
- 頁面渲染完成的時候,傳送請求-獲取資料
async componentDidMount() {
if (this.state.id) {
// 需要發請求,獲取文章詳細資訊
const res = await getArticleById(this.state.id)
console.log('res', res)
}
}
資料回顯-回顯資料
思路:
- 通過Form元件提供的方法 setFieldsValue 可以給表單設定值
- 設定fileList的值,fileList控制封面顯示的
- 設定表單的值
async componentDidMount() {
if (this.state.id) {
// 需要發請求,獲取文章詳細資訊
const res = await getArticleById(this.state.id)
const values = {
...res.data,
type: res.data.cover.type,
}
// 給表單設定values值
this.formRef.current.setFieldsValue(values)
const fileList = res.data.cover.images.map((item) => {
return {
url: item,
}
})
this.setState({
fileList,
})
}
}
修復bug-修改切換到新增的bug
{/* 新增 */}
<Route
exact
path="/home/publish"
component={ArticlePublish}
key="add"
></Route>
{/* 修改的路由 */}
<Route
path="/home/publish/:id"
component={ArticlePublish}
key="edit"
></Route>
修改功能完成
- 封裝介面,用於修改文章
- 判斷是否有id,如果有,傳送請求修改,否則,傳送請求新增
- 封裝介面
/**
* 修改文章的介面
* @param {*} data
* @param {*} draft
* @returns
*/
export const updateArticle = (data, draft) => {
return request({
url: `/mp/articles/${data.id}?draft=${draft}`,
method: 'PUT',
data,
})
}
- 判斷
async save(values, draft) {
const { fileList, type } = this.state
if (fileList.length !== type) {
return message.warn('上傳的圖片數量不正確')
}
// 根據fileList得到
const images = fileList.map((item) => {
return item.url || item.response.data.url
})
if (this.state.id) {
// 修改文章
await updateArticle(
{
...values,
cover: {
type,
images,
},
id: this.state.id,
},
draft
)
message.success('修改成功')
} else {
// 新增文章
await addAritcle(
{
...values,
cover: {
type,
images,
},
},
draft
)
message.success('新增成功')
}
this.props.history.push('/home/list')
}
導航高亮優化
- 給選單按鈕提供selectedKeys屬性
<Menu
theme="dark"
mode="inline"
selectedKeys={[this.state.selectedKey]}
style={{ height: '100%', borderRight: 0 }}
>
state = {
profile: {},
selectedKey: this.props.location.pathname,
}
- 需要在元件更新的時候,修改selectedKeys的值
// 元件更新完成的鉤子函式,,,路由變化了,元件也是會重新渲染
// prevProps: 上一次的props
componentDidUpdate(prevProps) {
// 判斷是否是url地址發生了變化,如果是,才更新
let pathname = this.props.location.pathname
if (this.props.location.pathname !== prevProps.location.pathname) {
// 考慮修改文章的高亮問題
if (pathname.startsWith('/home/publish')) {
pathname = '/home/publish'
}
this.setState({
selectedKey: pathname,
})
}
}
注意:在componentDidUpdate中想要呼叫setState必須新增判斷,不然會死迴圈