React基礎學習(第二天)

虛擬DOM

  • JSX 涉及到 虛擬DOM ,簡單聊一下

定時器渲染問題

// 方法
function render() {//2. 創建react對象let el = (<div><h3>時間更新</h3><p>{ new Date().toLocaleTimeString()}</p></div>)//3. 渲染ReactDOM.render(el, document.getElementById('root'))
}//4. 開啟一個定時器, 每秒渲染一次
setInterval(() => {render()
}, 1000)

渲染模式 :

/*** 最早的更新模式* 1. 數據* 2. 模板* 3. 數據+模板 => 真實的DOM* 4. 數據變了 => 最簡單直接的方式 => 最新數據+模板 => 新的DOM* 5. 新的DOM 把 舊的DOM完全直接替換掉* 6. 顯示新的DOM** 缺點 : 完全替換,  性能不好** 1. 數據* 2. 模板* 3. 數據+模板 => 真實的DOM* 4. 數據變化了 => 最新的數據 + 模板 => 新的DOM* 5. 新的DOM 和 舊的DOM 進行一一比較, 找到需要更新的地方* 6. 只需要更新需要改變的地方即可** 優點 : 不再是全部替換掉,* 缺點 : DOM比較就有性能問題了 , 會有多余的DOM和屬性進行比較(打印一級屬性),有損性能*  p 和 p對比  h3 和h3對比(多余的對比)** 1. 數據* 2. 模板* 3. 數據 + 模板 => 虛擬DOM (js對象) => 真實的DOM* 4. 數據發生改變(zs=>ls) => 最新的數據 + 模板 => 新的虛擬DOM* 5. 新的虛擬DOM 和 舊的虛擬DOM 通過 diff算法 進行比較* 6. 找到有差異的地方,(需要更新的地方)* 7. 更新一下就可以看到最新的DOM了*/
  • 打印屬性 :
let root = document.querySelector('#root')let str = ''
let count = 0
for (let k in root) {str += k + ' 'count++
}
console.log(str, count)
  • 查看圖片 : 演示對比找差異渲染
  • 文字描述 :
這就是所謂的 Virtual DOM 算法。包括幾個步驟:- 1.用 JavaScript 對象結構表示 DOM 樹的結構;然后用這個樹構建一個真正的 DOM 樹,插到文檔當中
- 2.當狀態變更的時候,重新構造一棵新的對象樹。然后用新的樹和舊的樹進行比較,記錄兩棵樹差異
- 3.2 所記錄的差異應用到步驟 1 所構建的真正的 DOM 樹上,視圖就更新了

DIff 算法

React 中有兩種假定:

  • 1 兩個不同類型的元素會產生不同的樹
  • 2 開發者可以通過 key 屬性指定不同樹中沒有發生改變的子元素

Diff 算法的說明 - 1

  • 如果兩棵樹的根元素類型不同,React 會銷毀舊樹,創建新樹
// 舊樹
<div><Counter />
</div>// 新樹
<span><Counter />
</span>執行過程: 刪除 div , 創建 span

Diff 算法的說明 - 2

  • 對于類型相同的 React DOM 元素,React 會對比兩者的屬性是否相同,只更新不同的屬性
  • 當處理完這個 DOM 節點,React 就會遞歸處理子節點。
// 舊
<div className="before" title="stuff"></div>
// 新
<div className="after" title="stuff"></div>
只更新:className 屬性// 舊
<div style={{color: 'red', fontWeight: 'bold'}}></div>
// 新
<div style={{color: 'green', fontWeight: 'bold'}}></div>
只更新:color屬性

Diff 算法的說明 - 3

  • 1 當在子節點的后面添加一個節點,這時候兩棵樹的轉化工作執行的很好
// 舊
<ul><li>1</li><li>2</li>
</ul>// 新
<ul><li>1</li><li>2</li><li>3</li>
</ul>執行過程:
React會匹配新舊兩個<li>1</li>,匹配兩個<li>2</li>,然后添加 <li>3</li> tree
  • 2 但是如果你在開始位置插入一個元素,那么問題就來了:
// 舊
<ul><li>1</li><li>2</li>
</ul>// 新
<ul><li>3</li>   li3 插入最前面<li>1</li><li>2</li>
</ul>執行過程:
React將改變每一個子節點,而非保持 <li>1</li><li>2</li> 不變

key 屬性

為了解決以上問題,React 提供了一個 key 屬性。當子節點帶有 key 屬性,React 會通過 key 來匹配原始樹和后來的樹。

// 舊
<ul><li key="1">1</li><li key="2">2</li>
</ul>// 新
<ul><li key="3">3</li><li key="1">1</li><li key="2">2</li>
</ul>執行過程:現在 React 知道帶有key '3' 的元素是新的,對于 '1''2' 僅僅移動位置即可

補充說明:

  • key 屬性在 React 內部使用,但不會傳遞給你的組件

  • 推薦:在遍歷數據時,推薦在組件中使用 key 屬性:<li key={item.id}>{item.name}</li>

  • 注意:key 只需要保持與他的兄弟節點唯一即可,不需要全局唯一

  • 注意:盡可能的減少數組 index 作為 key,數組中插入元素的等操作時,會使得效率底下 。 如果數組比較簡單, 開發中沒有刪除和移動操作,使用 index 也是可以的

組件

組件1 - 函數組件

基本使用

  • 函數組件 : 使用函數創建的組件叫組函數組件
  • 約定:
    • 約定1 : 組件名稱必須是大寫字母開頭, 也就是函數名稱需要首字母大寫
    • 約定2 : 函數組件必須有返回值
      • 不渲染內容 : return null
      • 渲染內容 : return JSX
    • 約定3 : 只能有一個唯一的根元素
    • 約定4 : 結構復雜, 使用() 包裹起來
  • 使用 : 把 組件名 當成 標簽名 一樣使用
// 函數組件
function Hello() {// return nullreturn <div>這是我的第一個函數組件</div>
}
// 渲染組件
ReactDOM.render(<Hello />, document.getElementById('root'))

傳參

  • 傳參 :
//1. 頭標簽內演示
//2. age='30'  age是字符串30age={30}   age是number 30
ReactDOM.render(<Child name='zs' age={30}/>, document.getElementById('root'))
  • 接收 :
    • 函數的參數接收 props
      • funciton Hello (props) { ... }
    • 讀取 : { props.name } 、 { props.age }
    • 注意 :
      • 傳過來的props 不能添加屬性
      • 傳過來的props 不能修改屬性值
    • 也可以直接解構 props里的屬性
      • funciton Hello ({ name, age }) { ... }

箭頭函數改造

const  Child = () => (<div><div>這是一個div</div><div>這是一個div</div></div>
)const Hello = ()=> <div>這是哈哈的啊</div>

組件2 - 類組件

基本使用

  • 類組件 : 使用 ES6 中class 創建的組件, 叫類組件
  • 約定 (同 函數組件)
    • 其他約定1 : 類組件必須繼承自 React.Component 父類 , 然后,才可以使用父類中提供的屬性或方法
    • 其他約定2 : 必須提供 render 方法, 來指定要渲染的內容, render 方法必須有返回值
// 2 創建類組件
class Hello extends React.Component {// 鉤子 render() {// return nullreturn <div>這是我的第一個class組件</div>}
}

傳參

  • 傳參 : 同函數組件一樣
ReactDOM.render(<Child name='zs'/>, document.getElementById('root'))
  • 接收參數
// 類組件
class Child extends React.Component { constructor(props) { super(props)// 接收方式1console.log(props);}render () { // 接收方式2console.log(this.props);// 解構const { name, age } = this.propsreturn <div>哈哈{ this.props.name }</div>}
}

ES6 - class

介紹

 ** es6 之前 創建對象 都是通過構造函數 實現的, 給原型添加方法,  給實例添加屬性* es6 之后, 給我們提供了一個字段 class *  通過class 創建對象 *   class :*     -: 一類對象, 對象的抽象 , 我們可以通過類創建對象*     - 動物        人 * *     - 對象: 具體的事物, 它有特征(屬性)和行為(方法)*     -//鳥     張三/王春春*/

使用 class 創建對象

  • 使用class 創建一個類 class Person { }
  • 創建對象 let p = new Person()
  • 添加屬性 在類里面的 constructor() { } 的里面添加屬性
  • 添加方法 直接在類里面添加方法
class Person { constructor() { this.name = 'zs';this.age = 30}say () { console.log('說話了');}
}let p = new Person()
console.log(p);
p.say()

繼承

  • 繼承 : 之前混入, 原型繼承… 都是對象繼承… (對象與對象之間,只要拿過來用就是繼承)
  • class 繼承 : 是 類與類之間的繼承 extends
// 人
class Person {constructor() {this.maxAge= 120}
}let p = new Person()
console.log(p)// ---------------------------------------------
/*** 以后凡是 extends 繼承* 當前類里面的 constructor 里面一定要加上super()* 因為底層都是給我們加的super,所以我們才能夠繼承過來,* 如果我們直接寫 constructor,而不寫super,意外著,底層的constructor會被覆蓋掉*/
// 中國人
class Chinese extends Person {constructor() {super() // super 其實就是調用父類的constructorthis.name = 'zs'}
}let c = new Chinese()
console.log(c)

函數組件和類組件的小結

  • 函數組件 : 函數創建組件
    • 函數名首字母一定要大寫
    • 把組件當成標簽使用
    • 函數內部 通過 return jsx
  • 類組件 : 類創建組件
    • 首字母也要大寫
    • 一定要繼承(extends) React.Component
    • 類里面一定要有一個 render 函數
    • render 函數里面通過 return jsx
    • 類組件也是當成標簽一樣使用的

函數組件和類組件的區別?

  • 函數組件 : 沒有狀態的, 沒有自己的數據
  • 類組件 : 有狀態 , 有自己的數據

狀態 State 的簡單說明

state 的定義

  • 方式1 : constructor 里面
 constructor() { super()//設置狀態1this.state = {name : 'zs'}}
  • 方法2 : 屬性初始化語法
// 設置狀態2
state = {name :'zhangsan '}

獲取 狀態 值 :

 // 直接獲取<p> { this.state.name }</p>// 解構獲取const { name } = this.state<p> { name }</p>

修改 狀態 值

// 鉤子函數 -  組件掛載完全  render調用完后會調用
componentDidMount() {//1. 直接修改// 如果使用 this.state.name = '春春' , 這樣只會修改state里面的數據,但是無法更新視圖// this.state.name = '春春'//2. 使用 setState 修改// 1-修改數據 2-重新調用render, 更新視圖this.setState({name: '春春'})
}

安裝 React 插件 ==> 查看 state 的值

  • react-developer-tools.crx
  • 安裝步驟 : 后綴crx 改為 zip, 解壓到當前文件, 安裝 拓展程序

使用 state 修改定時器

//2. 類組件
class Child extends React.Component {state = {time : new Date()     # + }render() {return (<div><h3>我是h3</h3><p>{ this.state.time.toLocaleTimeString() }</p>   # + </div>)}componentDidMount () { setInterval(() => {this.setState({      # + time: new Date()   # + })                   # + }, 1000);}
}

總結 :

  • 函數組件
    • 沒有狀態 ( 沒有自己的私有數據 )
    • 木偶組件, 組件一旦寫好, 基本就不會改變
    • 傳參 : function Child( props ) { } , props 只讀
  • 類組件
    • 有狀態 ( 有自己的私有數據 state )
    • 智能組件, 狀態發生改變, 就會更新視圖
    • 傳參 :
      • this.props
  • 優點
    • 類組件 : 有狀態,有生命周期鉤子函數, 功能比較強大
    • 函數組件 : 渲染更快
  • 以后區分使用 ?
    • 就看要不要狀態 , 要狀態(類組件) , 不要狀態 (函數組件)
  • props 和 state 區別?
    • state - 自己的私有數據 類似 vue 里的data
    • props - 外界傳進來的 類似 vue 里面的props

事件處理

事件注冊

  • 以前注冊事件
<button onclick='fn'>按鈕</button>
  • react 中注冊事件
    • 注冊事件屬性采用的是駝峰的 onClick=…
    • 注冊事件的事件處理函數 , 寫為函數形式,不能為字符串
    • onClick={ this.fn }, {} 可以拿到它的原始類型
// 注冊事件
<button onClick={ this.fn }>按鈕</button>// 事件處理函數
fn() {console.log('我被點擊了')
}

事件中 this 的處理

  • 演示this問題
// 注冊
<button onClick={this.fn}>按鈕</button>
// 事件
fn () { console.log('點擊了');this.setState({name : 'ls'})
}
// 報錯 : Uncaught TypeError: Cannot read property 'setState' of undefined
// react 中的this=undefined  是需要處理的
  • bind 和 call 的回憶使用
function f() {console.log(this)
}let obj = { name: 'zs' }bind 的使用
f.bind(obj) :  f里面的this 指向了obj
綁定之后沒有打印,不是bind出了問題,而是bind和call,和apply()
call和apply 1-調用 2-指向
bind   1-指向 2-返回一個新函數
let newF = f.bind(obj)newF()
  • 方式1 : bind
- 第一種constructor() { super()this.fn1 = this.fn1.bind(this)}- 第二種 : <button onClick={   this.fn1.bind(this)    }>按鈕</button>
  • 方式2 : 屬性初始化語法
// 注冊事件
return <button onClick={this.fn2}>按鈕</button>
// 屬性初始化語法
fn2 = () => { // 箭頭函數里面的this指向了外部的thisthis.setState({name : 'ls'})}
  • 方式3 : 箭頭函數
 <button onClick={     () =>  this.fn3()      }>按鈕</button>// 箭頭函數里面的this 指向外部的this
// 誰調當前this所在的函數, this就執行誰
fn3(){...
}
  • 總結
// 方法1 : bind (常用)
return <button onClick={     this.fn.bind(this) }>按鈕</button>
// 方法2 : 屬性初始化語法
return <button onClick={     this.fn1           }>按鈕</button>
// 方法3 : 箭頭函數
return <button onClick={    () => this.fn()     }>按鈕</button>
  • 三者使用場景
- 方式1和方式3 常用
- 如果函數體內的代碼比較少,比如就1~2=> 方式3
- 大部分情況下 => 優先使用 方式2
- 如果涉及到傳參  => 方式3

點擊事件傳參 + 配合this處理

  • 演示效果
return <button onClick={this.fn(123)}>按鈕</button>
不能這樣傳參,因為還沒有開始點擊,就已經開始調用了fn , 并且把參數傳過去了
  • 處理this方式1 : bind
 // 注冊事
return <button onClick={    this.fn.bind(this,123)     }>按鈕</button>// 傳參
fn( num ) { console.log('點擊了',num);
}
  • 處理this方式2 : 屬性初始化語法 – 不能傳參
  • 處理this方式3 : 箭頭函數
 // 注冊事
return <button onClick={   () => this.fn(123)          }>按鈕</button>// 傳參
fn( num ) { console.log('點擊了',num);
}

獲取事件對象 + 配合this處理

// 方式1 : bind , `處理函數最后一個參數`就是 事件對象 e
return <button onClick={this.fn1.bind(this, 123, 456)}>按鈕</button>
// 方式2 : 屬性初始化語法  不傳參數 默認形參就是事件對象 e
return <button onClick={this.fn2}>按鈕</button>
// 方式3 : 箭頭函數 通過箭頭函數獲取e,再繼續傳
return <button onClick={e => this.fn3(e)}>按鈕</button>

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/247921.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/247921.shtml
英文地址,請注明出處:http://en.pswp.cn/news/247921.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

iOS 去除字符串中的空格或多余空格(適合英文單詞)

NSString -stringByTrimmingCharactersInSet: 是個你需要牢牢記住的方法。它經常會傳入 NSCharacterSet whitespaceCharacterSet 或 whitespaceAndNewlineCharacterSet 來刪除輸入字符串的頭尾的空白符號。 需要重點注意的是&#xff0c;這個方法 僅僅 去除了 開頭 和 結尾 的…

華為交換機在Telnet登錄下自動顯示接口信息

因為用console連接交換機&#xff0c;默認是自動顯示接口信息的&#xff0c;比如down掉一個接口后&#xff0c;會自動彈出接口被down掉的信息&#xff0c;但是在telnet連接下&#xff0c;默認是不顯示這些信息的&#xff0c;需要開啟后才可顯示。 1、首先開啟info-center(默認是…

React基礎學習(第三天)

條件渲染 1. if / else render () {if (this.state.isLoading) { // 正在加載中return <h1>Loading...</h1>}return <div>這就是我們想要的內容</div>} // 鉤子函數 五秒鐘之后 修改狀態值componentDidMount () { setTimeout(() > {this.setState(…

componentsJoinedByString 和 componentsSeparatedByString 的方法的區別

將string字符串轉換為array數組 NSArray *array [Str componentsSeparatedByString:","]; &#xff1d;&#xff1d;反向方法 將array數組轉換為string字符串 NSString *tempString [mutableArray componentsJoinedByString:","];--,是分隔符 可不加分隔…

java中的各種數據類型在內存中存儲的方式

轉載別人的附上鏈接&#xff1a;https://blog.csdn.net/zj15527620802/article/details/80622314 1.java是如何管理內存的 java的內存管理就是對象的分配和釋放問題。&#xff08;其中包括兩部分&#xff09; 分配&#xff1a;內存的分配是由程序完成的&#xff0c;程序員需要通…

vscode的 jsonp 配置文件

{ // 工具-字體大小 “editor.fontSize”: 15, // 工具-tab縮進 “editor.tabSize”: 2, // 工具-在視區寬度換行 “editor.wordWrap”: “on”, // 工具-縮放 “window.zoomLevel”: 1, // 工具-編寫tab識別語言格式 “emmet.includeLanguages”: { “vue-html”: “html”, “…

NSString拼接字符串和NSPredicate詳解

NSString* string; // 結果字符串 02 NSString* string1, string2; //已存在的字符串&#xff0c;需要將string1和string2連接起來 03 04 //方法1. 05 string [[NSString alloc]initWithFormat:"%,%", string1, string2 ]; 06 07 //方法2. 08 string [string1 …

線程模塊

信號量 from threading import Semaphore,Thread import timedef func(a,b):time.sleep(1)sem.acquire()print(ab)sem.release()sem Semaphore(4) for i in range(10):t Thread(targetfunc,args(i,i5))t.start() 信號量事件 # 事件被創建的時候&#xff0c;默認為False狀態 #…

React中級學習(第一天)

Props深入 children 作用 : 獲取組件標簽的 子節點獲取方式 : this.props.children <App>此處的內容&#xff0c;就是組件的 children&#xff0c;將來通過組件的 props.children 就可以獲取到這些子節點了 </App>props 校驗 作用&#xff1a;規定組件props的類…

iOS 正則表達式判斷純數字以及匹配11位手機號碼

1用正則表達式 //是否是純數字(BOOL)isNumText:(NSString *)str{NSString * regex "(/^[0-9]*$/)";NSPredicate * pred [NSPredicate predicateWithFormat:"SELF MATCHES %", regex];BOOL isMatch [pred evaluateWithObject:st…

Elasticsearch集成ik分詞器

1、插件地址https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.0.0/elasticsearch-analysis-ik-7.0.0.zip 2、找到對應版本的插件通過 http://192.168.1.8:9200查看ES的版本&#xff0c;找到對應的IK分詞插件 下載與之對應的版本https://github.com/me…

React中級學習(第二天)

JSX 語法的轉化過程 (了解) 演示 : babel中文網試一試 let h1 JSX 僅僅是createElement() 方法的語法糖 (簡化語法)JSX 語法 被 babel/preset-react 插件編譯為 createElement() 方法React 元素&#xff1a;是一個對象&#xff0c;用來描述你希望在屏幕上看到的內容React 元素…

【】MTCNN基于NCNN的測試過程

前言 操作過程 NCNN: https://github.com/Tencent/ncnn/wiki/how-to-build#build-for-linux-x86; vector初始化&#xff1a;int num[4] { 1, 4, 3, 2 }; int numLength sizeof(num) / sizeof(num[0]); vector<int> nums(num, num numLength); //使用數組初始化向量 Q&…

iOS NSTextAttachment - 圖文混排

蘋果在iOS7中推出了一個新的類NSTextAttachment&#xff0c;它是做圖文混排的利器&#xff0c;本文就是用這個類&#xff0c;只用50行代碼實現文字與表情混排&#xff0c;當然也可以實現段落中的圖文混排。 首先說一下文字和表情的混排&#xff1a; 先來做點兒準備工作&#…

vuex的結構有哪些參數?

查看參考地址&#xff1a; https://vuex.vuejs.org/zh/ vuex 狀態管理模式&#xff0c;相當于數據的中間商 注意&#xff1a; 為相同 屬性有&#xff1a; 1.State vue中的data —> 存放數據 2.Getter vue中的計算屬性computed —>將已有的數據進行計算再次利用 3.…

百煉OJ - 1004 - 財務管理

題目鏈接&#xff1a;http://bailian.openjudge.cn/practice/1004/ 思路 求和取平均。。。 #include <stdio.h>int main() {float sum0,a;for(int i0;i<12;i){scanf("%f",&a);sum a;}printf("$%.2f\n",sum/12);return 0; } 轉載于:https://w…

iOS 自定義Cell按鈕的點擊代理事件

在實際開發工作中&#xff0c;我們經常會在自定義的Cell中布局一些按鈕&#xff0c;并且很多時候我們會在點擊這個按鈕的時候使我們的UItableviewController跳轉到下一界面&#xff0c;有的可能還要傳值。那么如何使我們的控制器能夠獲知我們按下了cell的按鈕呢&#xff1f;毫無…

Google 開源技術protobuf 簡介與樣例

今天來介紹一下“Protocol Buffers ”&#xff08;以下簡稱protobuf&#xff09;這個玩意兒。本來俺在構思“生產者/消費者模式 ”系列的下一個帖子&#xff1a;關于生產者和消費者之間的數據傳輸格式。由于里面扯到了protobuf&#xff0c;想想干脆單獨開一個帖子算了。 ★prot…

VUE全局導航守衛、 請求、響應攔截器 的設置

文件設置參考地址&#xff1a;https://gitee.com/wang_yu5201314/headlines__news/tree/master/%E9%A1%B9%E7%9B%AE%E6%BA%90%E7%A0%81%E6%96%87%E4%BB%B6/src 文件夾 Router 文件夾 index.js 中設置 全局導航守衛 文件 mian.js 中設置 請求、響應攔截器 設置 請求、響應攔截器…

JRE System Library和 Referenced Libraries 的區別和來源

JRE System Library 安裝jdk后&#xff0c;會有個目錄叫做jrejre目錄是核心類庫&#xff0c;目錄中裝的是類庫文件jre System Library顧名思義就表示系統類庫文件 Referenced Libraries referenced libraries放的是你引用的jar包&#xff0c;這個不需要自己創建的&#xff0c;你…