以下问题:
我有一个依赖于其父DOM的Vue.js组件。但是当道具通过的那一刻,它(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 :(得分:4)
您可以使用this.$slots
获取它,在父组件的mount函数中,您可以访问this.$slots
并将其分配给一些可以传递给article-index
组件的变量。
以下代码打印传递的插槽:
Vue.component('wrapper', {
name: 'Wrapper',
template: `<div><slot></slot></div>`,
mounted () {
this.$slots.default.forEach(vnode => {
console.log(vnode)
})
}
})
示例小提琴here。
答案 1 :(得分: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
作为整体,子组件可以访问文章ref,即使它在安装之前不存在。
所以这是我新的父组件:
<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>