① 安裝react腳手架工具css
// 全局安裝 create-react-app sudo npm -g install create-react-app // 經過create-react-app命令建立react項目 create-react-app evernote
除了經過全局安裝create-react-app來建立react項目外,咱們還能夠經過npm init命令去建立,即html
npm init react-app evernote
由於執行npm init
命令的時候,會自動在init以後的包名加上create前綴,因此至關於安裝並執行create-react-app包,因此咱們再傳入項目名稱便可建立對應的react項目了。注意,react的項目名不能以大寫字母開頭。vue
② 修改public下的index.html文件
react項目和vue項目同樣也是單頁面應用,因此public目錄下也會有一個index.html頁面,用於掛載react渲染的結果。因爲咱們的項目中會用到一些字體圖標,因此咱們須要把咱們的字體連接對應的css引入進來,如:react
// public/index.html <!DOCTYPE html> <html lang="en"> <head> <link rel="stylesheet" href="//at.alicdn.com/t/font_1609262_ijm97o315o.css"/> </head> </html>
這個在線css連接能夠到阿里巴巴iconfont字體庫中找到,如圖所示:ios
③ 修改src/App.js文件
src/App.js是項目的根組件,咱們將App.js中的代碼刪除,默認App是函數組件,咱們這裏改爲類組件,由於咱們須要讓App組件擁有本身的狀態,而後修改成以下代碼:git
import React from 'react'; import './App.css'; class App extends React.Component { render() { return ( <div className="app-container"> hello evernote. </div> ); } } export default App;
④ 修改src/App.css
將原來的App.css內容清空,這裏樣式就不作過多解釋,而後修改以下:github
.app-container { display: flex; height: 100%; } .app-left { width: 10%; min-width: 190px; background: #343434; } .app-left-header, .app-left-body-title { display: flex; align-items: center; color: white; font-weight: bold; padding: 10px 0; } .add { width: 25px; height: 25px; display: inline-block; border-radius: 50%; margin: 0 10px; background:#6fcb66; text-align: center; line-height: 25px; font-size: 15px; font-weight: bold; } .notebook-icon { height: 25px; text-align: center; line-height: 25px; margin: 0 5px 0 10px; } .notebook-list, .app-center-list{ margin: 0; list-style: none; padding: 0; color: white; } .notebook-list li { margin-top: 10px; font-size: 14px; display: flex; padding: 5px 0 5px 25px; } .notebook-list .active { background: #1a1a1a; } .notebook-list li i { margin-right: 3px; } .app-center{ width: 12%; min-width: 180px; background: #ececec; display: flex; flex-direction: column; } .app-center-header { padding: 10px 0px 10px 10px; font-weight: bold; border-bottom: 1px solid #ccc; } .app-center-list { padding: 0; height: 100%; overflow: scroll; } .app-center-list .active { background: yellow; } .app-center-list li { margin: 5px 10px; height: 180px; background: white; color: black; } .app-center-list-item .note-header { font-weight: bold; text-align: center; height: 30px; line-height: 30px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; padding-left: 5px; font-size: 12px; } .app-center-list-item .note-content { padding: 0px 10px; font-size: 13px; line-height: 22px; overflow: hidden; height: 130px; line-clamp: 3; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 6; } .app-right { width: 78%; display: flex; flex-direction: column; } .app-right-header { height: 30px; line-height: 30px; padding-left: 10px; border-bottom: 1px solid #ccc; } .app-right-header .notebookName { margin-left: 5px; font-weight: bolder; font-size: 13px; } .app-right-title { height: 20px; line-height: 20px; padding: 8px 0 8px 30px; font-weight: bold; outline: none; } .app-right-content { display: flex; flex: 1; overflow: scroll; } .app-right-edit { background: #22272a; width: 50%; color: white; font-size: 15px; line-height: 25px; padding: 10px 0 0 10px; outline: none; resize: none; } .app-right-show { border-top: 1px solid #ccc; width: 50%; padding-left: 20px; overflow: scroll; }
這裏爲了方便,將全部樣式都寫到了,App.css中,這樣其餘子組件均可以共享App.css中定義的樣式了。web
④ 修改index.css
爲了讓App組件可以佔滿全屏,須要對html、body、#root進行高度100%的設置,如:數據庫
html,body{ height: 100%; } #root { height: 100%; }
至此,evernote項目已經初始化完成。npm
從效果圖上能夠看到,整個印象筆記分爲左、中、右三塊,因此咱們能夠把它們分紅左、中、右三個組件。左邊用於顯示筆記本列表,中間用於顯示每一個筆記本下的筆記列表,右側用於顯示當前正在查看和編輯的筆記。因此在src目錄下新建一個components目錄,用於存放這三個組件。
// src/components/Left.js
import React from "react"; class Left extends React.Component { render() { return ( <div className="app-left"> 我是左邊 </div> ); } } export default Left;
// src/components/Center.js
import React from "react"; class Center extends React.Component { render() { return ( <div className="app-center"> 我是中間 </div> ); } } export default Center;
// src/components/Right.js
import React from "react"; class Right extends React.Component { render() { return ( <div className="app-right"> 我是右邊 </div> ); } } export default Right;
同時在App.js中引入這三個組件,如:
// src/App.js
class App extends React.Component { render() { return ( <div className="app-container"> <Left/> <Center/> <Right/> </div> ); } }
爲了簡單實現印象筆記在線操做功能,咱們這裏就不鏈接數據庫了,而是採用json-server來模擬數據庫,首先全局安裝json-server模塊,如:
sudo npm install -g json-server
而後在src目錄下新建一個data目錄,裏面放一個db.json文件,內容以下:
{ "notebooks": [ { "id": 1, "name": "默認筆記本" }, { "id": 2, "name": "個人2019" }, { "id": 3, "name": "個人2020" } ], "notes": [ { "id": 1, "title": "這是一段代碼", "content": "## 一段react的示例代碼\n## 安裝react\n```\nnpm install react --save-dev\nnpm install react-dowm --save-dev\n```\n### JS部分\n```\n// 引入react\nimport React from \"react\";\nimport ReactDOM from \"react-dom\";\n// 定義函數組件\nfunction App() {\n return (<h1>hello react !</h1>)\n}\n// 渲染組件到根節點\nReactDOM.render(<App/>, document.getElementById(\"root\"));\n```\n\n### html部分\n```\n<!DOCTYPE html>\n<html lang=\"en\">\n <head></head>\n <div id=\"root\">\n </div>\n</html>\n```", "bookId": 1 }, { "id": 2, "title": "2019可笑的笑話 最好能笑死別人", "content": "## 第一個\n> 朋友去唱歌找了小姐,買單時發現沒有現金只有銀行卡,服務員說:「能夠刷卡。」他說:「這卡是我老婆名字,刷了收到大家KTV短信,會打死個人。」服務員說:「沒事,咱們能夠幫你刷成飯店消費。」此男一聽很開心而後就刷了…結果剛一進家門老婆劈里啪啦兩個大耳光,把手機短信給他看:「沙縣小吃,消費8333元,你沒有撐死?」\n\n## 第二個\n> 有一次,一個男人準備去辦公室工做,他據說來了不少美女,就把本身打扮得漂漂亮亮,到了辦公室,美女們都對男人微笑,他認爲美女以爲本身很帥,其實,他的牙上沾了一顆紅的和一顆綠的辣椒皮!\n\n## 第三個\n> 女婿跟老丈人抱怨,我老婆開着80多W的車,穿着幾千的衣服, 用着蘋果X,我每天電動車,一年四季2件外衣,用着淘汰的老年機,你知道我多慘嗎? 只見老丈人神色淡定的說道:你每天睡着個開80多萬的車,穿着幾千塊衣服,手拿蘋果X的女人,還有什麼不滿意的!\n\n## 第四個\n> 前幾天哥幾個晚上去網吧玩,凌晨三點多回家,都離家比較近走着回去的,走到一半一哥們在路邊衝着一棵樹小解,咱們走前面,他解完就追上咱們,而後我說 你尿尿的姿式不對呀!哥們一臉懵逼,問我:怎麼不對了?我:你應該擡起一條腿!而後就被追殺7條街!\n\n## 第五個\n> 某君兒子沒考上大學,便找到在國企作董事長的老同窗。董事長很爽快:讓他來作副總經理吧,月薪五萬,天天例行開會就好了。某君:給個通常職位就好了。董事長:作總經理助理吧,月薪2萬,給總經理倒倒茶就好了。某君:仍是從普通業務員作起吧。董事長:咱們的業務員起碼要碩士學歷,薪水很低,還欠薪!\n\n## 第六個\n> 一女同事和我住同一個小區,有時我蹭她的車,有時她蹭個人車,常常一塊兒回到公司。昨天公司門衛跟我說:「我看到你媳婦在外面摟着個男的。」我知道他誤會女同事是我媳婦了,故意逗他說:「她這人就是貪玩,我也管不了。」今天女同事回來,說門衛給了她一朵玫瑰。\n\n## 第七個\n> 一新兵跑步老落後腿。班長問:爲什麼老最後?新兵答:報告班長,吃飯時間只有二分鐘,沒吃飽跑不動。次日,班長讓新兵吃了個飽。結果那新兵仍是跑了個倒數第一。班長問:咋還落後腿。新兵答:報告班長。吃太撐了。\n\n## 第八個\n> 我讀小學的時候遲到、逃學、打架什麼壞事都幹,反正就是一個〝萬人嫌〞,因此罰站罰跪就成了屢見不鮮。每次罰完跪,我都是哭着趴在姐姐背上回家的。有一次姐姐心疼的對我說:小冰呀,你之後仍是帶着爸爸的護膝上學吧!\n\n## 第九個\n> 我手機背景換了幾百次了,老公的依舊是個人大臉照。我說:不會換張美女啊什麼的,我不會不開心的?這二貨道:這樣很好,能夠控制玩手機的慾望!\n\n## 第十個\n> 一日,和哥們去一個沒去過的地方吃飯,找不到那個地方,看見路邊有個協警(背對着),看身材貌似是中年婦女。因而哥們衝過去說道:「阿姨,XXX飯店怎麼走。」那個協警黑着臉轉過身來,原來是個大叔,但他仍是指了路。哥們聽完很感激,繼續說:「謝謝阿姨……」\n本人一直單身,不知道爲何怎麼也找不到對象。最近的幾天趕上十年一遇的高溫,很讓人難受。咱們公司的一位漂亮妹紙有天終於熱得受不了了。她就問我:你住的那裏有空調嗎?我:有啊。妹紙:那我之後中午去你那休息,蹭一下空調好很差。我:固然不行,電費這麼貴。而後就沒有而後了...\n", "time": "2019-12-16", "bookId": 1 }, { "id": 3, "title": "2019年度最沙雕新聞你以爲是哪個?", "content": "## 2019年度最沙雕新聞你以爲是哪個?\n> 2019年度最沙雕新聞你以爲是哪個? 1 男子帶了一頂綠帽去盜竊,帽子上面寫的「忘了他吧,我偷電瓶車養你」,最後由於這個帽子太鮮明被警方抓獲。男子說買這個帽子是在地攤上看到,以爲很符合本身又窮又沒有愛情的心境,沒想到電瓶車沒偷,女孩也沒有跟我走就被抓了。 2 警察抓毒販時,毒販正在看以掃毒爲主題的電視劇《破冰行動》,網友稱電視劇來到現實。後因網絡反響強烈,記者追問已被拘捕的毒販對電視劇的評價,毒販說主演演得很好。 3 女子收電信詐騙電話,將卡號密碼告訴了犯罪分子,銀行察覺異常叫了警察,後來警察發現女子由於記性很差給了錯誤密碼而避免了損失。 4 男子報警稱本身的山地自行車被偷,民警處理髮現這車原本是報警的男子偷來的,被真車主碰上後在警察協助下騎走。警察問報警男子爲什麼自投羅網,偷車男子說騎了一段時間也有感情了。 5 男子和鄰居吵架,怕對方人多勢衆本身吃虧因此報警,民警作筆錄發現報警男子是逃犯。 6 男子接到電話稱本身被網上追逃,到派出所查詢想證實清白,民警一查確爲追逃對象將其拘捕。 7 四川南充民警準備抓特大電信詐騙案件嫌疑人,但強行破門有風險,後發現嫌疑人的鑰匙插在門鎖上忘拔,最後民警順利破門抓獲嫌疑人。 8 兩男子凌晨潛入串串店自行搭配鍋底偷吃串串,連吃三天後老闆才發現店裏進賊,第四天兩男子來偷吃終於被潛伏民警抓獲。 9 小偷入室盜竊,房主年紀大不會用手機報警,小偷:我幫你打110吧。最後被刑拘。 10 成都一女子要跳樓,一男子在對面看熱鬧不慎失足墜樓死亡,女子看到後以爲太嚇人了放棄跳樓。 11 男子報警稱被車壓到腳,周圍多個路人幫忙做證要求車主賠錢。男子善解人意說沒啥大事賠5000就行,後來調監控發現是他本身把腳伸車輪下,並且路人都是同夥。", "time": "2019-12-16", "bookId": 1 }, { "id": 4, "title": "2019年個人美好回憶", "content": "## 2019年個人美好回憶\n> 時光匆匆,歲月悠悠,春去冬來,不知不覺,2019年即將過去了,2020年就要到來了。\n回憶即將過去的一年,我有甜、有酸、有苦、也有樂,但全部的甜與酸苦與樂,都在歲月的流逝中化做了醇厚的濃香,使人耐人尋味。\n2019,是豐盈而充實的一年,收穫了一縷陽光,一股溫暖,一片友情。使個人晚年生活更加充實,更加幸福,更加美好。\n\n> 這一年,我懷着一顆熱愛漂亮篇的心,虛心學習,努力寫做。編寫了四十多篇文章和六十多條話題投稿美篇後,有八篇文章被美篇錄取加精,有四篇文章被加薦。其中有一篇《我是怎樣製做美篇文章的?》文章,被《美篇手冊》錄取,收錄在「美友經驗分享區」欄目裏,引發了很大的反響,美友閱讀量突破46000人,點贊留評人數達到1400多人。\n這一小小的收穫,除了本身努力以外,離不開衆人的幫助。在這裏要感謝美篇平臺的支持和關心,感謝《原創筆記》等圈子的幫助和鼓勵,特別要感謝美友們的到訪與點評。", "time": "2019-12-26", "bookId": 2 }, { "id": 5, "title": "怎樣才能娶到一個好老婆啊", "content": "## 怎樣才能娶到一個好老婆啊\n> 只要大家感情好。在一塊兒時間長了不會以爲很煩。你愛他。他也愛你。那樣生活起來纔不會以爲累。那樣纔會永遠相愛一生。這才叫娶個好老婆。\n\n> 若是你娶個很賢惠並且什麼都好的老婆。你不喜歡她。那日子也不會長久。不會長久的生活還在意娶什麼老婆嗎?衷心的祝福你能找到個誠心如意的老婆。男人年輕時,選老婆或選女朋友,\n第一都是看身材和臉蛋,人品性格和脾氣統統無論;到了中年時,纔會發現:原來,女人的美,不在外表,而在具備包容心和好脾氣的個性,尤爲是會撒嬌的女人,一旦撒嬌撒到男人的死穴,也就是打中了男人心坎裏的弱點,這時,就算她要男人去死,男人也會帶着微笑和知足的表情從容就義。\n男人要的只是一種相似母愛的包容和關懷,一種無怨無悔、夫唱婦隨的契合感受,我並不是把女人當跟班或第二性,也不是歧視女性,真的,男人要的就只是那種即便本身再落魄再倒黴,她也不棄不離的那種生死相隨的感動", "time": "2019-12-31", "bookId": 3 } ] }
此時再經過json-server去啓動並監聽db.json文件,就能夠以REST API的形式訪問db.json中的數據了,如:
json-server --watch ./src/data/db.json --port 8080
好比,咱們在瀏覽器中經過http://localhost:8080/notebooks
便可訪問到db.json文件中notebooks對應的數組數據了。
這裏解釋一下db.json中的數據結構,notebooks表示的是有哪些筆記本,notes表示的是有哪些比較,其中有一個bookId字段表示其是屬於哪一個筆記本下。
咱們這裏把全部的狀態數據都放在App根組件上,而後經過props傳遞到子組件上,Left組件要顯示全部的筆記本列表,全部須要notebooks這個數組以及當前選擇的是哪一個筆記本,全部須要知道當前筆記本索引currentIndex,在App組件上新增notebooks和currentIndex兩個狀態數據,咱們能夠在App組件掛載完成的時候去獲取全部的筆記本列表,請求數據使用axios,如:
npm install axios --save-dev
// src/App.js 新增notebooks和currentIndex兩個狀態屬性
class App extends React.Component { constructor(props) { super(props); this.state = { notebooks: [], // 存放筆記本列表 currentIndex: 0, // 默認顯示第一個筆記本 } } componentDidMount() { axios.get("http://localhost:8080/notebooks").then((res) => { this.setState({ notebooks: res.data // 更新筆記本列表 }); }); } render() { return ( <div className="app-container"> <Left notebooks={this.state.notebooks} currentIndex={this.state.currentIndex}/> <Center/> <Right/> </div> ); } }
此時App組件向Left組件中傳遞了notebooks筆記本列表數組和currentIndex當前筆記本索引兩個數據,而後開始開發Left組件,
// src/components/Left.js
import React from "react"; class Left extends React.Component { render() { return ( <div className="app-left"> <div className="app-left-header"> <i className="add iconfont icon-jiahao"></i> <span className="add-notebook">新建筆記</span> </div> <div className="app-left-body"> <div className="app-left-body-title"> <i className="notebook-icon iconfont icon-bijiben"></i> <span>筆記本</span> </div> <ul className="notebook-list"> { this.props.notebooks.map((notebook, index) => { return ( <li key={notebook.id} className={this.props.currentIndex === index ? "active" : ""} > <i className="iconfont icon-bijiben1"></i>{notebook.name} </li> ) }) } </ul> </div> </div> ); } } export default Left;
Center組件用於顯示筆記列表,因此須要把當前選擇的比較本下的全部筆記列表傳遞給Center組件,在App組件中新建一個notes狀態屬性,一樣是在componentDidMount的時候根據currentIndex獲取到當前筆記本下的全部筆記,如:
// src/App.js
// 在state中新增一個notes屬性 this.state = { notes: [], // 筆記列表 } // 新增一個getNotes方法用於根據筆記本的id獲取其下的全部筆記列表 getNotes(bookId) { // 根據bookId獲取筆記列表 axios.get(`http://localhost:8080/notes?bookId=${bookId}`).then((res) => { this.setState({ notes: res.data // 將獲取到的比較列表存放到notes狀態中 }); }); } // 修改componentDidMount,在獲取到筆記本列表後,根據currentIndex獲取到對應的筆記本信息,而後根據其id獲取筆記列表 componentDidMount() { axios.get("http://localhost:8080/notebooks").then((res) => { this.setState({ notebooks: res.data }); // 更新筆記本列表 const notebook = this.state.notebooks[this.state.currentIndex];// 取出當前索引對應的筆記本 this.getNotes(notebook.id); // 根據當前筆記本的id去獲取筆記列表 }); } // 將notes筆記列表傳遞給Center組件 <Center notes={this.state.notes} />
// src/component/Center.js
import React from "react"; class Center extends React.Component { render() { return ( <div className="app-center"> <div className="app-center-header">筆記列表</div> <ul className="app-center-list"> { this.props.notes.map((note, index) => { return ( <li key={note.id}> <div className="app-center-list-item"> <div className="note-header">{note.title}</div> <div className="note-content"><pre>{note.content}</pre></div> </div> </li> ) }) } </ul> </div> ); } } export default Center;
Right組件主要用於顯示選擇的筆記內容,因此須要將當前選擇的筆記傳遞給Right組件,App中新增一個currentNote狀態屬性,用於保存當前選擇的筆記,因爲Right組件中還須要顯示所在的筆記本名稱,而這些信息都在notebooks中,因此也須要傳遞notebooks和currentIndex,如:
// src/App.js
// 新增currentNote狀態屬性 this.state = { currentNote: null // 當前顯示的筆記 } // 若是選擇了某個筆記,纔會在右邊區域顯示具體的筆記內容 { this.state.currentNote ? <Right notebooks={this.state.notebooks} currentIndex={this.state.currentIndex} currentNote={this.state.currentNote} /> : null }
// src/component/Right.js
import React from "react"; class Right extends React.Component { render() { return( <div className="app-right"> <div className="app-right-header"> <i className="iconfont icon-bijiben1"></i> <span className="notebookName">{this.props.notebooks[this.props.currentIndex].name}</span> </div> <input className="app-right-title" name="title" value={this.props.currentNote.title}/> <div className="app-right-content"> <textarea className="app-right-edit" name="content" value={this.props.currentNote.content}/> <div className="app-right-show"> {this.props.currentNote.content} </div> </div> </div> ); } } export default Right;
此時右邊還不會顯示具體的筆記內容,由於currentNote爲null,因此須要進行currentNote的初始化,當筆記列表項被點擊的時候,根據其點擊的索引,而後找到對應的筆記信息賦值給currentNote便可,
// src/App.js
// 新增一個處理筆記列表項被點擊事件 doNoteClick(index) { const notebook = this.state.notes[index]; // 根據索引拿到被點擊的那個筆記 const noteId = notebook.id; // 拿到筆記的id axios.get(`http://localhost:8080/notes/${noteId}`).then((res) => { // 根據id獲取對應的筆記並保存到currentNote中 this.setState({ currentNote: res.data }); }); } // 根Center組件傳遞一個事件處理函數 <Center notes={this.state.notes} doNoteClick={(index) => {this.doNoteClick(index)}} />
// src/component/Center.js
// 新增筆記被點擊事件,執行父組件傳遞過來的事件 doNoteClick(index) { this.props.doNoteClick(index); } // 當某個筆記項被點擊後,將index傳遞給App組件 <li key={note.id} onClick={() => {this.doNoteClick(index)}} >
此時能夠顯示筆記內容了。可是Left組件中點擊筆記本列表項沒法切換,因此須要給Left組件的每一個選項添加click事件,如:
// src/App.js
// 給Left組件傳遞一個doNotebookClick事件,接收點擊的index <Left notebooks={this.state.notebooks} currentIndex={this.state.currentIndex} doNotebookClick={(index) => {this.doNotebookClick(index)}} /> // 新增一個doNotebookClick事件 doNotebookClick(index) { this.setState({ currentIndex: index // 更新currentIndex }); const notebook = this.state.notebooks[index];// 根據index拿到對應的筆記本 this.getNotes(notebook.id);// 而後根據筆記本的id找到旗下的全部筆記列表 this.setState({ currentNote: null // 清空currentNote }); }
// src/components/Left.js
// 主要將index傳遞給App組件 doNotebookClick(index) { this.props.doNotebookClick(index); } <li key={notebook.id} onClick={() => this.doNotebookClick(index)} >
還有一個就是新建筆記功能,添加doAdd事件,如:
// src/App.js
// 給子組件傳遞doAdd事件 <Left notebooks={this.state.notebooks} doAdd={() => {this.doAdd()}} /> // 添加doAdd事件 doAdd() { const id = parseInt(Math.random() * 100); // 隨機生成一個id const bookId = this.state.notebooks[this.state.currentIndex].id; // 獲取當前筆記本的id const note = { // 建立一個筆記 id, title: `新建筆記${id}`, content: "筆記內容", bookId } axios.post("http://localhost:8080/notes", note).then(() => { // 經過post添加一個筆記 this.getNotes(bookId);// 筆記新建成功後從新獲取筆記列表 this.setState({ // 而且顯示新建的筆記本內容 currentNote: note }); }); }
// src/components/Left.js
doAdd() { this.props.doAdd(); } <i className="add iconfont icon-jiahao" onClick={() => {this.doAdd()}}></i>
如今Right組件雖然能夠正常了,可是Right組件的右側顯示區顯示的是markdown的源文本,咱們須要對markdown源文本進行轉換後再顯示出來,咱們能夠經過marked這個模塊進行markdown文本的轉換,如:
// 安裝marked模塊 npm install marked --save-dev // 安裝github-markdown-css,給轉換後的marked html添加樣式 npm install github-markdown-css --save-dev
// src/components/Right.js
import marked from "marked"; import "github-markdown-css"; // 將轉換後的html插入到顯示區 <div className="app-right-show markdown-body" dangerouslySetInnerHTML={{__html: marked(this.props.currentNote.content)}} />
要想實如今線編輯功能,那麼咱們須要給編輯器添加上onChange事件,而後重置notes的內容,而且將其提交給服務器,如:
// src/App.js
// 給子組件傳遞onChange事件 <Right doContentChange={(e) => {this.doContentChange(e)}} /> doContentChange(e) { const currentNote = this.state.currentNote; // 取出當前編輯的筆記 currentNote[e.target.name] = e.target.value; // 更新筆記內容 this.setState({ // 重置筆記內容以便顯示區可以更新 currentNote }); const notes = this.state.notes; // 獲取的整個筆記列表 notes.forEach((note, index) => { if (note.id === currentNote.id) { // 找到當前更新的筆記 notes[index] = currentNote;// 更新notes以便列表處也能實時更新 this.setState({ notes }); } }); axios.put(`http://localhost:8080/notes/${currentNote.id}`, currentNote); // 將更新提交到服務器 }
// src/components/Right.js
doContentChange(e) { this.props.doContentChange(e); } <input className="app-right-title" name="title" value={this.props.currentNote.title} onChange={(e) => {this.doContentChange(e)}}/> <textarea className="app-right-edit" name="content" value={this.props.currentNote.content} onChange={(e) => {this.doContentChange(e)}} />