使用react實現一個簡版的印象筆記App

1、效果圖展現

屏幕快照 2020-01-12 下午7.56.14.png

2、初始化項目

① 安裝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字體庫中找到,如圖所示:
屏幕快照 2020-01-13 上午10.39.58.pngios

③ 修改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

3、項目分析

從效果圖上能夠看到,整個印象筆記分爲左、中、右三塊,因此咱們能夠把它們分紅左、中、右三個組件。左邊用於顯示筆記本列表中間用於顯示每一個筆記本下的筆記列表右側用於顯示當前正在查看和編輯的筆記。因此在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>
    );
  }
}

4、模擬數據

爲了簡單實現印象筆記在線操做功能,咱們這裏就不鏈接數據庫了,而是採用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字段表示其是屬於哪一個筆記本下。

5、開發Left組件

咱們這裏把全部的狀態數據都放在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;

6、開發Center組件

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;

7、開發Right組件

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;

8、添加事件

此時右邊還不會顯示具體的筆記內容,由於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>

9、實現markdown編輯器的顯示功能

如今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)}} />

10、實現markdown的在線編輯功能

要想實如今線編輯功能,那麼咱們須要給編輯器添加上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)}} />
相關文章
相關標籤/搜索