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

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

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

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

Q&A

解決済

3回答

277閲覧

コンポーネントをJSファイルにする方法

SystemAjisai

総合スコア171

Vue.js

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

0グッド

1クリップ

投稿2018/12/27 05:45

前提・実現したいこと

Vueの単一ファイルコンポーネント(.vueという名前のファイル)で、データを検索した結果を表で表示するコンポーネントを作成しました(Gridコンポーネントとします)
コンポーネント自体は完成したのですが、使える形にできなくて苦戦しています。

コンポーネントに渡すデータは各画面で違うのでコンポーネントの外に検索処理を置きたいです。
↓こういうイメージです。

html

1<body> 2<div id="element"> 3 <button @click="search">検索</button> 4 <grid :list="list"></grid> 5</div> 6 : 7 : 8</body> 9<!-- ↓作ったコンポーネント --> 10<script type="text/javascript" src="(パス)/grid.js" ></script> 11<script> 12new Vue({ 13 el:'#element', 14 components:{ 15 Grid 16 }, 17 data(){ 18 return { 19 list:[], 20 } 21 }, 22 methods:{ 23 search(){ 24 // サーバーの検索処理を呼出す実装 25 this.list = 検索結果 26 }, 27 } 28}); 29</script>

以前は単一ファイルコンポーネントではなく、jsファイルに全部コンポーネントを書いていました。
この場合は上記のように読み込んで使えていました。

javascript

1// jsファイルに全部書くバージョンのコンポーネント 2var Grid = { 3 template: "<div> ・・・・", 4 props: { list:Object,} 5 : 6 : 7}

単一コンポーネントのビルド結果をこういう風な形にできればいいと思うのですが、その場合のエントリーポイントの書き方がわかりません。
ネットで調べてみても後述のような書き方ばかり出てくるのですが、そもそも私が目指しているようなことは不可能なのでしょうか?
ご存知の方がいらっしゃいましたら助けてください!

現在のソースコード

■エントリーポイントのjsファイル

javascript

1import Vue from 'vue'; 2import Vuex from 'vuex'; 3import store from './js/store' 4import Grid from './js/components/Grid'; 5 6new Vue({ 7 el: '#grid', 8 store, 9 components:{ 10 Grid 11 }, 12});

■使用する側

html

1<body> 2 <div id="grid"> 3 <grid></grid> 4 </div> 5</body> 6<!-- ↓作ったコンポーネント --> 7<script type="text/javascript" src="(パス)/grid.js" ></script>

表は表示されて必要な機能は動いているのですが、gridコンポーネントにデータを渡そうにも既にnew Vue()がエントリーポイントの中にいるので、どうやって<grid></grid>にデータを渡せばいいのかわからない状態です…。

試していること

今はエントリーポイントのjsの中に検索処理を書く方法を取っています。
このコンポーネントを使用したい画面が今のところ16画面あり、今後も増える予定です。
16個エントリーポイント作って、「本当にこんなことするんだろうか・・・」と不安になってきました…。

config

1const path = require('path'); 2const { VueLoaderPlugin } = require("vue-loader"); 3const setPath = function(folderName) { 4 return path.join(__dirname, folderName); 5} 6module.exports = { 7 mode: 'production', 8 devtool: 'source-map', 9 entry: { 10  // ↓画面それぞれの検索処理を呼出したエントリーポイント 11 "screen1" : "./src/screen1.js", 12 "screen2" : "./src/screen2.js", 13 "screen3" : "./src/screen3.js", 14 "screen4" : "./src/screen4.js", 15 "screen5" : "./src/screen5.js", 16 "screen6" : "./src/screen6.js", 17 "screen7" : "./src/screen7.js", 18 : 19 : 20 }, 21 output: { 22 path: setPath('/dist'), 23 filename: "[name].js", 24 }, 25 : 26 :

補足情報(FW/ツールのバージョンなど)

vue: 2.5.17
webpack:4.25.1

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

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

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

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

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

guest

回答3

0

自己解決

全然質問した方法とは違いますが、自分なりに納得したのでクローズします。

結局「試してみたこと」の通りエントリーポイントを画面ごとに分ける方法でやることにしました。
開発を進めていくうちにGridコンポーネント以外にも細々と違いが出てきてしまったので、各画面の<script></script>の中に個別の処理を書くのとエントリーポイントを分けるのと大差ないし、それだったらちゃんとjsファイルの中にjavascriptが書かれている方がいいのでは?というのが納得した要因です。

エントリーポイントを分ける方法で「本当にこれでいいのか?」という思いが拭えなかった要因の一つに、
バンドルされたファイルが全部5メガ以上になっている、というものがありました。
5Mの原因はライブラリ(Vueとか)で、これを分けてバンドルすることができました。

■webpack.config.js

js

1module.exports = { 2 : 3 : 4 optimization:{ 5 splitChunks: { 6 name: 'lib', 7 chunks: 'initial', 8 } 9 }, 10 : 11}

これで各エントリーポイント共通で読まれているライブラリがlibファイルとしてバンドルされるので、画面間でもキャッシュされるそうです。
(体感できるほど早くなった気がしないので気にする程のことでもなかったのかもしれませんが…)

別件でVueを使ったライブラリというのを初めてつかったのですが、コンポーネントとして読み込んで使えました。
なので元々私がやりたかった「コンポーネントの形でビルドできる?」というのも近しいことができるんじゃないかと思っているのですが、ライブラリの読解が進まず試せていません。
もしうまくいったら追記します。

投稿2019/01/08 03:09

SystemAjisai

総合スコア171

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

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

0

エントリーポイントのVueインスタンスにtemplateを追加し、そこに<grid></grid>とすればいいのでは?

javascript

1import Vue from 'vue'; 2import Grid from './js/components/Grid'; 3 4new Vue({ 5 template: ` 6 <grid :list="list"></grid>`, 7 el: '#grid', 8 components:{ 9 Grid 10 }, 11 data(){ 12 return { 13 list:[], 14 } 15 }, 16 methods:{ 17 search(){ 18 // サーバーの検索処理を呼出す実装 19 this.list = 検索結果 20 }, 21 } 22});

投稿2019/01/08 02:14

7Kreuz

総合スコア112

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

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

SystemAjisai

2019/01/08 02:31

すみません、回答を読んだんですがよくわかりませんでした…。 「前提・実現したいこと」に記載の通り、求めているのは「コンポーネントに渡すデータは各画面で違うのでコンポーネントの外に検索処理を置きたい」ということです。 ご指摘の方法を試そうとしたのですが、結局search()を各画面個別にするためにエントリーポイントを各画面分記載することになって「試してみたこと」と同じことになってしまって、よくわからなくなってしまいました。 理解力が無くてすみません…。
guest

0

たしか、マウント対象にpropによる情報渡しはできなかったかと……
それを試された結果できなかったのでこの質問がついてるものと思いますのでそれを前提にどうしたらいいかを提案しますね。
(私もVueを勉強中なのでもっといい解決策あるかもですが…

まずは現状どうなっているのかの説明。

javascript

1new Vue({ 2 el: '#grid', 3 store, 4 components:{ 5 Grid 6 }, 7});

これでid="grid"の要素がGridコンポーネントにマウントされますよね。

つまり

HTML

1<body> 2 <div id="grid"> 3 <grid></grid> 4 </div> 5</body>

ここの<grid></grid>にpropによる情報渡しを試みても無意味なのは、
マウントによってid="grid"の要素自体が上書きされるからです。
なので、マウント時の情報渡しは諦めましょう。

どうすればいいかっていうと、

↓こういうイメージです。

と書かれたHTMLを単一コンポーネントとして用意し、それを現状のエントリーポイントから利用させましょう。

マウントとは……

HTML

1 <div id="grid"> 2 </div>

これに

javascript

1new Vue({ 2 el: '#grid', 3});

これが流し込まれるのをマウントといいます。

javascript

1new Vue({ 2 router, 3 store 4}).$mount('#app')

こうとも書けます。

投稿2019/01/08 01:15

HillTop

総合スコア22

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

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

SystemAjisai

2019/01/08 02:17

回答ありがとうございます。 分かりにくい質問になってしまいましたが、本文記載の通りGridコンポーネントを使用する画面ごとにデータ検索の処理が違うので、データ検索をコンポーネントの外に出したいというのが事の発端です。 「↓こういうイメージです。」のところを単一コンポーネント化すると、結局使用する画面数分コンポーネントを作成することになったうえに、それら全部をエントリーポイントで読み込まなければいけなくなります。 それであれば、試してみたことに記載の通りエントリーポイントを分けた方がファイルサイズ的にいいかと…。 gridにpropsが渡せないという話ですが、試してみたら渡せました。 たぶん私が「どうやって<grid></grid>にデータを渡せばいいのかわからない状態です」と書いたのが誤解の元だと思うのですが、私は検索結果をgridコンポーネントに渡すという前提で、エントリーポイントのjs内で既にVueのインスタンスが生成されているので、各画面個別の検索処理をどこに書いてどうVueインスタンス内に渡して、gridコンポーネントに渡せばいいのかがわからない、という意味で書きました。 検索結果を渡すということに固執しなければ、例えば検索処理のurlだけpropsで渡すという手もありましたね…。 実のところ、別の要因でエントリーポイントを分ける方法で行こうと思っていたのですが、あわよくば私の求めるビルド?バンドル?方法の回答が付かないかなーと質問を放置していたのが悪かったです…。 わざわざ読んでいただいて申し訳ありません。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問