如何在 React 中使用裝飾器-即@修飾符


前言
裝飾器 decorator 是一種函數,是 Es6 的一個語法糖,是一種與類(class)相關的語法,用來注釋或修改類和方法

以@+函數名形式展現,可以放在類和類方法的定義前面

那它在 React 中是如何使用的呢,這里以create-react-app腳手架搭建的項目為例

為什么要使用裝飾器模式?
在設計模式中講到優先使用對象而不是類繼承,動態的給對象添加一些額外的屬性或方法,相比與使用繼承,裝飾器模式更加靈活

在 React 中,高階組件是一個非常厲害的東西,它最大的特點就是能夠:重用組件邏輯.達到精簡代碼能力

前提條件
在使用這種裝飾器方式時,需要對create-react-app做一些配置,它默認是不支持裝飾器模式的,需要對項目做一些配置

在項目根目錄中終端下使用npm run eject,這條命令主要是將我們的配置項做一個反向輸出,暴露出隱藏的 webpack 配置項,這樣可以項目進行修改了的,注意它是不可逆的

方式 1-經過 eject 后在 package.json 中的 plugins 中配置
使用裝飾器,需要使用babel來進行轉換,用到的插件是@babel/plugin-proposal-decorators

當用eject將webpack一些配置彈射出來以后,會看到根目錄下的package.json文件下新增了很多文件

在babel對象處進行插件的配置,將@babel/plugin-proposal-decorators添加到plugins后

{
"babel": {
"presets": [
"react-app"
],

"plugins": [
    [
        "@babel/plugin-proposal-decorators",
        { "legacy": true }
    ]
]

}
}
注意

create-react-app 腳手架中已經安裝了 @babel/plugin-proposal-decorators 插件,如果是自己配置的腳手架,則先要安裝插件:`npm install @babel/plugin-proposal-decorators --save-dev

當然有一個比較便捷的寫法就是使用安裝babel-plugin-transform-decorators-legacy

{
"babel": {
"presets": [
"react-app"
],

"plugins":[
"transform-decorators-legacy"
]

}
}
注意

如果使用的是 vscode, 可以在項目根目錄下添加 jsconfig.json 文件來消除代碼警告

{
"compilerOptions": {
"experimentalDecorators": true
}
}
或者在 vscode 中的設置中tsconfig啟動Experimental Decorators就可以解決此警告

方式 2-安裝 babel 插件在 babelrc 中配置
在使用這種裝飾器方式時,需要對create-react-app做一些配置,它默認是不支持裝飾器模式的,你需要對項目做一些配置

在create-react-app根目錄中終端下使用npm run eject,這條命令主要是將我們的配置項做一個反向輸出,暴露出隱藏的 webpack 配置項,這樣可以項目進行修改了的,注意它是不可逆的

使用裝飾器模式時:需要安裝兩個依賴:

cnpm install -D babel-preset-stage-2
cnpm install -D babel-preset-react-native-stage-0
然后你需要在根目錄下創建一個.babelrc文件,對.babelrc文件做一些配置

{
"presets": ["react-native-stage-0/decorator-support"]
}
經過這么配置后,就可以使用裝飾器了的

未使用裝飾器之前
如下是componentA.js一個高階組件

import React, { Component } from 'react';

function A(WrappedComponent) {
// 函數接收一個組件為參數,並返回一個類組件,繼承自Component
return class componentA extends Component {
render() {
return (




);
}
};
}

export default A;
如下componentB.js一個組件

import React, { Component } from 'react';
import A from './componentA'; // 引入高階組件

class componentB extends Component {
render() {
return

我是組件B
;
}
}

export default A(componentB); // 直接調用A,將組件componentB作為參數傳入
如果嵌套層次很多,會發現這種代碼不優雅,很難理解,如果用裝飾器,就解決了多層嵌套的問題

使用裝飾器
在componentB.js組件中

import React, { Component } from 'react';
import A from './componentA'; // 引入高階組件

@A // 直接@+函數名就可以了的
class componentB extends Component {
render() {
return

我是組件B
;
}
}

export default componentB; // 這里直接返回componentB組件
你可以給高階組件添加靜態屬性,以及實例屬性

import React, { component } from 'react';

function Foo(params) {
params.title = 'itclanCoder';
params.prototype.decorator =
'decorator是裝飾器,即@+函數名,用來注釋或修改類方法';
}

@Foo
class ComponentA extends Component {
render() {
return (


{ComponentA.title}


{ComponentA.decorator}



);
}
}
在調用裝飾器的時候,可以往里面傳入實參,則在函數需要return一個函數,return 返回的函數參數是類的本身,下面的 Foo 函數可以接受參數,這就等於可以修改裝飾器的行為

import React, { component } from 'react';

function Foo(isAble) {
return function(target) {
target.isAble = isAble;
};
}

@Foo(false)
class ComponentA extends Component {
render() {
return

{componentA.isAble} // false
;
}
}
TypeScript
如果你的項目已經開始使用TypeScript,那我們只需要在tsconfig.json文件中的 experimentalDecorators 設置為 true

就可以使用 ES7 新特性裝飾器了

解決 vscode 中不支持 decorator 語法警告問題
在項目根目錄創建tsconfig.json,設置如下所示

{
"compilerOptions": {
"experimentalDecorators": true,
"allowJs": true
}
}
注意事項
⒈ 裝飾器對類的行為的改變時代碼編譯時發生的,而不是在運行時,這意味着,裝飾器能在編譯階段運行代碼,它本身就是編譯時執行的函數

⒉ 裝飾器只能用於類和類的方法,不能用於函數,因為它存在函數提升

結語
高階組件是函數,參數是組件並返回一個組件的函數,允許向一個現有的對象添加新的功能,增加靜態屬性於實例屬性,又不改變結構,屬於包裝器模式的一種

因為 Es7 中添加了 decorator 屬性,使用@函數名表示,在編寫 React 組件時,高階組件是一個非常實用的東西

或許不知不覺中,自己就已經實現了的,很久以前看過設計模式中的裝飾器模式,一直雲里霧里,不知道這個東西有什么用

直到它在 React 中高階組件還可以簡寫,這么用..

如果您有關裝飾器問題,歡迎給我留言,一起學習探討

引自:如何在 React 中使用裝飾器-即@修飾符


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM