1 npm install -g create-react-app
1 // 在命令行輸入以下命令 2 create-react-app todo-list 3 //注意npm命名限制,項目名稱不能含有大寫字母。
1 /** 2 - src目錄中的:App.css, App.test.js, logo.svg, serviceWorker.js文件 3 - public目錄中的: manifest.json文件 4 - 其中manifest.json,serviceWorker.js屬於pwa的配置文件,有興趣能夠了解一下。 5 - pwa 讓網頁寫好之後,用戶訪問了一次以後,就能夠把咱們的網頁看成app來用,能夠不用聯網。 6 - 在手機上或者電腦桌面上經過點擊快捷方式來打開頁面。 7 - 他的圖標和快捷方式是經過public中manifest.json去定義的 8 */
1 /** 2 - App.js刪除下列代碼註釋部分 3 */ 4 5 import React, { Component }from 'react'; 6 // import logo from './logo.svg'; 7 // import './App.css'; 8 9 class App extends Component { 10 render(){ 11 return ( 12 { 13 /* 14 <div className="App"> 15 <header className="App-header"> 16 <img src={logo} className="App-logo" alt="logo" /> 17 <p> 18 Edit <code>src/App.js</code> and save to reload. 19 </p> 20 <a 21 className="App-link" 22 href="https://reactjs.org" 23 target="_blank" 24 rel="noopener noreferrer" 25 > 26 Learn React 27 </a> 28 </header> 29 </div> 30 */ 31 } 32 <div> 33 hello react 34 </div> 35 36 ); 37 } 38 } 39 export default App;
1 /** 2 index.js 刪除一下注釋部分 3 */ 4 import React from 'react'; 5 import ReactDOM from 'react-dom'; 6 // import './index.css'; 7 import App from './App'; 8 //import * as serviceWorker from './serviceWorker'; // pwa 引入 9 10 ReactDOM.render(<App />, document.getElementById('root')); 11 12 // If you want your app to work offline and load faster, you can change 13 // unregister() to register() below. Note this comes with some pitfalls. 14 // Learn more about service workers: https://bit.ly/CRA-PWA 15 // serviceWorker.unregister(); // pwa 使用
<!-- public中的index.html文件,刪除如下注釋部分代碼 --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="theme-color" content="#000000" /> <meta name="description" content="Web site created using create-react-app" /> <link rel="apple-touch-icon" href="logo192.png" /> <!-- manifest.json provides metadata used when your web app is installed on a user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/ --> <!-- <link rel="manifest" href="%PUBLIC_URL%/manifest.json" /> --> <!-- Notice the use of %PUBLIC_URL% in the tags above. It will be replaced with the URL of the `public` folder during the build. Only files inside the `public` folder can be referenced from the HTML. Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will work correctly both with client-side routing and a non-root public URL. Learn how to configure a non-root public URL by running `npm run build`. --> <title>todo-list</title> <!-- 更改網頁標題 --> </head> <body> <noscript>You need to enable JavaScript to run this app.</noscript> <div id="root"></div> <!-- This HTML file is a template. If you open it directly in the browser, you will see an empty page. You can add webfonts, meta tags, or analytics to this file. The build step will place the bundled scripts into the <body> tag. To begin the development, run `npm start` or `yarn start`. To create a production bundle, use `npm run build` or `yarn build`. --> </body> </html>
/** - yarn.lock -- 包鎖文件 - README.MD -- 項目介紹 - package.json -- node的包文件 - .gitignore -- 使用git的時候能夠將不想上傳到git的文件在此處標記 - node_modules -- 項目依賴包 - index.html 項目首頁模版 - favicon.ico 網頁圖標 - index.js 入口js文件 - app.js 萬年老二組件 */
/** - jsx語法規定,在return中的最外層只能含有一個標籤。 - 爲此你可使用div也可使用react提供的Fragment佔位符,他其實也是一個組件。 - 在js中寫html標籤。就稱爲jsx語法 - render()函數中return => html標籤或者組件名加括號,組件必須以大寫字母開頭 - jsx中使用變量,須要使用{}包裹 - 如今咱們將App.js改形成以下代碼。 - 經過npm run start 啓動你的項目 */ import React, { Component, Fragment } from 'react'; class App extends Component { render(){ return ( <Fragment> <div > <input/><button>提交</button> </div> <ul> <li>react</li> </ul> </Fragment> ); } } export default App;
/** - 以前咱們已經將todo-list的結構搭好了。如今須要實現功能。 - 不要直接操做dom - 經過改變數據改變dom - 此時咱們須要準備兩組數據,1組數據存儲input裏面的值,1組數據存儲列表中的值。 - 如何定義數據? - 一個類一定有一個構造函數,而且他是最早執行的函數,咱們能夠將數據存在這個構造函數中 - constructor 即爲App類的構造函數,構造函數中有state屬性,他是用來存放這個類的變量的。 - 所以數據就定義在state中。 - constructor 構造函數還有一個super()方法,他能夠幫助App類調用他的父類(Component)的屬性。 - 使用箭頭函數否則this指向出錯 - 只能經過setState方法去改變state中的變量 - 代碼以下 */ import React, { Component, Fragment }from 'react'; class App extends Component { constructor(props){ super(props); this.state = { inputValue: '',// 用來存儲 input框中的 value值。 list:[] // 用來存儲 每個li的 value值。 } } render(){ return ( <Fragment> <div> <input/> <button>提交</button> </div> <ul> <li>react</li> </ul> </Fragment> ); } } export default App;
1 /** 2 - 咱們上面已經定義好了數據,如今將數據綁定到對應的dom上 3 - 這樣方便咱們經過數據改變dom 4 - react jsx語法中,綁定數據到dom上,使用{} 包裹。 -- value = {this.state.inputValue} 5 - 列表數據綁定也是同樣,在{}中寫js表達式,咱們能夠經過es5的map函數遍歷list數組得到item值,和他的下標 6 - 而後經過return返回一個li標籤,返回以前,將item綁定到li的value值,將index做爲li的key 7 - 注意的是,實際開發中將index做爲key值是一個錯誤的作法。 8 */ 9 import React, { Component, Fragment }from 'react'; 10 11 class App extends Component { 12 constructor(props){ 13 super(props); 14 this.state = { 15 inputValue: '',// 用來存儲 input框中的 value值。 16 list:['西瓜','蘋果'] // 用來存儲 每個li的 value值。 17 } 18 } 19 render(){ 20 return ( 21 <Fragment> 22 <div> 23 <input value = {this.state.inputValue} /> 24 <button>提交</button> 25 </div> 26 <ul> 27 { 28 this.state.list.map((item, index) => { 29 return ( 30 <li key={index}> 31 {item} 32 </li> 33 ) 34 }) 35 } 36 </ul> 37 </Fragment> 38 ); 39 } 40 } 41 export default App;
1 /** 2 - 咱們如今須要綁定input的onChange事件,以此達到input的value值的變化和咱們數據inputValue變化一致 3 - react的事件綁定和原生的區別就是第二個單詞首字母要大寫,onChang 4 - 在onChange事件中綁定handleInputChange()方法,傳入事件對象,獲取target值,他的value就是當前input的value值 5 - 再經過this.setState()方法區改變組件中inputValue的值。 6 - 要注意的是,react中只能經過setState方法改變state中的屬性。 7 */ 8 import React, { Component, Fragment }from 'react'; 9 10 class App extends Component { 11 constructor(props){ 12 super(props); 13 this.state = { 14 inputValue: '',// 用來存儲 input框中的 value值。 15 list:['西瓜','蘋果'] // 用來存儲 每個li的 value值。 16 } 17 } 18 handleInputChange = (e) => { 19 this.setState({ 20 inputValue: e.target.value 21 }) 22 console.log(e.target) 23 } 24 render(){ 25 return ( 26 <Fragment> 27 <div> 28 <input 29 onChange = {this.handleInputChange} 30 value = {this.state.inputValue} /> 31 <button>提交</button> 32 </div> 33 <ul> 34 { 35 this.state.list.map((item, index) => { 36 return ( 37 <li key={index}> 38 {item} 39 </li> 40 ) 41 }) 42 } 43 </ul> 44 </Fragment> 45 ); 46 } 47 } 48 export default App;
1 /** 2 - 增長思路 在input框中輸入要添加的字段,點擊提交,提交綁定一個方法,將inputValue的值添加到list數組中 3 - 刪除思路 在每個li中綁定點擊事件,在點擊的時候,傳入當前li的下標,在事件方法中經過下標刪除list中的對應元素 4 - 要注意的時,在傳入index的時候我嘗試過直接在方法名後面傳入,可是會報錯,改在bind()方法中第二個參數傳入,就沒有問題了 5 - state中的屬性數據,只能經過this.setState({})方法修改,不能直接修改。 6 - 在使用splice的時候踩了一個坑,list = list.splice(index, 1) 7 - 這是一行錯誤代碼,這樣賦值,list等因而你刪除的哪一個元素組成的數組,splice會改變原數組,返回被刪除的數組。無需再賦值 8 */ 9 import React, { Component, Fragment } from 'react'; 10 class App extends Component { 11 12 // 定義數據,一個類一定有一個構造函數,他是最早執行的函數 13 constructor(props){ 14 super(props); // App繼承Component類,因此要經過super(props)調用他的父類的屬性 15 this.state = { 16 inputValue: '', // input框的value 17 list: [] // 列表的數據 18 } 19 } 20 handleInputChange = (e) => { // 使用箭頭函數否則this指向出錯 21 this.setState({ // 只能經過setState去改變state中的變量 22 inputValue : e.target.value 23 }) 24 console.log(e.target) 25 } 26 // 增長方法 27 handleBtnClick = () => { 28 this.setState({ 29 list : [...this.state.list, this.state.inputValue], 30 inputValue: '' 31 }) 32 } 33 // 刪除方法 34 handleItemDelet = (index) => { 35 console.log(index) 36 let list = [...this.state.list]; 37 // list = list.splice(index, 1) // 這是一行錯誤代碼,這樣賦值,list等因而你刪除的哪一個元素組成的數組 38 list.splice(index, 1) 39 console.log(list) 40 this.setState({ 41 list : [...list] 42 }) 43 } 44 render(){ 45 return ( 46 <Fragment> 47 <div > 48 <input 49 value = { this.state.inputValue } // 數據相應綁定 50 onChange = { this.handleInputChange } // 事件綁定 51 /> 52 <button 53 onClick = { this.handleBtnClick } 54 >提交</button> 55 </div> 56 <ul> 57 { 58 this.state.list.map((item, index) => { 59 return <li key={index} onClick = { this.handleItemDelet.bind(this, index) }>{item}</li> // 實際編程之中使用index作key值是一個很是很差的習慣 60 }) 61 } 62 </ul> 63 </Fragment> 64 ); 65 } 66 } 67 68 export default App;
1 /** 2 - 註釋用大括號包裹,單行註釋要換行 3 - 添加樣式使用 className ,class會被解析成類 4 - dangerouslySetInnerHTML = {js表達式} 5 - dangerouslySetInnerHTML = {{ __html: item }} 多一個花括號表示一個js對象 6 - // 若是須要顯示input框中內容中的標籤效果 就這麼寫。可是這樣寫容易形成xss攻擊 對應的標籤中就不須要寫item了 7 - lable標籤 使用htmlFor引入到指定標籤中 8 */ 9 render(){ 10 return ( 11 <Fragment>{/* 他實際上是一個組件 */ } 12 <div > 13 <lable htmlFor = "insertArea">輸入內容</lable> 14 <input 15 id = 'insertArea' 16 className = 'input' 17 value = { this.state.inputValue } // 數據相應綁定 18 onChange = { this.handleInputChange } // 事件綁定 19 /> 20 <button 21 onClick = { this.handleBtnClick } 22 >提交</button> 23 </div> 24 <ul> 25 { 26 this.state.list.map((item, index) => { 27 return ( 28 <li 29 key={index} 30 onClick = { this.handleItemDelet.bind(this, index) } 31 dangerouslySetInnerHTML = {{ __html: item }} // 若是須要顯示input框中內容中的標籤效果 就這麼寫。可是這樣寫容易形成xss攻擊 32 > 33 34 </li>) // 實際編程之中使用index作key值是一個很是很差的習慣 35 }) 36 } 37 </ul> 38 </Fragment> 39 ); 40 }
1 /** 2 系統的學習能讓本身在工做中避免不少低級錯誤。 4 */