2017-01-07 14 views
1

のスロットのコンテンツにアクセスするには:はどのように問題に続いて別の子コンポーネント

私は、その親の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> 

1は、上記のコードのこの部分を含んで使用するコンポーネント:私はあることを親コンポーネントを待っていると考え

<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 execute querySelectorを実行するには、DOM要素にアクセスする必要があるためです。どうしますか? – 22samuelk

+0

私はそこにvue変数を渡そうとしますが、親DOMのHTMLも追加して、アクセスしたいものが何であるかを指摘できます。私はあなたがタイトルを編集した参照@saurabh – Saurabh

答えて

0

@saurabhの助けを借りて、私は子供に直接通っているスロットにアクセスできることが分かりました。

しかし、コアの問題が残っていました。コンポーネントがその時点でマウントされていませんでした。

私はどのように私が渡されたスロットにアクセスしている変更しました。

親要素の代わりに、親コンポーネントのデフォルトスロットを渡しています。

slots小道具はVNodeオブジェクトの配列なので、私はDOMメソッドを使用できません。しかしVNodeのelmプロパティには実際のDOM要素が含まれているので、代わりにその要素を使用しています。

もう一度、問題:まだマウントされていません。

これは、v-forが今やheadingsデータを指しているので、削除されたメソッドではありません。 代わりに、コンポーネントがマウントされたときにVueによって自動的に呼び出されるmounted()メソッドを追加しました。

このメソッドが呼び出されると、スロットがマウントされているので、そのプロパティのelmにアクセスできます。私の場合、複数のデフォルトスロットがあるので、slotsアレイには複数の項目があります。特定のquerySelectorAllを呼び出すことができるように、私はいくつかの機能を追加しましたArray魔法。

編集:レンダリングされたコンテンツのquerySelectorに直接アクセスする方が意味があるため、$slotsの代わりに$refs属性を渡しています。 私は$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> 
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

関連する問題