1. 在項目中使用 react
-
運行
cnpm i react react-dom -S
安裝包- react: 專門用於創建組件和虛擬DOM的,同時組件的生命週期都在這個包中
- react-dom: 專門進行DOM操作的,最主要的應用場景,就是
ReactDOM.render()
-
在
index.html
頁面中,創建容器:<!-- 容器,將來,使用 React 創建的虛擬DOM元素,都會被渲染到這個指定的容器中 --> <div id="app"></div>
-
js文件中導入包:
import React from 'react' import ReactDOM from 'react-dom'
-
創建虛擬DOM元素:
// 這是 創建虛擬DOM元素的 API <h1 title="啊,五環" id="myh1">你比四環多一環</h1> // 第一個參數: 字符串類型的參數,表示要創建的標籤的名稱 // 第二個參數:對象類型的參數, 表示創建的元素的屬性節點,可以用null // 第三個參數: 子節點 const myh1 = React.createElement('h1', { title: '啊,五環', id: 'myh1' }, '你比四環多一環')
-
渲染:
// 3. 渲染虛擬DOM元素 // 參數1: 表示要渲染的虛擬DOM對象 // 參數2: 指定容器,注意:這裏不能直接放 容器元素的Id字符串,需要放一個容器的DOM對象 ReactDOM.render(myh1, document.getElementById('app'))
2. JSX語法
什麼是JSX語法:就是符合 xml 規範的 JS 語法;(語法格式相對來說,要比HTML嚴謹很多)
-
如何啓用 jsx 語法?
-
安裝
babel
插件- 運行
cnpm i babel-core babel-loader babel-plugin-transform-runtime -D
- 運行
cnpm i babel-preset-env babel-preset-stage-0 -D
- 運行
-
安裝能夠識別轉換jsx語法的包
babel-preset-react
- 運行
cnpm i babel-preset-react -D
- 運行
-
添加
.babelrc
配置文件{ "presets": ["env", "stage-0", "react"], "plugins": ["transform-runtime"] }
-
添加babel-loader配置項:
module: { //要打包的第三方模塊 rules: [ { test: /\.js|jsx$/, use: 'babel-loader', exclude: /node_modules/ } ] }
-
-
jsx 語法的本質: 並不是直接把 jsx 渲染到頁面上,而是內部先轉換成了 createElement 形式,再渲染的;
-
在 jsx 中混合寫入 js 表達式:在 jsx 語法中,要把 JS代碼寫到
{ }
中- 渲染數字
let a = 10; ReactDOM.render(<div>{a}</div>, document.getElementById('app'))
- 渲染字符串
let a = 'aaa'; ReactDOM.render(<div>{a}</div>, document.getElementById('app'))
- 渲染布爾值
let a = false; ReactDOM.render(<div>{a ? '條件爲真' : '條件爲假'}</div>,document.getElementById('app'))
- 爲屬性綁定值
let title = "sss"; ReactDOM.render(<div title={title}></div>, document.getElementById('app'))
- 渲染jsx元素
let aaa = <h1>111</h1>;\ ReactDOM.render(<div>{aaa}</div>, document.getElementById('app'))
- 渲染jsx元素數組
let arr = [ <h1>111</h1>, <h2>222</h2> ]; ReactDOM.render(<div>{arr}</div>, document.getElementById('app'))
- 將普通字符串數組,轉爲jsx數組並渲染到頁面上【兩種方案】
第一種
第二種const arrStr = ['aaa','bbb','ccc'] const nameArr = [] arrStr.forEach(item => { const temp = <h1>{item}</h1> nameArr.push(temp) }) ReactDOM.render(<div>{nameArr}</div>, document.getElementById('app'))
const arrStr = ['aaa','bbb','ccc'] ReactDOM.render(<div> {arrStr.map(item => <h1>{item}</h1>)} </div>, document.getElementById('app'))
- 渲染數字
-
在 jsx 中 寫註釋:推薦使用
{ /* 這是註釋 */ }
-
爲 jsx 中的元素添加class類名:需要使用
className
來替代class
;htmlFor
替換label的for
屬性 -
在JSX創建DOM的時候,所有的節點,必須有唯一的根元素進行包裹;
-
在 jsx 語法中,標籤必須 成對出現,如果是單標籤,則必須自閉和!
當 編譯引擎,在編譯JSX代碼的時候,如果遇到了
<
那麼就把它當作 HTML代碼去編譯,如果遇到了{}
就把 花括號內部的代碼當作 普通JS代碼去編譯;
3. React中創建組件
第1種 - 創建組件的方式
使用構造函數來創建組件,如果要接收外界傳遞的數據,需要在 構造函數的參數列表中使用
props
來接收;必須要向外return一個合法的JSX創建的虛擬DOM;
-
創建組件:
function Hello () { // return null return <div>Hello 組件</div> }
-
爲組件傳遞數據:
const dog = { name : "大黃", age : 3 } // 在構造函數中,使用 props 形參,接收外界 傳遞過來的數據 function Hello(props) { // props.name = 'zs' console.log(props) // 結論:不論是 Vue 還是 React,組件中的 props 永遠都是隻讀的;不能被重新賦值; return <div>這是 Hello 組件 --- {props.name} --- {props.age}</div> } // 使用組件並 爲組件傳遞 props 數據 ReactDOM.render(<div> <Hello name={dog.name} age={dog.age}></Hello> //es6寫法 //<Hello {...dog}></Hello> </div>, document.getElementById('app'))
-
父組件向子組件傳遞數據
-
使用{…obj}屬性擴散傳遞數據
-
將組件封裝到單獨的文件中
-
注意:組件的名稱首字母必須是大寫
-
在導入組件的時候,如何省略組件的
.jsx
後綴名:// 打開 webpack.config.js ,並在導出的配置對象中,新增 如下節點: resolve: { extensions: ['.js', '.jsx', '.json'], // 表示,這幾個文件的後綴名,可以省略不寫 alias: { '@': path.join(__dirname, './src')// 這樣@就表示項目根目錄中src這一層目錄 } }
-
在導入組件的時候,配置和使用
@
路徑符號
第2種 - 創建組件的方式
使用 class 關鍵字來創建組件
ES6 中 class 關鍵字,是實現面向對象編程的新形式;
瞭解ES6中 class 關鍵字的使用
-
class 中
constructor
的基本使用 -
實例屬性和實例方法
-
靜態屬性和靜態方法
// 創建了一個動物類 // 注意:在 class 的 { } 區間內,只能寫 構造器、靜態方法和靜態屬性、實例方法 class Animal { // 這是類中的 構造器 // 每一個類中,都有一個構造器,如果我們程序員沒有手動指定構造器,那麼,可以認爲類內部有個隱形的、看不見的 空構造器,類似於 constructor(){} // 構造器的作用,就是,每當 new 這個類的時候,必然會優先執行 構造器中的代碼 constructor(name, age) { // 實例屬性 this.name = name; this.age = age } // 在 class 內部,通過 static 修飾的屬性,就是靜態屬性 static info = "eee" // (用的不多) // 這是動物的實例方法(會經常用到 實例方法) jiao() { console.log('動物的實例方法') } // 這是 動物 類的靜態方法(用的不多) static show() { console.log('這是 Animal 的靜態 show 方法') } } const a1 = new Animal('大黃', 3); console.log(a1); a1.jiao(); Animal.show();
-
使用
extends
關鍵字實現繼承// 這是父類 【可以直接把 父類,理解成 原型對象 prototype】 class Person { constructor(name, age){ this.name = name this.age = age } //打招呼 的 實例方法 sayHello(){ console.log('大家好') } } // 這是子類 美國人 // 在 class 類中,可以使用 extends 關鍵字,實現 子類繼承父類 // 語法:class 子類 extends 父類 {} class American extends Person { constructor(name, age){ // 問題1:爲什麼一定要在 constructor 中調用 super // 答案: 因爲,如果一個子類,通過 extends 關鍵字繼承了父類,那麼,在子類的 constructor 構造函數中,必須 優先調用一下 super(),規定 // 問題2:super 是個什麼東西? // 答案: super 是一個函數,而且,它是 父類的 構造器;子類中的 super,其實就是父類中,constructor 構造器的一個引用; super(name, age) } } const a1 = new American('Jack', 20) console.log(a1) a1.sayHello() // 這是子類 中國人 class Chinese extends Person{ // IDNumber 身份證號 【中國人獨有的】,既然是獨有的,就不適合 掛載到 父類上; constructor(name, age, IDNumber){ super(name, age) // 語法規範:在子類中, this 只能放到 super 之後使用 this.IDNumber = IDNumber } } const c1 = new Chinese('張三', 22, '130428******') console.log(c1) c1.sayHello()
基於class關鍵字創建組件
-
最基本的組件結構:
// 如果要使用 class 定義組件,必須 讓自己的組件,繼承自 React.Component class 組件名稱 extends React.Component { // 在 組件內部,必須有 render 函數,作用:渲染當前組件對應的 虛擬DOM結構 render(){ // render 函數中,必須 返回合法的 JSX 虛擬DOM結構 return <div>這是 class 創建的組件</div> } }
-
組件的props和state
// import React, {Component} from 'react' import React from 'react' import ReactDOM from 'react-dom' // class 關鍵字創建組件 class Movie extends React.Component { constructor() { // 由於 Movie 組件,繼承了 React.Component 這個父類,所以,自定義的構造器中,必須 調用 super() super() // 只有調用了 super() 以後,才能使用 this 關鍵字 this.state = { msg: '大家好,我是 class 創建的 Movie組件' } } // render 函數的作用,是 渲染 當前組件所對應的 虛擬DOM元素 render() { // 在 class 關鍵字創建的組件中,如果想使用 外界傳遞過來的 props 參數,不需接收,直接通過 this.props.*** 訪問即可 // 注意:不論是 class 還是普通 function 創建的組件,它們的 props 都是隻讀的; // 在 class 創建的組件中, this.state 上的數據,都是可讀可寫的! // this.state.msg = 'msg的值被我修改了!' return <div> {/* 注意:在 class 組件內部,this 表示 當前組件的實例對象 */} 這是 Movie 組件 -- {this.props.name} -- {this.props.age} -- {this.props.gender} <h3>{this.state.msg}</h3> </div> } } const user = { name: 'zs', age: 22, gender: '男' } // 3. 調用 render 函數渲染 ReactDOM.render(<div> {/* 這裏的 Movie 標籤,其實,就是 Movie 類的一個實例對象 */} {/* <Movie name={user.name} age={user.age}></Movie> */} <Movie {...user}></Movie> </div>, document.getElementById('app'))
4. 兩種創建組件方式的對比
注意:使用 class 關鍵字創建的組件,有自己的私有數據(this.state) 和 生命週期函數;
注意:使用 function 創建的組件,只有props,沒有自己的私有數據和 生命週期函數;
- 用構造函數創建出來的組件:叫做“無狀態組件”【無狀態組件今後用的不多】
- 用class關鍵字創建出來的組件:叫做“有狀態組件”【今後用的最多】
- 什麼情況下使用有狀態組件?什麼情況下使用無狀態組件?
- 如果一個組件需要有自己的私有數據,則推薦使用:class創建的有狀態組件;
- 如果一個組件不需要有私有的數據,則推薦使用:無狀態組件;
- React官方說:無狀態組件,由於沒有自己的state和生命週期函數,所以運行效率會比 有狀態組件稍微高一些;
有狀態組件和無狀態組件之間的本質區別就是:有無state屬性、和 有無生命週期函數;
- 組件中的
props
和state/data
之間的區別- props 中的數據都是外界傳遞過來的;
- state/data 中的數據,都是組件私有的;(通過 Ajax 獲取回來的數據,一般都是私有數據);
- props 中的數據都是隻讀的;不能重新賦值;
- state/data 中的數據,都是可讀可寫的;