溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

React遠(yuǎn)程動(dòng)態(tài)組件怎么實(shí)現(xiàn)

發(fā)布時(shí)間:2023-03-27 14:25:21 來(lái)源:億速云 閱讀:148 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要介紹了React遠(yuǎn)程動(dòng)態(tài)組件怎么實(shí)現(xiàn)的相關(guān)知識(shí),內(nèi)容詳細(xì)易懂,操作簡(jiǎn)單快捷,具有一定借鑒價(jià)值,相信大家閱讀完這篇React遠(yuǎn)程動(dòng)態(tài)組件怎么實(shí)現(xiàn)文章都會(huì)有所收獲,下面我們一起來(lái)看看吧。

    遠(yuǎn)程動(dòng)態(tài)組件實(shí)現(xiàn)

    遠(yuǎn)程動(dòng)態(tài)組件庫(kù)

    遠(yuǎn)程動(dòng)態(tài)組件庫(kù)項(xiàng)目結(jié)構(gòu)如下所示:

    .
    ├── babel.config.js
    ├── package.json
    ├── rollup.config.js
    └── src
        ├── Button.js
        ├── Text.js

    我們簡(jiǎn)單實(shí)現(xiàn)了兩個(gè)組件 ButtonText

    import React from 'react'
    export default ({children}) => {
      return <button style={{color: 'blue'}}>{children}</button>
    }
    import React from 'react'
    export default ({children}) => {
      return <span style={{color: 'blue'}}>{children}</span>
    }

    我們使用 rollup 對(duì)其進(jìn)行打包,之所以用 rollup 是因?yàn)槠浯虬鰜?lái)的代碼非常簡(jiǎn)潔,方便我們查看,rollup 配置為:

    import babel from 'rollup-plugin-babel'
    import fs from 'fs'
    const components = fs.readdirSync('./src')
    export default components.map((filename) => {
      return {
        input: `./src/${filename}`,
        output: {
          file: `dist/${filename}`,
          format: 'cjs',
        },
        plugins: [babel()],
      }
    })

    打包后的結(jié)果如下所示:

    .
    ├── dist
    │   └── Button.js
    │   └── Text.js

    其中 Button.js 如下所示:

    'use strict'
    var React = require('react')
    function _interopDefaultLegacy(e) {
      return e && typeof e === 'object' && 'default' in e ? e : {default: e}
    }
    var React__default = /*#__PURE__*/ _interopDefaultLegacy(React)
    var Button = function (_ref) {
      var children = _ref.children
      return /*#__PURE__*/ React__default['default'].createElement(
        'button',
        {
          style: {
            color: 'blue',
          },
        },
        children
      )
    }
    module.exports = Button

    然后我們使用 http-server 在 dist 目錄下開啟一個(gè)靜態(tài)文件服務(wù),則可以通過(guò) http://localhost:8080/Button.js 獲取到打包后的代碼。

    遠(yuǎn)程組件庫(kù)介紹完畢,接下來(lái)介紹業(yè)務(wù)項(xiàng)目中如何使用。

    接入遠(yuǎn)程組件庫(kù)

    我們使用 create-react-app 創(chuàng)建一個(gè) React 應(yīng)用,并新增一個(gè) DynamicComponent 組件:

    const DynamicComponent = ({name, children, ...props}) => {
      const Component = useMemo(() => {
        return React.lazy(async () => fetchComponent(name))
      }, [name])
      return (
        <Suspense
          fallback={
            <div style={{alignItems: 'center', justifyContent: 'center', flex: 1}}>
              <span style={{fontSize: 50}}>Loading...</span>
            </div>
          }>
          <Component {...props}>{children}</Component>
        </Suspense>
      )
    }
    export default React.memo(DynamicComponent)

    這里使用到了 React 中的 Suspense 組件和 React.lazy 方法,關(guān)于他們的用法這里不做過(guò)多解釋,整個(gè) DynamicComponent 組件的含義是遠(yuǎn)程加載目標(biāo)組件,這個(gè)過(guò)程該組件會(huì)渲染傳入 Suspense 參數(shù) fallback 之中的內(nèi)容,最后會(huì)使用加載成功的組件進(jìn)行替換。接下來(lái)看看 fetchComponent 是如何實(shí)現(xiàn)的:

    const fetchComponent = async (name) => {
      const text = await fetch(
        `http://127.0.0.1:8080/${name}.js?ts=${Date.now()}`
      ).then((a) => {
        if (!a.ok) {
          throw new Error('Network response was not ok')
        }
        return a.text()
      })
      const module = getParsedModule(text, name)
      return {default: module.exports}
    }

    該方法會(huì)發(fā)起網(wǎng)絡(luò)請(qǐng)求得到組件的代碼,并交給 getParsedModule 去解析,最后得到模塊返回。我們來(lái)看一下 getParsedModule 是怎么實(shí)現(xiàn)的:

    const packages = {
      react: React,
    }
    const getParsedModule = (code) => {
      let module = {
        exports: {},
      }
      const require = (name) => {
        return packages[name]
      }
      Function('require, exports, module', code)(require, module.exports, module)
      return module
    }

    這里使用 Function 來(lái)運(yùn)行傳入的代碼,因?yàn)榇虬h(yuǎn)程組件的時(shí)候并沒有將 react 庫(kù)打包進(jìn)去,所以這里需要實(shí)現(xiàn) require 這個(gè)方法。

    我們結(jié)合之前打包得到的 Button.js 來(lái)看這段代碼,它其實(shí)同下面這個(gè)代碼是等價(jià)的:

    const packages = {
      react: React,
    }
    const getParsedModule = (code, moduleName) => {
      let module = {
        exports: {},
      }
      const require = (name) => {
        return packages[name]
      }
      ;((require, exports, module) => {
        'use strict'
        var React = require('react')
        function _interopDefaultLegacy(e) {
          return e && typeof e === 'object' && 'default' in e ? e : {default: e}
        }
        var React__default = /*#__PURE__*/ _interopDefaultLegacy(React)
        var Button = function (_ref) {
          var children = _ref.children
          return /*#__PURE__*/ React__default['default'].createElement(
            'button',
            {
              style: {
                color: 'blue',
              },
            },
            children
          )
        }
        module.exports = Button
      })(require, module.exports, module)
      return module
    }

    最后我們可以按照如下方式來(lái)使用 DynamicComponent 組件:

    import DynamicComponent from './DynamicComponent'
    function App() {
      return (
        <div>
          <DynamicComponent name='Button'>Click Me</DynamicComponent>
          <DynamicComponent name='Text'>Remote Component</DynamicComponent>
        </div>
      )
    }
    export default App

    現(xiàn)在我們嘗試修改遠(yuǎn)程動(dòng)態(tài)組件庫(kù)中的組件,重新打包后就可以馬上看到修改后的效果了。

    關(guān)于“React遠(yuǎn)程動(dòng)態(tài)組件怎么實(shí)現(xiàn)”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對(duì)“React遠(yuǎn)程動(dòng)態(tài)組件怎么實(shí)現(xiàn)”知識(shí)都有一定的了解,大家如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。

    向AI問(wèn)一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI