1. 程式人生 > 實用技巧 >React-建立專案-引入antd-按需載入-自定義主題-裝飾器

React-建立專案-引入antd-按需載入-自定義主題-裝飾器

建立專案:

npx create-react-app demo
cd demo
npm start  

引入antd:

yarn add antd
import React from "react";
import Button from "antd/es/button";
import "antd/dist/antd.css";

function App() {
  return (
    <div className="App">
      app
      <Button type="primary">btn</Button>
    </div>
  );
}

export default App;

// ps:此時使用antd元件時的方式較麻煩且樣式全部引入增加程式碼量,推薦按需引入的方式

引入antd按需載入時的配置:

首先安裝外掛:

yarn add react-app-rewired customize-cra babel-plugin-import  

其次新增配置項檔案config-overrides.js:

const { override, fixBabelImports } = require("customize-cra");

module.exports = override(
  fixBabelImports("import", {
    libraryName: "antd",
    libraryDirectory: "es",
    style: "css",
  })
);

然後修改package.json檔案中的啟動命令scripts:

{
  "name": "demo-react",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^4.2.4",
    "@testing-library/react": "^9.3.2",
    "@testing-library/user-event": "^7.1.2",
    "antd": "^4.4.3",
    "babel-plugin-import": "^1.13.0",
    "customize-cra": "^1.0.0",
    "react": "^16.13.1",
    "react-app-rewired": "^2.1.6",
    "react-dom": "^16.13.1",
    "react-scripts": "3.4.1"
  },
  "scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test",
    "eject": "react-app-rewired eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}  

最後按需引入antd中的元件,無需再單獨引入樣式檔案,App.js:

import React from "react";
// import Button from "antd/es/button";
// import "antd/dist/antd.css";
import { Button } from "antd";

function App() {
  return (
    <div className="App">
      app
      <Button type="primary">btn</Button>
    </div>
  );
}

export default App;

antd自定義主題:需要用到less變數,可引入customize-cra中提供的less相關函式addLessLoader來幫助載入less樣式,同時修改config-overrides.js檔案:

安裝less-loader:

yarn add less [email protected]  

修改配置檔案config-overrides.js檔案:

const { override, fixBabelImports, addLessLoader } = require("customize-cra");

module.exports = override(
  fixBabelImports("import", {
    libraryName: "antd",
    libraryDirectory: "es",
    style: true,
  }),
  addLessLoader({
    javascriptEnabled: true,
    modifyVars: { "@primary-color": "red" },
  })
);  

高階元件-HOC:引數為元件,返回值為新元件的函式

 

const foo = (Cmp) => {
  return (props) => {
    return (
      <div className="border">
        <Cmp {...props} />
      </div>
    );
  };
};

// 雙箭頭函式等價於上面的雙return函式
const foo = (Cmp) => (props) => {
  return (
    <div className="border">
      <Cmp {...props} />
    </div>
  );
};
// 高階元件及鏈式呼叫:
import React, { Component } from "react";

// HOC 是個函式,接收一個元件,返回一個新的元件
function Child(props) {
  return <div>child</div>;
}
// Cmp這裡是function或class元件 雙箭頭函式
const foo = (Cmp) => (props) => {
  return (
    <div className="border">
      <Cmp {...props} />
    </div>
  );
};


const foo2 = (Cmp) => (props) => {
  return (
    <div className="border1">
      <Cmp {...props} />
    </div>
  );
};

const Foo = foo2(foo(foo(Child)));
export default class HocPage extends Component {
  render() {
    return (
      <div>
        <h3>HocPage</h3>
        <Foo />
      </div>
    );
  }
}

裝飾器:

安裝裝飾器:

npm install -D @babel/plugin-proposal-decorators  

更新config-overrides.js檔案:

const { override, fixBabelImports, addLessLoader,addDecoratorsLegacy } = require("customize-cra");

module.exports = override(
  // antd按需載入配置
  fixBabelImports("import", {
    libraryName: "antd",
    libraryDirectory: "es",
    style: true,
  }),
  //   主題樣式配置
  addLessLoader({
    javascriptEnabled: true,
    modifyVars: { "@primary-color": "red" },
  }),
  addDecoratorsLegacy() // 配置裝飾器
);  

檔案中的裝飾器寫法:

import React, { Component } from "react";

// HOC 是個函式,接收一個元件,返回一個新的元件

// Cmp這裡是function或class元件 雙箭頭函式
const foo = (Cmp) => (props) => {
  return (
    <div className="border">
      <Cmp {...props} />
    </div>
  );
};

const foo2 = (Cmp) => (props) => {
  return (
    <div className="border1">
      <Cmp {...props} />
    </div>
  );
};

@foo
@foo2
@foo
class Child extends Component {
  render() {
    return <div>child</div>;
  }
}

export default class DecoratorsPage extends Component {
  render() {
    return (
      <div>
        <h3>DecoratorsPage</h3>
        <Child />
      </div>
    );
  }
}