是否可以将函数传递给stencilJs
组件?
就像是:
@Prop() okFunc: () => void;
我有一个模态,并希望Ok
在模态页脚中单击的按钮上动态调用传递的函数,就像onClick
在普通 HTML 按钮上一样。
是否可以将函数传递给stencilJs
组件?
就像是:
@Prop() okFunc: () => void;
我有一个模态,并希望Ok
在模态页脚中单击的按钮上动态调用传递的函数,就像onClick
在普通 HTML 按钮上一样。
是的你可以。这只是一个正常的@Prop()
声明,在 TSX 中表现得非常好。然而...
如另一个答案和评论中所述,如果您正在使用纯 ol' HTML 中的 Stencil 组件,您将无法使用 Stencil 的属性-道具绑定将函数(或任何非标量值)通过HTML 属性。
这意味着如果您想附加事件或将函数道具传递给 Stencil 组件,则必须与 DOM 交互。一旦您的组件进入 DOM,与任何其他自定义元素相比,它实际上并没有什么特别之处。
如果没有 JSX 或其他模板 DSL(例如 Angular),您将需要附加事件并使用 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 文档中执行此操作:
<my-stencil-component ... >...</my-stencil-component>
<script>
var componentInstance = document.currentScript.previousElementSibling
componentInstance.someFunc = function(...) { ... }
</script>
认识到这一点很重要Properties ≠ Attributes
。Props 是JavaScript Properties,在这种情况下,是表示元素的 DOM 对象的属性。属性是 XML 属性,尽管 HTML 属性具有一些独特的特性并且行为与典型的 XML 略有不同。
Stencil 会在可能的情况下为您自动将 HTML 属性“绑定”到属性 - 特别是对于标量值 ( boolean
, number
, string
)。对象引用和函数不能用作属性的值。从技术上讲,只有string
s 可以是属性值,但 Stencil 足够聪明,可以string
在boolean
您number
指定@Prop()
.
我为我的团队开发了一个解决方案,使用MutationObserver
. 它基本上监视一个特殊的属性bind-json
,然后将属性以开头映射json-
到相应的 camelCase DOM 属性。用法如下所示:
<my-stencil-component
bind-json
json-prop-name='{ "key": "value" }'>
</my-stencil-component>
MutationObserver
就位后,这与以下内容相同:
const componentInstance = document.querySelector('my-stencil-component')
componentInstance.propName = JSON.parse(componentInstance.getAttribute('json-prop-name'))
然而,在纯 HTML中绑定函数确实没有令人满意的解决方案。eval
如果没有另一条评论中描述的某种丑陋的黑客攻击,它真的是无法完成的。这不仅会污染你的组件的 API,而且由于我不会在这里讨论的各种其他原因,它的使用会在几乎任何现代安全检查中自动使你的应用程序失败。
在我们的 Storybook 故事中,我们将回调函数定义绑定到window
, 并使用<script>
标签和document.currentScript
/querySelector
将函数道具和事件绑定传递给组件实例:
const MyStory = ({ ... }) => {
window.myStoryFunc = () => { ... }
window.myStoryClickHandler = () => { ... }
return `
<my-stencil-component ... >...</my-stencil-component>
<script>
const componentInstance = document.currentScript.previousElementSibling
componentInstance.someFunc = window.myStoryFunc
componentInstance.addEventListener('click', window.myStoryClickHandler)
</script>
`
}
您可以将 a 添加@Prop() someFunc: Function
到任何组件并从外部传递它,例如
<any-component someFunc={() => console.log('coming from the outside')} />
在 anyComponent 中只需检查if (this.someFunc) { this.someFunc() }