iT邦幫忙

2022 iThome 鐵人賽

DAY 16
0
Modern Web

web component - 次世代網頁技術的重要拼圖系列 第 16

[Day15] web component 的應用-和react合作

  • 分享至 

  • xImage
  •  

因為小弟我對angularJS不熟,Vue和React倒是還算上手。

React

身為前端生態中最靈活的框架(X)函式庫(O),react 一直以來提供的都是一個目標。如何用最高效的方式,把state變成對應的渲染樹。至於渲染樹會變成什麽就沒有限制了。渲染的是HTML元素,就能使用在網頁上(react-dom);渲染的是可以轉換成原生平臺的代碼,就能使用在跨平臺上(react-native)。而web component只是一種有特別名稱的html元素,使用react-dom當然是一點問題都沒有...才怪,還是有一些要注意的地方。

react 中使用 webcomponent

以下是官網的例子,看起來很簡單吧?平時如何使用html元素,也可以用相同的手法使用web component,但真正的問題是在載入web component的地方

class HelloMessage extends React.Component {
  render() {
    return <div>Hello <x-search>{this.props.name}</x-search>!</div>;
  }
}

react 載入web component檔案

因為babel的限制,直接import web component會出問題

主檔

import './xSearch.js'

class HelloMessage extends React.Component {
  render() {
    return <div>Hello <x-search>{this.props.name}</x-search>!</div>;
  }
}

./xSearch.js

class XSearch extends HTMLElement {
  ...
}
customElements.define('x-search', XSearch);  //在使用babel時,這段會出錯

關於babel的限制

解法1

簡單的解法是,不要用babel打包就好了(廢話?)

public.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <-- 多的部分刪光光 -->
    <title>React App</title>
    <script>
class XSearch extends HTMLElement {
  ...
}
customElements.define('x-search', XSearch);  //因為放在public,所以不會使用babel
    </script>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
  </body>
</html>

解法2

因為babel會出錯,所以裝個讓babel能使用的polyfills,這也是官網給的建議

react 官網給的建議

使用web component的事件

因為react的事件都只能用在內建的元素事件上,想要使用web component的事件,就需要先綁ref,再用ref來使用事件。

const Hello = () => {
    const searchEl = useRef(null); // 使用useRef
    const handleSearch =(text) => {
        searchEl.current.mySearch(text) //使用web component的事件
    }
    render() {
    return (
    <div>Hello
        <x-search ref={searchEl}> // 要綁到ref上
            {this.props.name}
        </x-search>
    </div>)
  }
}
class XSearch extends HTMLElement {
  ...
  mySearch(text) {
      ...
  }
}

web component中使用 react

在web component中使用react也還算簡單,使用ReactDOM.createRoot把節點加到shadow DOM,再用render方法渲染react component就可以了。

當然啦,如果要使用JSX,還是要面對babel沒辦法正常使用的問題就是了。

class MyReact extends HTMLElement {
    root = null
    constructor() {
        super();
        this.root = this.attachShadow({mode: 'open'});
        this.root.appendChild(this.render())
    }
    render() {
        const root = document.createElement('div');
        const app = ReactDOM.createRoot(root);
        app.render(React.createElement('div', null, `Hello World!`))
        return root
    }
}
customElements.define('my-react', MyReact);

上一篇
[Day14] web component 的應用-和框架合作
下一篇
[Day16] web component 的應用-和Vue合作
系列文
web component - 次世代網頁技術的重要拼圖30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言