将函数传递给模板组件 [英] Pass functions to stencil component

查看:26
本文介绍了将函数传递给模板组件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以将函数传递给 stencilJs 组件?

Is it possible to pass a function to a stencilJs component?

类似于:

@Prop() okFunc: () => void;

我有一个模态,想在模态页脚中点击的 Ok 按钮上动态调用传递的函数,就像普通 HTML 按钮上的 onClick 一样.>

I have a modal and want to dynamically call a passed function on the Ok button clicked in the modal footer, like an onClick on a normal HTML button.

推荐答案

是的,你可以.它只是一个普通的 @Prop() 声明并且在 TSX 中表现得非常好.不过……

Yes, you can. It is just a normal @Prop() declaration and plays very nicely in TSX. However...

如另一个答案和评论中所述,如果您使用纯 ol' HTML 中的 Stencil 组件,您将无法使用 Stencil 的属性属性绑定将函数(或任何非标量值)传递给通过 HTML 属性 prop.

As noted in another answer and comments, if you are consuming a Stencil component in plain ol' HTML, you will not be able to use Stencil's attribute-prop binding to pass a function (or any non-scalar value) to a prop via an HTML attribute.

这意味着如果你想附加事件或将函数道具传递给 Stencil 组件,你必须与 DOM 交互.一旦您的组件进入 DOM,与任何其他自定义元素相比,它真的没有什么特别之处.

This means that you have to interact with the DOM if you want to attach events or pass function props to Stencil components. Once your component makes it into the DOM, there is really nothing special about it compared to any other Custom Element.

如果没有 JSX 或其他模板 DSL(例如 Angular),您将需要附加事件并使用 JavaScript DOM API 设置您的函数或对象引用道具:

Without JSX or another template DSL (e.g. Angular), you will need to attach events and set your function- or object-reference props with the JavaScript DOM API:

const componentInstance = document.querySelector('my-stencil-component')

// This works and will trigger a rerender (as expected for a prop change)
componentInstance.someFunc = (...) => { ... }

// This works for any event, including custom events fired from Stencil's EventEmitter
componentInstance.addEventListener('myCustomEvent', (event: MyCustomEvent) => { ... })

如果您出于某种原因绝对必须在 HTML 文档中执行此操作:

If you absolutely must do this in your HTML document for some reason:

<my-stencil-component ... >...</my-stencil-component>
<script>
  var componentInstance = document.currentScript.previousElementSibling
  componentInstance.someFunc = function(...) { ... }
</script>


为什么我必须这样做?

认识到属性≠属性很重要.道具是 JavaScript 属性,在本例中,是 DOM 的属性表示元素的对象.属性 是 XML 属性,尽管 HTML 属性有一些独特的特征并且表现得略有不同不同于典型的 XML.


Why do I have to do this?

It's important to realize that Properties ≠ Attributes. Props are JavaScript Properties, in this case, properties of the DOM object representing an element. Attributes are XML attributes, although HTML attributes have some unique characteristics and behave slightly differently than typical XML.

Stencil 会自动绑定"在可能的情况下为您的属性设置 HTML 属性 - 特别是对于标量值(booleannumberstring).对象引用和函数不能用作属性的值.从技术上讲,只有 string 可以是属性值,但是 Stencil 足够智能,可以将 string 转换为其他另一种标量类型(booleannumber) 当您指定 @Prop() 的类型时.

Stencil will automatically "bind" HTML attributes to properties for you where possible - in particular, for scalar values (boolean, number, string). Object references, and therefore functions, cannot be used as the value of an attribute. Technically, only strings can be attribute values, but Stencil is smart enough to convert string to other another scalar type (boolean or number) when you specify the type of your @Prop().

我为我的团队开发了一个解决方案,使用 MutationObserver 将包含 JSON 的属性绑定到 Stencil 属性.它基本上监视一个特殊的属性 bind-json,然后将以 json- 开头的属性映射到相应的驼峰 DOM 属性上.用法如下所示:

I developed a solution for my team to bind attributes containing JSON to Stencil properties using a MutationObserver. It basically watches for a special attribute bind-json, then maps attributes starting with json- onto the corresponding camelCase DOM properties. Usage looks like this:

<my-stencil-component
  bind-json
  json-prop-name='{ "key": "value" }'>
</my-stencil-component>

使用 MutationObserver 后,这等同于:

With the MutationObserver in place, this is identical to:

const componentInstance = document.querySelector('my-stencil-component')
componentInstance.propName = JSON.parse(componentInstance.getAttribute('json-prop-name'))

然而,在纯 HTML 中绑定 函数 确实没有令人满意的解决方案.如果没有其他评论中描述的诸如 eval 之类的丑陋黑客,它真的无法完成.这不仅会污染您的组件的 API,而且会因为 各种其他原因而造成问题'进入这里,它的使用将自动使您的应用在几乎所有现代安全检查中失败.

However, there really is not a satisfying solution for binding functions in plain HTML. It really just can't be done without some sort of ugly hack like eval described in another comment. Not only does that pollute your component's API, it's problematic for all kinds of other reasons I won't get into here and its use will automatically fail your app in practically any modern security check.

在我们的 Storybook 故事中,我们将回调函数定义绑定到 window,并使用

登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆