【问题标题】:How do I get the dom node of a component in Svelte?如何在 Svelte 中获取组件的 dom 节点?
【发布时间】:2020-09-28 10:17:26
【问题描述】:

假设我渲染了以下对话框:

let dialog;

<MyDialog bind:this={dialog}/>

我想定位这个对话框(我猜是使用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

如何访问它的 dom 以定位它?

【问题讨论】:

    标签: svelte svelte-3


    【解决方案1】:

    MyDialog 不是 DOM 元素,它是一个 Svelte 组件。所以,当你在上面bind:this 时,你会得到它:一个 Svelte 组件。

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

    <div bind:this={el} />
    

    如果您需要从其使用者(父)组件访问MyDialog 的DOM,则需要从MyDialog 组件代理它。

    MyDialog.svelte

    <script>
      export let el
    </script>
    
    <div class="dialog" bind:this={el}>
      <slot />
    </div>
    

    App.svelte

    <script>
      import MyDialog from './MyDialog.svelte'
    
      let dialog
    
      $: console.log(dialog) // here, DOM element!
    </script>
    
    <MyDialog bind:el={dialog}>
      Hello!
    </MyDialog>
    

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

    编辑

    用道具移动...

    Props 是“反应性的”,它们的值由框架自动反映在 DOM 中,所以你不需要运行函数来移动东西。你可以声明你想要的。这是这些声明性框架的首选样式。

    <script>
      export let top
      export let left
    
      $: style = `top: ${top}px; left: ${left}px`
    </script>
    
    <div class="dialog" {style}>
      <slot />
    </div>
    

    如果您也需要,您仍然可以在使用 reactive blocks 更改道具时(必须)运行一些代码:

    <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>
    

    【讨论】:

    • 谢谢。你能给我一个更好的解决方案的例子吗?也许导出一个函数而不是 dom 节点?
    • 取决于你在说“位置”时真正想做的事情,但我认为我会做的可能是在 MyDialog 组件上添加类似 position 的道具,并且从那里,从内部将效果应用于 DOM 元素。这样一来,如果你的对话框组件的 DOM/CSS 发生了变化,你就只有一个集中的地方需要适应。
    • 如何通过更改要导出的道具来移动对话框(例如,使用 dom 顶部/左侧样式属性)?我看到了一个导出的函数,我可以给它一些坐标,然后我执行 Dom 操作来定位对话框;但我不明白你只导出一个道具的想法如何。当 prop 发生变化时,你如何执行 Dom 操作?
    • 一个道具可以是一个对象,一个数组...这只是一个例子,重点是通常希望在有限的 API 后面抽象出组件的内部,而不是暴露整个位它,然后当你想改变这些位时你会被卡住......我添加了一些如何使用道具移动元素的示例。
    • 伙计,如果你有的话,我只是想花你几秒钟的时间,但你给我写了一个完整的编辑。你是一个了不起的人:) 谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-06
    • 1970-01-01
    • 2010-11-30
    • 2015-11-20
    相关资源
    最近更新 更多