简体   繁体   English

Stencil:通过 DOM 从另一个组件调用公共方法

[英]Stencil: call public method from another component via the DOM

I have a Stencil sidebar component with a refresh() method.我有一个带有refresh()方法的 Stencil 侧边栏组件。 I've exposed it with @Method() :我用@Method()暴露了它:

@Method() async refresh() { ... }

and I can call it from my app:我可以从我的应用程序中调用它:

const sidebar = document.querySelector('my-sidebar');
await sidebar.refresh();

However, I also have a popup component which is generated ad-hoc by the app via a separate API, and I want to make a button in the popup trigger the sidebar's refresh() .但是,我还有一个弹出组件,它是由应用程序通过单独的 API 临时生成的,我想在弹出窗口中创建一个按钮来触发侧边栏的refresh() I've set the method as a Prop on the popup:我已将该方法设置为弹出窗口中的Prop

@Prop() refresh: Function;

and I've set the Prop in the app code as a reference to the method:并且我在应用程序代码中设置了 Prop 作为对该方法的引用:

popup.refresh = sidebar.refresh;

...but when I try to execute it I get an error: ...但是当我尝试执行它时,我得到一个错误:

Uncaught (in promise) TypeError: ref.$lazyInstance$[memberName] is not a function

How can I get the popup to see the sidebar's method?如何让弹出窗口查看侧边栏的方法?

If you look at the value of sidebar.refresh in your app when you're trying to assign that Prop, you'll see something like this:如果您在尝试分配该 Prop 时查看应用程序中sidebar.refresh的值,您会看到如下内容:

value(...args) {
  const ref = getHostRef(this);
  return ref.$onInstancePromise$.then(() => ref.$lazyInstance$[memberName](...args));
}

Stencil components are lazy-loaded by generating proxies with references pointing to methods, so you're just passing a reference to a proxy. Stencil 组件通过生成带有指向方法的引用的代理来延迟加载,因此您只需将引用传递给代理。 The easiest way to fix this is to make a function which explicitly calls the method, forcing its hydration.解决此问题的最简单方法是创建一个 function 显式调用该方法,强制其水合。 (If the source component is not already hydrated, you'll need to wait for that first by using its lifecycle methods.) (如果源组件尚未水合,则需要先使用其生命周期方法等待。)

Here's what that would look like in your app:这是您的应用程序中的样子:

popup.refresh = () => sidebar.refresh();

// or, passing any arguments:
popup.refresh = args => sidebar.refresh(args);

You can also do it in your popup component:您也可以在弹出组件中执行此操作:

async popupRefresh() {
  let sidebar = document.querySelector('my-sidebar');
  await sidebar.refresh();
}

If calling the method from inside another component in this way, you may see the TypeScript error Property 'refresh' does not exist on type 'Element'.如果以这种方式从另一个组件内部调用该方法,您可能会看到 TypeScript 错误Property 'refresh' does not exist on type 'Element'.

To avoid this, import the sidebar component into your popup component:为避免这种情况,请将侧边栏组件导入您的弹出组件:

import { mySidebar } from 'stencil';

Then, use it as the type:然后,将其用作类型:

let sidebar: mySidebar = document.querySelector('my-sidebar');

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM