初探React中函數組件和類組件的差異

    自從React Hooks的出來,社區討論Hooks的越來越多。愛掏網 - it200.com這并不是說React Hooks就優于類組件,但是使用Hooks來構建組件時有一個巨大的可用性提升,特別是因為這些函數組件可以通過React Hooks中的鉤子函數來訪問狀態和生命周期。愛掏網 - it200.com

    今天我們就來一起聊聊如何將React的類組件轉換為函數組件,用React Hooks中的鉤子函數替換類組件中的setState和生命周期方法,比如componentWillMountcomponentWillReceiveProps等。愛掏網 - it200.com

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

    • 有一個文本輸入框(,用戶可以在輸入框中輸入想要的內容
    • 有一個“添加列表項”按鈕(button,點擊該按鈕之后可以將文本輸入框的內容添加到列表中(ToDoList中)
    • 顯示每個待辦事項的列表清單
    • 每個單獨的列表項目都有一個相關聯的復選框(),可以用來將列表項標記為已完成
    • 列表項會存儲到瀏覽器的緩存中(本地存儲),并在應用程序啟動時從本地存儲中再次加載

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

    在開始之前,先來學習關于類和函數相關的知識點。愛掏網 - it200.com

    作為Web開發者,經常和函數打交道。愛掏網 - it200.com但要真正的理解和掌握他們也不是件易事,特別是對于初學JavaScript的同學更是如此。愛掏網 - it200.com至少給我自己的感覺是如此。愛掏網 - it200.com

    在這里我們不會深入的去聊函數和類,因為要真正的聊透他們,都可以去寫本書了。愛掏網 - it200.com由于我們今天要聊React的類組件和函數組件,那么在開始之前很有必要的先了解一頂點有關于JavaScript的函數和類。愛掏網 - it200.com先來看函數吧。愛掏網 - it200.com

    函數在JavaScript中被認為是第一類公民,在JavaScript中明確的創建函數的概念非常重要。愛掏網 - it200.com

    JavaScript語言似乎和其他編程語言不同,我們可以在JavaScript中以不同的方式來創建一個函數,常見的方式主要有:

    用幾個簡單的示例代碼來演示他們之間的不同:

    // Function Declaration
    function Greeting(user) {
        console.log(`Hello, ${user}`)
    }
    
    Greeting('@w3cplus') // ? Hello, @w3cplus
    
    // Function Expression
    const Greeting = function(user) { // 作為對象分配給變量
        console.log(`Hello, ${user}`)
    }
    
    const Methods = {
        numbers: [1, 2, 8],
        // Function Expression
        sum: function() { // 在對象上創建一個方法
            return this.numbers.reduce(function(acc, num){ // Function Expression (使用該函數作為回調函數)
                return acc + num
            })
        }
    }
    
    // Shorthand Method Definition
    const Collection = { // 用于Object Literals和ES6 Class聲明中
        items: [],
        // 使用函數名來定義
        // 使用一對圓括號中的參數列表和一對花括號來分隔主體語句
        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中的生成器函數返回這個生成器的迭代器對象
    
    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中開始引入的,實質上是JavaScript現有的基于原型的繼承的語法糖。愛掏網 - it200.com實際上,類是特殊的函數,就像你能夠定義的函數表達式和函數聲明一樣,類語法主要有兩個組成部分:類表達式類聲明愛掏網 - it200.com

    // 類聲明
    class Rectangle {
        constructor(height, width) {
            this.height = height
            this.width = width
        }
    }
    
    // 類表達式
    
    // 匿名類
    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關鍵字在類聲明或類表達式中用于創建一個類作為另一個類的子類:

    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
    

    如果子類中存在構造函數,則需要在使用this之前首先調用super()愛掏網 - it200.com也可以擴展傳統折基于函數的“類”

    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() 
    

    如果你想更深入的了解有關于JavaScript中的函數和類相關的知識的話,可以花點時間閱讀下面相關文章:

    • 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的世界當中來。愛掏網 - it200.com在React中我們可以以函數形式定義一個組件,比如像下面這樣:

    function SayHi() {
        return 

    Hello, React

    }

    也可以將SayHi這個組件以類的形式來定義:

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

    Hello, React

    } }

    在當你要使用一個組件時,比如要使用SayHi這個組件,并不會過多的關注它是以什么方式來定義(聲明)的組件,只會關心如何使用:

    雖然使用者不會太過關注它是怎么創建的(以哪種方式創建的),但React自身對于怎么創建組件是較為關注也會在意其差別。愛掏網 - it200.com

    如果SayHi是一個函數,React需要調用它:

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

    Hello, React

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

    Hello, React

    如果SayHi是一個類,React需要先用new操作符將其實例化,然后調用剛才生成實例的render方法:

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

    Hello, React

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

    Hello, React

    無論哪種情況,React的最終目標是去獲取渲染后的DOM節點,比如SayHi組件,獲取渲染后的DOM節點是:

    Hello, React

    具體需要取決于SayHi組件是怎么定義的。愛掏網 - it200.com

    從上面的代碼中你可能已經發現了,在調用類時,使用了new關鍵字來調用:

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

    Hello, React

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

    Hello, React

    那么JavaScript中的new起什么作用呢?在ES6之前,JavaScript是沒有類(class)這樣的概念。愛掏網 - it200.com在這種情況之前如果要使用類這樣的特性都是使用普通函數來模擬。愛掏網 - it200.com即,在函數調用前加上new關鍵字,就可以把任何函數當做一個類的構造函數來用

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

    JavaScript中的new關鍵字會進行如下的操作:

    • 創建一個空的對象,即{}
    • 鏈接該對象(即設置該對象的構造函數)到另一個對象
    • 將創建的對象作為this的上下文
    • 如果該函數沒有返回對象,則返回this

    正如上面的示例來說:

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

    也就是說:

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

    new關鍵字同時也把放在Fruit.prototype上的東西放到了apple對象上:

    function Fruit(name) {
        this.name = name
    }
    
    Fruit.prototype.SayHi = function () {
        console.log(`Hi,我想吃${this.name}`)
    }
    
    const apple = new Fruit('蘋果')
    
    apple.SayHi() // ? Hi,我想吃蘋果
    

    這就是在JavaScript中如何通過new關鍵字來模擬類的方式。愛掏網 - it200.com有關于new更多的介紹可以閱讀:

    • JavaScript’s new

    聲明:所有內容來自互聯網搜索結果,不保證100%準確性,僅供參考。如若本站內容侵犯了原著者的合法權益,可聯系我們進行處理。
    發表評論
    更多 網友評論0 條評論)
    暫無評論

    返回頂部

    主站蜘蛛池模板: 国产三级一区二区三区| 久久免费视频一区| 日本一区二区三区日本免费| 国产在线精品一区免费香蕉| 中文字幕日韩一区二区不卡| 精品国产不卡一区二区三区| 白丝爆浆18禁一区二区三区 | 国产福利电影一区二区三区久久老子无码午夜伦不 | 精品国产一区二区三区www| 免费无码一区二区三区| 国模精品一区二区三区| 无码日韩人妻AV一区免费l| 国产高清视频一区二区| 精品日韩一区二区| 在线|一区二区三区| 亚洲国产欧美日韩精品一区二区三区 | 久久精品动漫一区二区三区| 亚洲一区视频在线播放 | 亚洲午夜一区二区三区| 日韩精品中文字幕无码一区| 无码一区二区三区在线观看| 亚洲午夜福利AV一区二区无码| 国产色精品vr一区区三区| 亚洲中文字幕丝袜制服一区 | 91在线视频一区| 国产精品久久久久久麻豆一区| 亚洲高清一区二区三区 | 国产在线视频一区| 国产亚洲欧洲Aⅴ综合一区| 国产在线观看一区二区三区精品| 国产91一区二区在线播放不卡| 亚洲乱码国产一区网址| 亚洲国产综合无码一区 | 成人精品一区二区三区中文字幕| 国产精品一区二区三区99| 亚洲色婷婷一区二区三区| 日产精品久久久一区二区| 久久久久人妻一区二区三区| 久久久久人妻精品一区| 色一情一乱一伦一区二区三欧美 | 国产精品一区二区久久国产|