React組件总棵、組件封裝、組件通信

React

目標

  • 了解組件以及組件的封裝

  • 組件通信

  • children

  • defaultProps

React

React.js 是一個幫助你構建頁面 UI 的庫。React.js 將幫助我們將界面分成了各個獨立的小塊帜篇,每一個塊就是組件糙捺,這些組件之間可以組合、嵌套笙隙,就成了我們的頁面洪灯。

一個組件的顯示形態(tài)和行為有可能是由某些數據決定的。而數據是可能發(fā)生改變的竟痰,這時候組件的顯示形態(tài)就會發(fā)生相應的改變签钩。而 React.js 也提供了一種非常高效的方式幫助我們做到了數據和組件顯示形態(tài)之間的同步。

React.js 不是一個框架坏快,它只是一個庫铅檩。它只提供 UI (view)層面的解決方案。在實際的項目當中莽鸿,它并不能解決我們所有的問題昧旨,需要結合其它的庫,例如 Redux祥得、React-router 等來協助提供完整的解決方法兔沃。

  • 模塊化:從 代碼 的角度,去分析問題级及,把我們編程時候的業(yè)務邏輯乒疏,分割到不同的模塊中來進行開發(fā),這樣能夠方便代碼的重用饮焦;

  • 組件化:從 UI 的角度怕吴,去分析問題,把一個頁面县踢,拆分為一些互不相干的小組件转绷,隨著我們項目的開發(fā),我們手里的組件會越來越多硼啤,最后议经,我們如果要實現一個頁面,可能直接把現有的組件拿過來進行拼接丙曙,就能快速得到一個完整的頁面爸业, 這樣方便了UI元素的重用其骄;組件是元素的集合體亏镰。

vue 組件化與 React組件化

1、Vue是如何實現組件化的:.vue 組件模板文件拯爽,瀏覽器不識別這樣的.vue文件索抓,所以,在運行前,會把 .vue 預先編譯成真正的組件逼肯;

  • template: UI結構

  • script: 業(yè)務邏輯和數據

  • style: UI的樣式

2耸黑、React如何實現組件化:在React中實現組件化的時候,根本沒有像 .vue 這樣的模板文件篮幢,而是大刊,直接使用JS代碼的形式,去創(chuàng)建任何你想要的組件三椿;

  • React中的組件缺菌,都是直接在 js 文件中定義的;

  • React的組件搜锰,并沒有把一個組件 拆分為 三部分(結構伴郁、樣式、業(yè)務邏輯)蛋叼,而是全部使用JS來實現一個組件的焊傅;(也就是說:結構、樣式狈涮、業(yè)務邏輯是混合在JS里面一起編寫出來的)

React中的核心概念

  • 虛擬DOM(Virtual Document Object Model)

  • DOM的本質是什么:就是用JS表示的UI元素

  • DOM和虛擬DOM的區(qū)別:

    • DOM是由瀏覽器中的JS提供功能狐胎,所以我們只能人為的使用 瀏覽器提供的固定的API來操作DOM對象;

    • 虛擬DOM:并不是由瀏覽器提供的薯嗤,而是我們程序員手動模擬實現的顽爹,類似于瀏覽器中的DOM,但是有著本質的區(qū)別骆姐;

  • 為什么要實現虛擬DOM:

  • 什么是React中的虛擬DOM:

  • 虛擬DOM的目的:

 DOM      DOM
?
?
 {
 html:
 head:
 body:{
 Navigation:na
 content:content
 }
?
 }
?
 class  Navigation {
 constructor() {
?
 }
?
 render(){
 <img />
 <p></p>
 }
 }
?
 var na = new Navigation();```

*   Diff算法

*   tree diff:新舊DOM樹镜粤,逐層對比的方式,就叫做 tree diff,每當我們從前到后玻褪,把所有層的節(jié)點對比完后肉渴,必然能夠找到那些 需要被更新的元素;

*   component diff:在對比每一層的時候带射,組件之間的對比同规,叫做 component diff;當對比組件的時候,如果兩個組件的類型相同窟社,則暫時認為這個組件不需要被更新券勺,如果組件的類型不同,則立即將舊組件移除灿里,新建一個組件关炼,替換到被移除的位置;

*   element diff:在組件中匣吊,每個元素之間也要進行對比儒拂,那么寸潦,元素級別的對比,叫做 element diff社痛;

*   key:key這個屬性见转,可以把 頁面上的 DOM節(jié)點 和 虛擬DOM中的對象,做一層關聯關系蒜哀;

#### 配置和安裝 React

##### 使用 create-react-app 腳手架安裝 React 開發(fā)環(huán)境

用 React 官網提供的 create-react-app 來搭建非常簡單:

1斩箫、配置安裝 npm

```npm -v```

2、安裝 create-react-app

```npm install -g create-react-app```

3撵儿、創(chuàng)建 React 項目

```//cd 創(chuàng)建項目的目錄
cd 項目路徑
?
//創(chuàng)建
create-react-app 項目名稱```

這條命令會幫我們構建一個叫 react_test 的工程校焦,并且會自動地幫助我們安裝所需要的依賴,現在只需要安靜地等待它安裝完统倒。

4寨典、啟動工程開始項目

```//cd 到項目路徑
cd react_test
?
//npm 啟動工程
npm start```

##### 手動創(chuàng)建 React 開發(fā)環(huán)境

面對復雜的項目, 入門級的構建工具, 是遠遠不夠的, 我們這里從零開始, 用webpack, 手動配置一個獨立的React開發(fā)環(huán)境, 開發(fā)環(huán)境完成后, 支持自動構建, 自動刷新, sass語法 等功能

1、創(chuàng)建項目路徑

```//cd 項目路徑
?
mkdir react_test
?
// 使用 npm 初始化項目
cd react_test
npm init```

2房匆、安裝相關的依賴和軟件包

```//這里主要示例安裝 react react-dom react-scripts
npm install react react-dom react-scripts```

3耸成、配置 package.json 文件和 webpack.config.js文件

## 組件

組件是 React 的核心,組件機制允許你將UI切分成獨立浴鸿、可復用的部分井氢,并針對每個部分單獨去做一定的處理。

#### 組件的好處

1岳链、標記鮮明花竞,容易維護,易與復用

2掸哑、塊狀化結構约急,減少css 的書寫,并且方便擴展

## React 中的組件

### React 構建組件的兩種方式

#### 構造函數構建組件

在React中苗分,構造函數厌蔽,就是一個最基本的組件,如果想要把組件放到頁面中摔癣,可以把 構造函數的名稱奴饮,當作組件的名稱,以 HTML 標簽形式引入頁面中即可择浊。

> 注意:React在解析所有的標簽的時候戴卜,是以標簽的首字母來區(qū)分的,如果標簽的首字母是小寫琢岩,那么就按照普通的 HTML 標簽來解析投剥,如果首字母是大寫,則按照組件的形式去解析渲染

```// 結論:組件的首字母必須是大寫
 function HelloMessage(props) {
 // 在組件中粘捎,如果想要使用外部傳遞過來的數據薇缅,必須,顯示的在 構造函數參數列表中攒磨,定義 props 屬性來接收泳桦;
 // 通過 props 得到的任何數據都是只讀的,不能從新賦值
 props.name = '000'
 return(
 <div>
 <h1>這是在Hello組件中定義的元素 --- {props.name}</h1>
 </div>
 )
 }```

#### Class 關鍵字構建組件

```class HelloMessage extends React.Component {
  render() {
    return <h1>Hello World!</h1>;
  }
}
  • 區(qū)別
  1. 用構造函數創(chuàng)建出來的組件:專業(yè)的名字叫做“無狀態(tài)組件”

  2. 用class關鍵字創(chuàng)建出來的組件:專業(yè)的名字叫做“有狀態(tài)組件”

JSX 語法

JSX是一種 JavaScript 的語法擴展娩缰,是 React 官方推出的一套語法規(guī)范灸撰。他可以在 JavaScript 寫 HTML 標簽,JSX 這種語法拼坎,就是為了把HTML模板直接嵌入到JS代碼里面浮毯,這樣就做到了模板和組件關聯,但是 JS 不支持這種包含 HTML 的語法泰鸡,所以需要通過工具將 JSX 編譯輸出成 JS 代碼才能使用债蓝。

npm i babel-preset-react -D
?```

> 1、如要要使用 JSX 語法盛龄,必須先運行 `cnpm i babel-preset-react -D`饰迹,然后再 `.babelrc` 中添加 語法配置;</br>  2余舶、JSX語法的本質:還是以 React.createElement 的形式來實現的啊鸭,并沒有直接把 用戶寫的 HTML代碼,渲染到頁面上匿值;</br>  3赠制、 當 編譯引擎,在編譯JSX代碼的時候挟憔,如果遇到了`<`那么就把它當作 HTML代碼去編譯钟些,如果遇到了 `{}` 就把 花括號內部的代碼當作 普通JS代碼去編譯;</br>  4绊谭、在JSX創(chuàng)建DOM的時候厘唾,所有的節(jié)點,必須有唯一的根元素進行包裹龙誊;

#### JSX 原理

JSX 其實就是 JavaScript 對象,JSX內部在運行的時候抚垃,也是先把 類似于HTML 這樣的標簽代碼,  轉換為了 React.createElement 的形式趟大;也就是說:我們寫了 JSX 這樣的標簽鹤树,也并不是直接把 我們的 HTML 標簽渲染到頁面上,而是先轉換成 React.createElement 這樣的JS代碼逊朽,再渲染到頁面中罕伯;

![image](https://upload-images.jianshu.io/upload_images/20519044-74e477ceea6121ae.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 

```import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import './index.css'
?
class Header extends Component {
 render () {
 return (
 <div>
 <h1 className='title'>React 學習</h1>
 </div>
 )
 }
}
?
ReactDOM.render(
 <Header />,
 document.getElementById('root')
)
?```

```import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import './index.css'
?
class Header extends Component {
 render () {
 return (
 React.createElement(
 "div",
 null,
 React.createElement(
 "h1",
 { className: 'title' },
 "React 學習"
 )
 )
 )
 }
}
?
ReactDOM.render(
 React.createElement(Header, null),
 document.getElementById('root')
);

組件嵌套

返回多個 JSX 元素必須要用一個外層的 JSX 元素把所有內容包裹起來。返回并列多個 JSX 元素是不合法的叽讳。

image

復用性非常強追他,我們可以把組件的內容封裝好坟募,然后靈活在使用在任何組件內。另外這里要注意的是邑狸,自定義的組件都必須要用大寫字母開頭懈糯,普通的 HTML 標簽都用小寫字母開頭。

組件state

React 把組件看成是一個狀態(tài)機(State Machines)单雾。通過與用戶的交互赚哗,實現不同狀態(tài),然后渲染 UI硅堆,讓用戶界面和數據保持一致屿储。 React 里,只需更新組件的 state渐逃,然后根據新的 state 重新渲染用戶界面(不要操作 DOM)够掠。

?
class CollectButton extends React.Component{
 constructor(){
 super();
 this.state = {
 collect:false,
 collectPrompt:"未收藏"
 }
 }
?
 handleClick(){
 var status = !this.state.collect
 var text = status?"收藏":"未收藏";
 this.setState({
 collect:status,
 collectPrompt:text
 });
 }
?
 render(){
 return(
 <button onClick={()=>{
 this.handleClick()
 }}>{this.state.collectPrompt}</button>
 );
 }
}
?
export default CollectButton;```

## 組件通信

#### React Props

state 和 props 主要的區(qū)別在于 props 是不可變的,而 state 可以根據與用戶交互來改變茄菊。這就是為什么有些容器組件需要定義 state 來更新和修改數據祖屏。 而子組件只能通過 props 來傳遞數據。

### 父傳子

子組件定義接受數據屬性名稱  父組件向該屬性賦值

```//父組件
class  Father extends React.Component {
  constructor() {
    super();
    this.state = {
      屬性名稱:屬性值
    }
  }

  render(){
    return({
      <子組件 子組件屬性名稱={this.state.屬性名稱}/>
    });
  }
}

//子組件接受
class Son extends React.Component{
  constructor(props){
    super();
    this.state = props;
  }

  render(){
    return(
      <子元素標簽>{this.state.子組件屬性名稱}</子元素標簽>
    );
  }

}

子傳父

回調函數的方式

class  Father extends React.Component {
  constructor() {
    super();
    this.state = {
      屬性名稱:屬性值
    }
  }

  // 父組件接受數據定于函數
  getData = (需要傳遞給父組件的值)=>{
    //拿到子組件傳遞給父組件的值
  }

  render(){
    return({
      <子組件 子組件屬性名稱={this.state.屬性名稱} 父組件接受數據函數名稱={this.getData}/>
    });
  }
}

//子組件接受
class Son extends React.Component{
  constructor(props){
    super();
    this.state = props;
  }

  handleClick(需要傳遞給父組件的值){
    this.props.父組件接受數據函數名稱(需要傳遞給父組件的值)
  }

  render(){
    return(
      <子元素標簽 onClick={()=>{
        this.handleClick(需要傳遞給父組件的值);
      }}>{this.state.子組件屬性名稱}</子元素標簽>

    );
  }

}

兄弟組件

通過父組件進行數據交互

跨組件通信

數據類型校驗

children

defaultProps

React 獲取dom

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
?
class Index extends Component {
 onClick(event){
 console.log(event.target.value);
 // 第一種方式
 var submitObj = document.getElementById('submit');
 submitObj.style.color = 'green';
 // 第二種方式
 ReactDOM.findDOMNode(submitObj).style.color = 'yellow';
 // 第三種方式
 this.refs.submit.style.color = 'blue';
 }
 render(){
 return (
 <div>
 <input id='submit' ref='submit'
 type='button' value='style'
 onClick={this.onClick.bind(this)}/>
 </div>
 )
 }
}```
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末买羞,一起剝皮案震驚了整個濱河市袁勺,隨后出現的幾起案子,更是在濱河造成了極大的恐慌畜普,老刑警劉巖期丰,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異吃挑,居然都是意外死亡钝荡,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進店門舶衬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來埠通,“玉大人,你說我怎么就攤上這事逛犹《巳瑁” “怎么了?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵虽画,是天一觀的道長舞蔽。 經常有香客問我,道長码撰,這世上最難降的妖魔是什么渗柿? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮脖岛,結果婚禮上朵栖,老公的妹妹穿的比我還像新娘颊亮。我一直安慰自己,他們只是感情好陨溅,可當我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布终惑。 她就那樣靜靜地躺著,像睡著了一般声登。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上揣苏,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天悯嗓,我揣著相機與錄音,去河邊找鬼卸察。 笑死脯厨,一個胖子當著我的面吹牛,可吹牛的內容都是我干的坑质。 我是一名探鬼主播合武,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼涡扼!你這毒婦竟也來了稼跳?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤吃沪,失蹤者是張志新(化名)和其女友劉穎汤善,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體票彪,經...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡红淡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了降铸。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片在旱。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖推掸,靈堂內的尸體忽然破棺而出桶蝎,到底是詐尸還是另有隱情,我是刑警寧澤谅畅,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布俊嗽,位于F島的核電站,受9級特大地震影響铃彰,放射性物質發(fā)生泄漏绍豁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一牙捉、第九天 我趴在偏房一處隱蔽的房頂上張望竹揍。 院中可真熱鬧敬飒,春花似錦、人聲如沸芬位。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽昧碉。三九已至英染,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間被饿,已是汗流浹背四康。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留狭握,地道東北人闪金。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像论颅,于是被迫代替她去往敵國和親哎垦。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,446評論 2 348