如何在 Svelte 中获取组件的 dom 节点?

use*_*322 4 svelte svelte-3

假设我呈现以下对话框:

let dialog;

<MyDialog bind:this={dialog}/>
Run Code Online (Sandbox Code Playgroud)

我想定位这个对话框(afterUpdate我猜是使用生命周期函数)。但是,dialog不是 dom 元素。当我记录它时,它看起来像:

MyDialog {$$: {…}, left: 785, $set: ƒ, $capture_state: ƒ, $inject_state: ƒ}
$$: {fragment: {…}, ctx: Array(1), props: {…}, update: ƒ, not_equal: ƒ, …}
$capture_state: () => {…}
$inject_state: $$props => {…}
$set: $$props => {…}
someExportedProp: (...)
__proto__: SvelteComponentDev
Run Code Online (Sandbox Code Playgroud)

我怎样才能访问它的 dom 以定位它?

rix*_*ixo 11

MyDialog不是 DOM 元素,它是一个 Svelte 组件。因此,这就是您bind:this使用它时所得到的:Svelte 组件。

当绑定到一个实际元素时,你只会得到一个 DOM 元素:

<div bind:this={el} />
Run Code Online (Sandbox Code Playgroud)

如果您需要MyDialog从其消费者(父)组件访问 DOM ,则需要从该MyDialog组件代理它。

MyDialog.svelte

<script>
  export let el
</script>

<div class="dialog" bind:this={el}>
  <slot />
</div>
Run Code Online (Sandbox Code Playgroud)

App.svelte

<script>
  import MyDialog from './MyDialog.svelte'

  let dialog

  $: console.log(dialog) // here, DOM element!
</script>

<MyDialog bind:el={dialog}>
  Hello!
</MyDialog>
Run Code Online (Sandbox Code Playgroud)

话虽如此,在将 DOM 元素泄漏到组件之外之前,我会三思而后行。它有点打破封装,这通常最终使您的生活变得复杂......也许您可以想到一个更好的解决方案来控制您的对话位置,而无需让消费者直接访问组件的内部?

编辑

用道具移动...

props 是“reactive”的,它们的值会被框架自动反映在 DOM 中,所以你不需要运行一个函数来移动东西。你可以只声明你想要的。这是这些声明式框架的首选样式。

<script>
  export let top
  export let left

  $: style = `top: ${top}px; left: ${left}px`
</script>

<div class="dialog" {style}>
  <slot />
</div>
Run Code Online (Sandbox Code Playgroud)

如果你也需要,你仍然可以在 props 改变(必须)时运行一些代码,反应块

<script>
  export let top
  export let left

  let el

  // reactive block will rerun each time el, top, or left changes
  $: if (el) {
    el.style.top = top + 'px'
    el.style.left = left + 'px'
  }
</script>

<div class="dialog" bind:this={el}>
  <slot />
</div>
Run Code Online (Sandbox Code Playgroud)

  • 一个 prop 可以是一个对象、一个数组……这只是一个例子,重点是通常需要在有限的 API 后面抽象组件的内部,而不是暴露它的全部部分,然后你就可以了当您想要更改这些位时卡住了...我添加了一些如何使用道具移动元素的示例。 (2认同)