質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

1677閲覧

スロットプロパティには好きな名前は使えないのでしょうか?

stadmlmg

総合スコア12

Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2020/01/27 15:17

お世話になります。
現在Vue.jsを勉強中で、ドキュメントに目を通しています。
スロットの説明で理解できない部分があります。
どなたかご教示いただけると大変ありがたいです。

不明点

ガイドのスロットの章「その他の例」の説明に関してなのですが、この部分の説明は「isCompleteがtrueのタスクに関しては先頭に✓をつける」というUIの操作を、親コンポーネントから行っているケースだと解釈しています。

ここで、親コンポーネントの<template v-slot:todo="{ todo }">{ todo }の記述の部分が、同じドキュメント内でも説明のあるスロットプロパティであると認識しています。

html

1<todo-list v-bind:todos="todos"> 2 <template v-slot:todo="{ todo }"> 3 <span v-if="todo.isComplete"></span> 4 {{ todo.text }} 5 </template> 6</todo-list>

スロットプロパティの説明では

すべてのスロットプロパティを保持するオブジェクトの名前を slotProps にしましたが、あなたの好きな名前を使うことができます。

とあるので、ドキュメントのコードを動く形にし、自分の好きなスロットプロパティ名に変更してみたところ、エラーで画面が真っ白になってしまいました。
※コード内がtodoだらけでどこになんの値が反映されているのか分かりずらかったので、変更できる部分は変更してみようと思ったのが発端です

html

1<!DOCTYPE html> 2<html lang="ja"> 3<head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <meta http-equiv="X-UA-Compatible" content="ie=edge"> 7 <title>Vue Document</title> 8 <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> 9 <link href="https://use.fontawesome.com/releases/v5.6.1/css/all.css" rel="stylesheet"> 10</head> 11<body> 12 13 <div id="app"> 14 15 16 <todo-list v-bind:todos="todos"> 17 <template v-slot:todo="{ acceptAnySlotPropertyName }"><!-- スロットプロパティの名前はなんでも良いはず --> 18 <span v-if="acceptAnySlotPropertyName.isComplete"></span> 19 {{ acceptAnySlotPropertyName.text }} 20 </template> 21 </todo-list> 22 </div> 23 24 25 <script> 26 Vue.component('todo-list', { 27 data: function(){ 28 return { 29 filteredTodos: [ 30 { id: '1', text: 'ID1のテキスト', isComplete: true }, 31 { id: '2', text: 'ID2のテキスト', isComplete: false }, 32 { id: '3', text: 'ID3のテキスト', isComplete: true } 33 ] 34 } 35 }, 36 props:['todos'], 37 template: ` 38 <ul> 39 <li 40 v-for="todo in filteredTodos" 41 v-bind:key="todo.id" 42 > 43 <slot name="todo" v-bind:todo="todo"> 44 <!-- フォールバックコンテンツ --> 45 {{ todo.text }} 46 </slot> 47 </li> 48 </ul> 49 ` 50 }); 51 52 new Vue({ 53 el: '#app', 54 data: { 55 todos: [ 56 { }, 57 { }, 58 { } 59 ] 60 } 61 }) 62</script> 63</body> 64</html>

コンソールのエラー内容は下記になります。

console

1[Vue warn]: Error in render: "TypeError: Cannot read property 'isComplete' of undefined" 2 3vue.js:1897 TypeError: Cannot read property 'isComplete' of undefined 4 at fn (eval at createFunction (vue.js:11649), <anonymous>:3:194) 5 at normalized (vue.js:2597) 6 at Proxy.renderSlot (vue.js:2693) 7 at eval (eval at createFunction (vue.js:11649), <anonymous>:3:91) 8 at Proxy.renderList (vue.js:2637) 9 at Proxy.eval (eval at createFunction (vue.js:11649), <anonymous>:3:27) 10 at VueComponent.Vue._render (vue.js:3551) 11 at VueComponent.updateComponent (vue.js:4067) 12 at Watcher.get (vue.js:4478) 13 at new Watcher (vue.js:4467)

スロットプロパティの文言と小コンポーネントでバインドしている属性名を一致させると期待通りの表示になるのですが、それだと「好きな名前を使うことができます」というドキュメントの説明と一致しないため疑問に思い質問させていただきました。

そもそもの理解として間違っている部分がありましたらご指摘いただけると幸いです。
何卒よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

すべてのスロットプロパティを保持するオブジェクトの名前を slotProps にしましたが、あなたの好きな名前を使うことができます。

この部分で勘違いをされているようです。

上記の文が意味しているのは、公式ドキュメントのスコープ付きスロットの例で言うと、slotにバインドする属性の名前(v-bind:useruserの部分(1))に関係なく、受け取るオブジェクトの名前(slotProps(2))を決められるということです。

vue

1// 子コンポーネント 2<span> 3 <slot v-bind:user="user"> <!-- (1) --> 4 {{ user.lastName }} 5 </slot> 6</span>

vue

1// 親コンポーネント 2<current-user> 3 <template v-slot:default="slotProps"> <!-- (2) --> 4 {{ slotProps.user.firstName }} 5 </template> 6</current-user>

slotのuser属性にuserという値をバインディングしていますが、それを受け取った親コンポーネントでは、slotProps.userのように使用していることに注目してください。これは、userという値を渡してるように思えて、実際にはuserをプロパティに持つオブジェクトを渡しているということです。

すべてのスロットプロパティを保持するオブジェクトの名前を slotProps にしましたが、あなたの好きな名前を使うことができます。

というのは、「ラッピングするオブジェクトの名前を変えられる」と言う意味です。


ちなみに、stadmlmgさんが試したのは、オブジェクトを受け取るのではなくて、それに含まれるプロパティを、(デフォルトでは同じ名前の)変数として受け取ることです。これは、分割代入と言って、最近のJavaScript(ES2015以降)で可能になった構文です。Vue.jsのbindingのv-bind:xxx="yyy"yyyの部分は純粋なJavaScriptとして解釈されるので、こういったことが可能です。

もしかしたら、以下のようなソースコードを見たことがあるかもしれません。

javascript

1const obj = { 2 myProp: "hello" 3} 4 5// 変数myPropにはobj.myPropが代入される 6const { myProp } = obj 7 8console.log(myProp) // => hello

公式ドキュメントのslotのページにもスロットプロパティの分割代入として説明されていますので、より詳しく知りたい場合は、そちらをご覧ください。

投稿2020/01/31 16:17

編集2020/01/31 16:18
NozomuIkuta

総合スコア1260

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

stadmlmg

2020/02/01 01:11 編集

NozomuIkutaさん回答ありがとうございます。 自分が勘違いしている部分がよくわかりました。 「スロットプロパティの分割代入」のドキュメントに目を通したつもりではいたのですが、どうやらきちんと理解できておらず、今回疑問に感じたドキュメント部分でオブジェクトを渡しているものだと勘違いしておりました。 これは分割代入だったのですね。。。 きちんと分割代入を理解していれば、よく見れば自分が書いたコードがドキュメントの例と異なり、`{acceptAnySlotPropertyName}`という様に、分割代入で渡してしまっていることに気がつけた様な気がします。 オブジェクトで渡す場合も、分割代入で渡す場合も両方理解できました。 本当にありがとうございました。
NozomuIkuta

2020/02/01 03:53

解決したようでよかったです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問