因為小弟我對angularJS不熟,Vue和React倒是還算上手。
身為前端生態中最靈活的框架(X)函式庫(O),react 一直以來提供的都是一個目標。如何用最高效的方式,把state變成對應的渲染樹。至於渲染樹會變成什麽就沒有限制了。渲染的是HTML元素,就能使用在網頁上(react-dom);渲染的是可以轉換成原生平臺的代碼,就能使用在跨平臺上(react-native)。而web component只是一種有特別名稱的html元素,使用react-dom當然是一點問題都沒有...才怪,還是有一些要注意的地方。
以下是官網的例子,看起來很簡單吧?平時如何使用html元素,也可以用相同的手法使用web component,但真正的問題是在載入web component的地方
class HelloMessage extends React.Component {
render() {
return <div>Hello <x-search>{this.props.name}</x-search>!</div>;
}
}
因為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打包就好了(廢話?)
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>
因為babel會出錯,所以裝個讓babel能使用的polyfills,這也是官網給的建議
因為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也還算簡單,使用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);