2017-01-07 41 views
1

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

我有一个Vue.js组件,它依赖于其父级的DOM。但是道具通过的那一刻(this.$el)未定义,可能是因为它尚未安装。

我的组件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> 

使用上面的一个包含这段代码的组件:

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

我想等待父组件是但这样我似乎无法像上面那样保留模板,因为它总是会立即尝试访问方法(或变量)。

我该如何解决这个问题?

编辑:

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

这里的父组件的模板。我唯一需要的是.article div或插槽的内容。

+0

为什么你传递'这个$ el'的道具? – Saurabh

+0

@saurabh因为我需要访问DOM元素才能执行querySelector。你会怎么做? – 22samuelk

+0

我会尝试在那里传递一个vue变量,您是否也可以添加您的父DOM的HTML,并指出您想要访问的内容。 – Saurabh

回答

0

随着@saurabh的帮助下,我才得以发现,我可以访问我传递给孩子直接插槽。

但核心问题依然存在:该组件是未安装的那一刻。

所以我改变了我怎样,我访问过插槽。

相反的父元素的,我现在通过默认插槽父组件。

由于slots prop是一个VNode对象的数组,因此我无法在它们上使用任何DOM方法。但由于VNode的elm属性包含实际的DOM元素,因此我正在使用它。

问题再次出现:它尚未安装。

这就是为什么v-for现在指向headings数据,而不是删除的方法。 相反,我添加了一个mounted()方法,它在组件挂载时自动被Vue调用。

当该方法被调用,所述槽被安装,所以可以访问他们的elm性质。在我的情况下,有多个默认插槽,因此slots阵列有多个项目。为了能够打电话给特定的querySelectorAll,我添加了一些功能Array魔法。

编辑:由于在呈现的内容上直接访问querySelector更有意义,所以我现在通过$refs属性而不是$slots。 即使我只需要$refs.article,如果我直接传递它,我会变得不确定。通过整体传递this.$refs,子组件即使在安装之前不存在,也可以访问文章引用。

所以这是我的新父组件:

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

和儿童:

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

则可以使用this.$slots,在父组件的安装功能,您可以访问this.$slots并将其分配给一些变量,它可以传递给article-index组件获得。

下面的代码打印传递插槽:

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

样品小提琴here

+0

所以我不能使用像querySelector这样的方法,对吧? – 22samuelk

+0

您可以使用'vnode.elm'访问'vnode'的HTML。 http://jsfiddle.net/mimani/hd1n41he/1/ – Saurabh

+0

'elm'未定义... – 22samuelk

相关问题