一区二区日本_久久久久久久国产精品_无码国模国产在线观看_久久99深爱久久99精品_亚洲一区二区三区四区五区午夜_日本在线观看一区二区

初探React中函數(shù)組件和類組件的差異

自從React Hooks的出來(lái),社區(qū)討論Hooks的越來(lái)越多。愛(ài)掏網(wǎng) - it200.com這并不是說(shuō)React Hooks就優(yōu)于類組件,但是使用Hooks來(lái)構(gòu)建組件時(shí)有一個(gè)巨大的可用性提升,特別是因?yàn)檫@些函數(shù)組件可以通過(guò)React Hooks中的鉤子函數(shù)來(lái)訪問(wèn)狀態(tài)和生命周期。愛(ài)掏網(wǎng) - it200.com

今天我們就來(lái)一起聊聊如何將React的類組件轉(zhuǎn)換為函數(shù)組件,用React Hooks中的鉤子函數(shù)替換類組件中的setState和生命周期方法,比如componentWillMountcomponentWillReceiveProps等。愛(ài)掏網(wǎng) - it200.com

因此,讓我們首先使用狀態(tài)和生命周期方法構(gòu)建一個(gè)基于類的React組件。愛(ài)掏網(wǎng) - it200.com也是大家最為熟悉的ToDoList組件。愛(ài)掏網(wǎng) - it200.com該組件具備:

  • 有一個(gè)文本輸入框(,用戶可以在輸入框中輸入想要的內(nèi)容
  • 有一個(gè)“添加列表項(xiàng)”按鈕(button,點(diǎn)擊該按鈕之后可以將文本輸入框的內(nèi)容添加到列表中(ToDoList中)
  • 顯示每個(gè)待辦事項(xiàng)的列表清單
  • 每個(gè)單獨(dú)的列表項(xiàng)目都有一個(gè)相關(guān)聯(lián)的復(fù)選框(),可以用來(lái)將列表項(xiàng)標(biāo)記為已完成
  • 列表項(xiàng)會(huì)存儲(chǔ)到瀏覽器的緩存中(本地存儲(chǔ)),并在應(yīng)用程序啟動(dòng)時(shí)從本地存儲(chǔ)中再次加載

我們的組件將使用statecomponentDidMountcomponentDidUpdategetDerivedStateFromProps生命周期方法。愛(ài)掏網(wǎng) - it200.com其中一些生命周期方法(比如getDerivedStateFromProps)將以一種非人為方式使用,以便能夠演示有哪些Hooks的鉤子函數(shù)可以替換這些生命周期的方法。愛(ài)掏網(wǎng) - it200.com

在開(kāi)始之前,先來(lái)學(xué)習(xí)關(guān)于類和函數(shù)相關(guān)的知識(shí)點(diǎn)。愛(ài)掏網(wǎng) - it200.com

作為Web開(kāi)發(fā)者,經(jīng)常和函數(shù)打交道。愛(ài)掏網(wǎng) - it200.com但要真正的理解和掌握他們也不是件易事,特別是對(duì)于初學(xué)JavaScript的同學(xué)更是如此。愛(ài)掏網(wǎng) - it200.com至少給我自己的感覺(jué)是如此。愛(ài)掏網(wǎng) - it200.com

在這里我們不會(huì)深入的去聊函數(shù)和類,因?yàn)橐嬲牧耐杆麄儯伎梢匀?xiě)本書(shū)了。愛(ài)掏網(wǎng) - it200.com由于我們今天要聊React的類組件和函數(shù)組件,那么在開(kāi)始之前很有必要的先了解一頂點(diǎn)有關(guān)于JavaScript的函數(shù)和類。愛(ài)掏網(wǎng) - it200.com先來(lái)看函數(shù)吧。愛(ài)掏網(wǎng) - it200.com

函數(shù)在JavaScript中被認(rèn)為是第一類公民,在JavaScript中明確的創(chuàng)建函數(shù)的概念非常重要。愛(ài)掏網(wǎng) - it200.com

JavaScript語(yǔ)言似乎和其他編程語(yǔ)言不同,我們可以在JavaScript中以不同的方式來(lái)創(chuàng)建一個(gè)函數(shù),常見(jiàn)的方式主要有:

用幾個(gè)簡(jiǎn)單的示例代碼來(lái)演示他們之間的不同:

// Function Declaration
function Greeting(user) {
    console.log(`Hello, ${user}`)
}

Greeting('@w3cplus') // ? Hello, @w3cplus

// Function Expression
const Greeting = function(user) { // 作為對(duì)象分配給變量
    console.log(`Hello, ${user}`)
}

const Methods = {
    numbers: [1, 2, 8],
    // Function Expression
    sum: function() { // 在對(duì)象上創(chuàng)建一個(gè)方法
        return this.numbers.reduce(function(acc, num){ // Function Expression (使用該函數(shù)作為回調(diào)函數(shù))
            return acc + num
        })
    }
}

// Shorthand Method Definition
const Collection = { // 用于Object Literals和ES6 Class聲明中
    items: [],
    // 使用函數(shù)名來(lái)定義
    // 使用一對(duì)圓括號(hào)中的參數(shù)列表和一對(duì)花括號(hào)來(lái)分隔主體語(yǔ)句
    add(...items) { 
        this.items.push(...items)
    },
    get(index) {
        return this.items[index]
    }
}

// Arrow Function
let empty = () =>{}

let simple = a => a > 15 ? 15 : a

let max = (a, b) => a > b ? a : b

let numbers = [1, 2, 3, 4]
let sum = numbers.reduce((a, b) => a + b)
let even = numbers.filter(v => v % 2 == 0)
let double = numbers.map(v => v * 2)

primise.then( a => {
    // ...
}).then(b => {
    // ...
})

// Generator Function
// JavaScript中的生成器函數(shù)返回這個(gè)生成器的迭代器對(duì)象

function* indexGenerator() {
    var index = 0
    while(true) {
        yield index++
    }
}

const indexGenerator = function* () {
    var index = 0
    while(true) {
        yield index++
    }
}

const obj = {
    *indexGenerator() {
        var index = 0
        while(true) {
            yield index++
        }
    }
}

// Function Constructor
const sum = new Function('a', 'b', 'return a + b')
sum(1, 2) // ? 3

類是ES6中開(kāi)始引入的,實(shí)質(zhì)上是JavaScript現(xiàn)有的基于原型的繼承的語(yǔ)法糖。愛(ài)掏網(wǎng) - it200.com實(shí)際上,類是特殊的函數(shù),就像你能夠定義的函數(shù)表達(dá)式和函數(shù)聲明一樣,類語(yǔ)法主要有兩個(gè)組成部分:類表達(dá)式類聲明愛(ài)掏網(wǎng) - it200.com

// 類聲明
class Rectangle {
    constructor(height, width) {
        this.height = height
        this.width = width
    }
}

// 類表達(dá)式

// 匿名類
let Rectangle = class {
    constructor(height, width) {
        this.height = height
        this.width = width
    }
}

// 命名類
let Rectangle = class Rectangle {
    constructor(height, width) {
        this.height = height
        this.width = width
    }
}

而且還可以使用extends關(guān)鍵字在類聲明或類表達(dá)式中用于創(chuàng)建一個(gè)類作為另一個(gè)類的子類:

class Animal {
    constructor(name) {
        this.name = name
    }

    sayHi() {
        console.log(this.name)
    }
}

class Dog extends Animal {
    sayHi() {
        console.log(`${this.name} barks.`)
    }
}
let dog = new Dog('Mitzie')
dog.sayHi() // ? Mitzie barks

如果子類中存在構(gòu)造函數(shù),則需要在使用this之前首先調(diào)用super()愛(ài)掏網(wǎng) - it200.com也可以擴(kuò)展傳統(tǒng)折基于函數(shù)的“類”

function Animal(name) {
    this.name = name
}

Animal.prototype.sayHi = function() {
    console.log(this.name)
}

class Dog extends Animal {
    sayHi() {
        super.sayHi()
        console.log(`${this.name} barks.`) 
    }
}

let dog = new Dog('Mitzie')
dog.sayHi() 

如果你想更深入的了解有關(guān)于JavaScript中的函數(shù)和類相關(guān)的知識(shí)的話,可以花點(diǎn)時(shí)間閱讀下面相關(guān)文章:

  • 6 Ways to Declare JavaScript Functions
  • Understanding JavaScript Functions
  • How To Define Functions in JavaScript
  • Curry and Function Composition
  • Understanding JavaScript Callbacks and best practices
  • Understanding Classes in JavaScript
  • Understanding Prototypes and Inheritance in JavaScript
  • A Deep Dive into Classes
  • A Guide To Prototype-Based Class Inheritance In JavaScript
  • Understanding Public and Private Fields in JavaScript Class
  • 3 ways to define a JavaScript class
  • Object-oriented JavaScript: A Deep Dive into ES6 Classes
  • Demystifying Class in JavaScript
  • Javascript Classes — Under The Hood
  • JavaScript engine fundamentals: Shapes and Inline Caches
  • Understanding "Prototypes" in JavaScript
  • Advanced TypeScript Concepts: Classes and Types
  • A Beginner's Guide to JavaScript's Prototype

我們回到React的世界當(dāng)中來(lái)。愛(ài)掏網(wǎng) - it200.com在React中我們可以以函數(shù)形式定義一個(gè)組件,比如像下面這樣:

function SayHi() {
    return 

Hello, React

}

也可以將SayHi這個(gè)組件以類的形式來(lái)定義:

class SayHi extends React.Component {
    render() {
        return 

Hello, React

} }

在當(dāng)你要使用一個(gè)組件時(shí),比如要使用SayHi這個(gè)組件,并不會(huì)過(guò)多的關(guān)注它是以什么方式來(lái)定義(聲明)的組件,只會(huì)關(guān)心如何使用:

雖然使用者不會(huì)太過(guò)關(guān)注它是怎么創(chuàng)建的(以哪種方式創(chuàng)建的),但React自身對(duì)于怎么創(chuàng)建組件是較為關(guān)注也會(huì)在意其差別。愛(ài)掏網(wǎng) - it200.com

如果SayHi是一個(gè)函數(shù),React需要調(diào)用它:

// 你的代碼
function SayHi() {
    return 

Hello, React

} // React內(nèi)部 const result = SayHi(props) // ?

Hello, React

如果SayHi是一個(gè)類,React需要先用new操作符將其實(shí)例化,然后調(diào)用剛才生成實(shí)例的render方法:

// 你的代碼
class SayHi extends React.Component {
    render() {
        return 

Hello, React

} } // React內(nèi)部 const instance = new SayHi(props) // ? SayHi {} const result = instance.render() // ?

Hello, React

無(wú)論哪種情況,React的最終目標(biāo)是去獲取渲染后的DOM節(jié)點(diǎn),比如SayHi組件,獲取渲染后的DOM節(jié)點(diǎn)是:

Hello, React

具體需要取決于SayHi組件是怎么定義的。愛(ài)掏網(wǎng) - it200.com

從上面的代碼中你可能已經(jīng)發(fā)現(xiàn)了,在調(diào)用類時(shí),使用了new關(guān)鍵字來(lái)調(diào)用:

// 如果SayHi是一個(gè)函數(shù)
const result = SayHi(props); // ? 

Hello, React

// 如果SayHi是一個(gè)類 const instance = new SayHi(props) // ? SayHi {} const result = instance.render() // ?

Hello, React

那么JavaScript中的new起什么作用呢?在ES6之前,JavaScript是沒(méi)有類(class)這樣的概念。愛(ài)掏網(wǎng) - it200.com在這種情況之前如果要使用類這樣的特性都是使用普通函數(shù)來(lái)模擬。愛(ài)掏網(wǎng) - it200.com即,在函數(shù)調(diào)用前加上new關(guān)鍵字,就可以把任何函數(shù)當(dāng)做一個(gè)類的構(gòu)造函數(shù)來(lái)用

function Fruit(name) {
    this.name = name
}

const apple = new Fruit('apple') // ? Fruit?{name: "apple"}
const banana = Fruit('banana')   // ? undefined   

JavaScript中的new關(guān)鍵字會(huì)進(jìn)行如下的操作:

  • 創(chuàng)建一個(gè)空的對(duì)象,即{}
  • 鏈接該對(duì)象(即設(shè)置該對(duì)象的構(gòu)造函數(shù))到另一個(gè)對(duì)象
  • 將創(chuàng)建的對(duì)象作為this的上下文
  • 如果該函數(shù)沒(méi)有返回對(duì)象,則返回this

正如上面的示例來(lái)說(shuō):

  • 調(diào)用Fruit('apple')時(shí)前面添加了new關(guān)鍵字,這個(gè)時(shí)候JavaScript會(huì)知道Fruit只是一個(gè)函數(shù),同時(shí)也會(huì)假裝它是一個(gè)構(gòu)造函數(shù)。愛(ài)掏網(wǎng) - it200.com會(huì)創(chuàng)建一個(gè)空對(duì)象({}并把Fruit中的this指向那個(gè)對(duì)象,以便我們可以通過(guò)類似this.name的形式去設(shè)置一些東西,然后把這個(gè)對(duì)象返回
  • 調(diào)用Fruit('banana')時(shí)前面沒(méi)有添加new關(guān)鍵字,其中的this會(huì)指向某個(gè)全局且無(wú)用的東西,比如windowundefined,因此代碼會(huì)崩潰或者做一些像設(shè)置window.name之類的傻事

也就是說(shuō):

// 和Fruit中的this是等效的對(duì)象
const apple = new Fruit('apple') // ? Fruit?{name: "apple"}

new關(guān)鍵字同時(shí)也把放在Fruit.prototype上的東西放到了apple對(duì)象上:

function Fruit(name) {
    this.name = name
}

Fruit.prototype.SayHi = function () {
    console.log(`Hi,我想吃${this.name}`)
}

const apple = new Fruit('蘋(píng)果')

apple.SayHi() // ? Hi,我想吃蘋(píng)果

這就是在JavaScript中如何通過(guò)new關(guān)鍵字來(lái)模擬類的方式。愛(ài)掏網(wǎng) - it200.com有關(guān)于new更多的介紹可以閱讀:

  • JavaScript’s new

聲明:所有內(nèi)容來(lái)自互聯(lián)網(wǎng)搜索結(jié)果,不保證100%準(zhǔn)確性,僅供參考。如若本站內(nèi)容侵犯了原著者的合法權(quán)益,可聯(lián)系我們進(jìn)行處理。
發(fā)表評(píng)論
更多 網(wǎng)友評(píng)論0 條評(píng)論)
暫無(wú)評(píng)論

返回頂部

主站蜘蛛池模板: 性高湖久久久久久久久 | 日韩免费视频一区二区 | 婷婷成人在线 | 91久久精品日日躁夜夜躁欧美 | www免费视频 | 国产小视频在线观看 | 亚洲一区 | 精品国产18久久久久久二百 | 亚洲欧美在线观看 | 国产福利在线播放麻豆 | 人成精品 | 黄视频网址| 国产在线小视频 | 中文字幕电影在线观看 | 色橹橹欧美在线观看视频高清 | 一区二区三区精品视频 | 国产一区二区在线免费观看 | 欧美一区免费 | 欧美激情精品久久久久久 | 国产一区二区日韩 | 天天干com | 成人av一区二区三区 | 999免费网站 | 国产区一区二区三区 | 午夜视频网站 | 国产福利在线小视频 | 国产一区二区在线播放 | 国产精品免费在线 | 色综合99 | 国产91 在线播放 | 欧美视频一区二区三区 | 欧洲亚洲精品久久久久 | a毛片视频网站 | 午夜精品一区二区三区在线视 | 精品天堂| 伊人春色在线观看 | 中文欧美日韩 | 亚洲免费三区 | 日韩av在线一区 | 成人一区二区三区在线 | 91国产视频在线观看 |