react入門筆記2

1. 在項目中使用 react

  1. 運行 cnpm i react react-dom -S 安裝包

    • react: 專門用於創建組件和虛擬DOM的,同時組件的生命週期都在這個包中
    • react-dom: 專門進行DOM操作的,最主要的應用場景,就是ReactDOM.render()
  2. index.html頁面中,創建容器:

    <!-- 容器,將來,使用 React 創建的虛擬DOM元素,都會被渲染到這個指定的容器中 -->
    <div id="app"></div>
    
  3. js文件中導入包:

    import React from 'react'
    import ReactDOM from 'react-dom'
    
  4. 創建虛擬DOM元素:

    // 這是 創建虛擬DOM元素的 API    <h1 title="啊,五環" id="myh1">你比四環多一環</h1>
    //  第一個參數: 字符串類型的參數,表示要創建的標籤的名稱
    //  第二個參數:對象類型的參數, 表示創建的元素的屬性節點,可以用null
    //  第三個參數: 子節點
    const myh1 = React.createElement('h1', { title: '啊,五環', id: 'myh1' }, '你比四環多一環')
    
  5. 渲染:

    // 3. 渲染虛擬DOM元素
    // 參數1: 表示要渲染的虛擬DOM對象
    // 參數2: 指定容器,注意:這裏不能直接放 容器元素的Id字符串,需要放一個容器的DOM對象
    ReactDOM.render(myh1, document.getElementById('app'))
    

2. JSX語法

什麼是JSX語法:就是符合 xml 規範的 JS 語法;(語法格式相對來說,要比HTML嚴謹很多)

  1. 如何啓用 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/ }
          ]
      }
      

  2. jsx 語法的本質: 並不是直接把 jsx 渲染到頁面上,而是內部先轉換成了 createElement 形式,再渲染的;

  3. 在 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'))
      
  4. 在 jsx 中 寫註釋:推薦使用{ /* 這是註釋 */ }

  5. 爲 jsx 中的元素添加class類名:需要使用className 來替代 classhtmlFor替換label的for屬性

  6. 在JSX創建DOM的時候,所有的節點,必須有唯一的根元素進行包裹

  7. 在 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')) 
    
  1. 父組件向子組件傳遞數據

  2. 使用{…obj}屬性擴散傳遞數據

  3. 將組件封裝到單獨的文件中

  4. 注意:組件的名稱首字母必須是大寫

  5. 在導入組件的時候,如何省略組件的.jsx後綴名:

    // 打開 webpack.config.js ,並在導出的配置對象中,新增 如下節點:
    resolve: {
        extensions: ['.js', '.jsx', '.json'], // 表示,這幾個文件的後綴名,可以省略不寫
        alias: {
            '@': path.join(__dirname, './src')// 這樣@就表示項目根目錄中src這一層目錄
        }
    }
    
  6. 在導入組件的時候,配置和使用@路徑符號

第2種 - 創建組件的方式

使用 class 關鍵字來創建組件

ES6 中 class 關鍵字,是實現面向對象編程的新形式;

瞭解ES6中 class 關鍵字的使用

  1. class 中 constructor 的基本使用

  2. 實例屬性和實例方法

  3. 靜態屬性和靜態方法

    // 創建了一個動物類
    // 注意:在 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();
    
  4. 使用 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關鍵字創建組件

  1. 最基本的組件結構:

    // 如果要使用 class 定義組件,必須 讓自己的組件,繼承自 React.Component
    class 組件名稱 extends React.Component {
        // 在 組件內部,必須有 render 函數,作用:渲染當前組件對應的 虛擬DOM結構
        render(){
            // render 函數中,必須 返回合法的 JSX 虛擬DOM結構
            return <div>這是 class 創建的組件</div>
        }
    }
    
  2. 組件的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,沒有自己的私有數據和 生命週期函數;

  1. 構造函數創建出來的組件:叫做“無狀態組件”【無狀態組件今後用的不多】
  2. class關鍵字創建出來的組件:叫做“有狀態組件”【今後用的最多】
  3. 什麼情況下使用有狀態組件?什麼情況下使用無狀態組件?
    • 如果一個組件需要有自己的私有數據,則推薦使用:class創建的有狀態組件;
    • 如果一個組件不需要有私有的數據,則推薦使用:無狀態組件;
    • React官方說:無狀態組件,由於沒有自己的state和生命週期函數,所以運行效率會比 有狀態組件稍微高一些;

有狀態組件和無狀態組件之間的本質區別就是:有無state屬性、和 有無生命週期函數;

  1. 組件中的 propsstate/data 之間的區別
    • props 中的數據都是外界傳遞過來的;
    • state/data 中的數據,都是組件私有的;(通過 Ajax 獲取回來的數據,一般都是私有數據);
    • props 中的數據都是隻讀的;不能重新賦值;
    • state/data 中的數據,都是可讀可寫的;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章