简体   繁体   English

如何访问另一个子组件中的插槽内容

[英]How to access content of slot in another child component

Following problem:以下问题:

I have a Vue.js component which relies on its parent's DOM.我有一个依赖于其父 DOM 的 Vue.js 组件。 But the moment the prop gets passed, it ( this.$el ) is undefined, probably because it's not yet mounted then.但是当 prop 被传递时,它( this.$el )是未定义的,可能是因为它还没有安装。

My component's vue template file looks like this:我的组件的 vue 模板文件如下所示:

<template>
  <md-card>
    <md-card-content>
      <ol>
        <li v-for="item in headings(content)">
          <a :href="`#${item.id}`">{{ item.name }}</a>
        </li>
      </ol>
    </md-card-content>
  </md-card>
</template>
<script>
  export default {
    props: ['content'],
    methods: {
      headings(content) {
        // DOM element is used
        // At this moment, `content` is undefined
      },
    },
  };
</script>

The component that uses the one above includes this piece of code:使用上述组件的组件包括以下代码:

<article-index :content="this.$el"></article-index>

I thought of waiting for the parent component to be mounted, but that way I can't seem to keep the template like above, because it would always try to access the method (or variable) instantly.我想过等待父组件被挂载,但那样我似乎无法像上面那样保留模板,因为它总是会尝试立即访问方法(或变量)。

How can I solve this?我该如何解决这个问题?

Edit:编辑:

<template>
  <div class="content">
    <div class="left"><article-index :content="this.$el"></article-index></div>
    <div class="article"><slot></slot></div>
    <div class="right"><slot name="aside"></slot></div>
  </div>
</template>

Here's the parent component's template.这是父组件的模板。 The only thing I actually need is the .article div, or the slot's contents.我唯一真正需要的是.article div,或插槽的内容。

You can get it using this.$slots , in the parent component's mount function you can access this.$slots and assign it to some variable which can be passed to article-index component.您可以使用this.$slots获取它,在父组件的挂载函数中,您可以访问this.$slots并将其分配给可以传递给article-index组件的某个变量。

Following code prints the passed slots:以下代码打印传递的插槽:

Vue.component('wrapper', {
    name: 'Wrapper',
  template: `<div><slot></slot></div>`,
  mounted () {
    this.$slots.default.forEach(vnode => { 
        console.log(vnode)
    })
  }
})

Sample fiddle here .样品小提琴在这里

With the help of @saurabh I was able to find out that I can access the slot I'm passing to the child directly.在@saurabh 的帮助下,我发现我可以直接访问我传递给孩子的插槽。

But the core problem remained: The component was not mounted at that moment.但核心问题仍然存在:当时没有安装组件。

So I changed how I'm accessing the passed slot.所以我改变了访问传递槽的方式。

Instead of the parent element, I'm now passing the default slot in the parent component.我现在在父组件中传递默认插槽,而不是父元素。

Since the slots prop is an Array of VNode objects, I cannot use any DOM methods on them.由于slot道具是一个VNode对象数组,我不能对它们使用任何 DOM 方法。 But since a VNode 's elm property contains the actual DOM element, I'm using that instead.但是由于VNode的 elm 属性包含实际的 DOM 元素,所以我使用它来代替。

Again, the problem: it's not mounted yet.同样,问题是:它还没有安装。

That's why the v-for now points to the headings data, not the method, which removed.这就是为什么v-for now 指向headings数据,而不是删除的方法。 Instead, I added a mounted() method, which automatically gets called by Vue when the components got mounted.相反,我添加了一个mount()方法,当组件被挂载时,Vue 会自动调用该方法。

When that method gets called, the slot has been mounted, so I can access their elm properties.当调用该方法时,插槽已安装,因此我可以访问它们的elm属性。 In my case, there are multiple default slots, so the slots array has more than one items.就我而言,有多个默认插槽,因此slots数组有多个项目。 To make it possible to call a specific querySelectorAll , I've added some functional Array magic.为了能够调用特定的querySelectorAll ,我添加了一些函数式数组魔法。

Edit: Since it makes more sense to directly access querySelector on the rendered content, I'm now passing the $refs attribute instead of $slots .编辑:由于直接访问渲染内容上的 querySelector 更有意义,我现在传递$refs属性而不是$slots Even though I only need $refs.article , if I pass it directly, I'll get undefined.即使我只需要$refs.article ,如果我直接传递它,我会得到未定义的。 By passing this.$refs as a whole, the child component can access the article ref even if it doesn't exist before mounting.通过将this.$refs作为一个整体传递,子组件可以访问文章 ref,即使它在挂载之前不存在。

So this is my new parent component:所以这是我的新父组件:

<template>
  <div class="content">
    <div class="left">
      <article-index :refs="this.$refs"></article-index>
    </div>
    <div class="article" ref="article"><slot></slot></div>
    <div class="right"><slot name="aside"></slot></div>
  </div>
</template>

and the child:和孩子:

<template>
  <md-card>
    <md-card-content>
      <ol>
        <li v-for="item in headings">
          <a @click="scroll(item.id)" :href="hash">
            {{ item.name }}
          </a>
        </li>
      </ol>
    </md-card-content>
  </md-card>
</template>
<script>
  import dashify from 'dashify';

  export default {
    props: ['refs'],
    data: () => ({
      headings: {},
      hash: location.hash,
    }),
    methods: {
      scroll(to) {
        this.refs.article.querySelector(`#${to}`).scrollIntoView();
      },
    },
    mounted() {
      const elements = Array.from(this.refs.article.querySelectorAll('h2'));
      elements.forEach(node => node.id = dashify(node.innerText));

      this.headings = elements.map(node => ({
        name: node.innerText,
        id: node.id,
      }));
    },
  };
</script>

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

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