Web组件化 - 事件、属性交互
第一篇介绍了如何将React组件转换为Web Component
第二篇介绍了子应用(Web Component)中的路由可以正常作用与Shell App
本文将介绍React实现的Web Component如何与Shell App交互,包括属性、事件。
先介绍属性传递,打开index.html,为hello-component增加属性my-name
<html>
<script src='bundle.js'></script>
<body>
<hello-component my-name="Andy"></hello-component>
</body>
</html>
打开app.tsx, 修改代码如下:
App增加属性name
class HelloElement extends HTMLElement {
connectedCallback() {
const myName = this.getAttribute('my-name'); //获取html标签的属性
ReactDOM.render(
<div>
<App name={myName}></App> //将name属性传入App组件
</div>,
this
);
}
}
App组件中使用该属性
type AppProp = {
name: string;
}
function App(prop: AppProp) {
return (
<Router>
<div>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/account">Account - {prop.name}</Link>
</li>
</ul>
<hr />
<Switch>
<Route exact path="/">
<Home />
</Route>
<Route path="/about">
<About />
</Route>
<Route path="/account">
<Account />
</Route>
</Switch>
</div>
</Router>
)
}
最后执行
npm run build
node ./src/server.js
查看效果
同理,我们也可以把Shell app中定义的方法传递给Web Component
修改index.html
<html>
<script src='bundle.js'></script>
<body>
<script>
function onHelloComClick(e) {
alert(e);
}
</script>
<hello-component my-name="Andy" click='onHelloComClick'></hello-component>
</body>
</html>
修改app.tsx,这里用eval将传入的click属性从string类型转换为any,再绑定到button的onClick事件上。
class HelloElement extends HTMLElement {
connectedCallback() {
const myName = this.getAttribute('my-name');
const clickFn = eval(this.getAttribute('click'));
ReactDOM.render(
<div>
<App name={myName}></App>
<button onClick={clickFn.bind(this)}>
Click Me!
</button>
</div>,
this
);
}
}
执行npm run build, node ./src/server.js
最后,我们尝试通过自定义事件(CustomEvent)让WebComponent通知Shell App
首先index.html加入以下代码
<script>
document.addEventListener('fooEvent', e =>{
console.log('fooEvent fired');
});
</script>
为document对象添加fooEvent事件监听。
其次,app.tsx,触发document对象的fooEvent
function myClick() {
const event = new CustomEvent('fooEvent', {bubbles: true, detail: {message:'inner of web component'}});
document.dispatchEvent(event);
}
ReactDOM.render(
<div>
<App name={myName}></App>
<button onClick={myClick.bind(this)}>
Click Me!
</button>
</div>,
this
);