v-ifやifで親コンポーネントからで子コンポーネントの表示制御を行う方法です。覚書も多少かねています。
目次
v-ifとpropsで子コンポーネントの表示制御を行う(方法1)
子コンポーネント
まず、子コンポーネントをv-ifで切り分け、親コンポーネントとデータのやりとりをするためpropsを用意しましょう、
<b-container fluid="xl"> <b-row v-if="showChildA" class="my-2 py-2"> <b-col cols="12">表示A</b-col> </b-row> <b-row v-if="showChildB" class="my-2 py-2"> <b-col cols="12">表示B</b-col> </b-row> <b-row v-if="showChildC" class="my-2 py-2"> <b-col cols="12">表示C</b-col> </b-row> </b-container>
htmlはbootstrapvueを使っているため、適時書き換えてください。
props: { showChildA: { type: Boolean, default: true }, showChildB: { type: Boolean, default: true }, showChildC: { type: Boolean, default: true } },
defaultをfalseにすると、その部分が非表示になります。
親コンポーネント
次に親コンポーネントです。
<Childcomponents :show-child-a="showA" :show-child-b="showB" :show-child-c="showC" />
ハイフンを使いなさいとwaringででたため命名はハイフンにしました。ケバフケースにします。
falseにしたものだけ消えます。
import Childcomponents from '~/components/Childcomponents.vue' export default { components: { Childcomponents }, data() { return { // 子コンポーネントの表示管理 showA: false, showB: true, showC: false } } }
propsはこちらの記事がわかりやすいです。
あとはUdemyなどで勉強しましょう。
【複数】親ページの2ヵ所から1つのファイルにある違う子コンポーネントを読み込む
レイアウトや他のコードの都合上、コンポーネントを読み込む箇所が2箇所になってしまう場合です。
子コンポーネンを以下にするだけです。親側は各々falseに設定するだけです。
<div v-if="this.$route.name === 'PageName' && this.$route.name === 'partsA '"> </div> <div v-if="this.$route.name === 'PageName' && this.$route.name === 'partsB '"> </div>
propsは配列や関数を渡す場合は注意
型だけの場合はこう。
props: { propArray: Array },
中には型を指定していないコードもありますが、基本型は指定することが多い気がします。defaultも指定しないとeslintのエラーがでるため、、結局、typeとdefaultの両方は指定することが個人的に多いですね。
関数式で表すthisとアロー関数で表すthisの乖離がむずすぎるんだがww
前者は指してるオブジェクトのまんまなんやけど
後者はグローバルオブジェクトっていうね🙄— ゆうぼう🦥ただのナマケモノ (@yubosasaki) May 4, 2020
アロー関数なので配列や関数を渡す場合は若干注意が必要です。
default: () => {}
ボタンclick時にpropでデータをゲットする
違うところは、子コンポーネントはcomputedで監視します。
emitの使い方
propsとemitの違い
コンポーネントの表示制御だけならpropsでOKです。コンポーネントからデータをセットする場合はemitが必要です。
初心者向けemitの使い方
子から親に渡すものなので子コンポーネント(componetsフォルダのファイル)に書きます。厳密には親コンポーネントのイベントを発火できるもの。
this.$emit('childEditFlag', this.isEditFlag)
ボタンクリック時に渡すみたいな使い方が多い気がします。
methods: {
send() {
this.$emit('childEditFlag', this.isEditFlag)
}
}
受け取り側はこう書きます。@はv-onです。htmlで完結する場合、代入する形です。
@childEditFlag="checkEditFlag = $event"
Javascriptに渡す場合は次のようになります。
<ChildComponent @childEditFlag="checkEditFlag"/>
methods: {
checkEditFlag(flag) {
console.log('checkEditFlag', flag)
}
}
clickイベントのような形で引数なしで渡すケース
フラグ程度であれば実際は引数を渡す必要はないでしょう。子で発火させて値を渡すのは親側のみで完結します。modalウィンドウを閉じる場合なんかに利用されます。
methods: {
closeModal() {
this.$emit('close')
}
}
<ChildComponent @close="modal('mes')"/>
初心者時代、udemyの「超Vue JS 2 入門 完全パック – もう他の教材は買わなくてOK! (Vue Router, Vuex含む)」を参考にさせてもらいました。
propsのエラー
prop must be a string
prop must be a string
コピペでうっかりエラー。Stringになっていてもdefaultがfalseになっていたためエラー。
props: {
uid: {
type: String,
default: false
}
},
↓
props: {
uid: {
type: String,
default: ''
}
},
親コンポーネントから子コンポーネント内のメソッドを発火(refs)
propsやemitの他にrefsという手法があります。
次のように親コンポーネントに書くと、簡単に子コンポーネントのcancel() を呼び出せます。
<Child ref="child" />
this.$refs.child.cancel()
$refsの他に、$parent、$rootもあります。
propsはまどろっこしく感じてしまうところもありますが、$refsのいいところはわかりやすいです。ただ、こんなツイートが。
ref
— yoshihide@ (@T_yoshihide_) May 20, 2020
refsはVue.js的にあんまりよくないらしい😱
emit
propsで書き直そう😃#プログラミング初心者 #駆け出しエンジニアと繋がりたい
今の所の解決策はpropでtrue / false 渡して
— Tsubasa Ryuto (@TsubasaRyuto) May 24, 2021
watchさせる作戦になっているが、これが正解感もないし、こんなことをしている情報も見たことがない。
実際、社内のフロントエンドエンジニアに提案したらいい反応ではなかったしなー(わかりづらいのか?)
詳しくは調べていないのですが、$refsを使うと動作がもっさりする気がします(ただ、デプロイするともっさりしませんね。。)。
stackoverflowでも議論されていますが、methodの呼び出しは意見が割れているようです。
親のページ名でif文の切り分け(方法2)
値のやりとりがない場合、親のページ名で子コンポーネントを切り分けることもできます。
htmlとjsは各々次のとおりです。こちらは記述量が少なく簡単です。実は表示と非表示の制御だけならこっちでいいかも。
<div v-if="this.$route.name === 'parentPagename'"> 親ページに表示するもの。 </div> <div v-else> その他のページに表示するもの。 </div>
if(this.$route.name === 'parentPagename'){ console.log('this.$route.name(ページ名)', this.$route.name) }
動的なページ対応はthis.$route.name.includes(‘user’)
よくありますが、userページが増えていくような動的なページがあったとしましょう。
フォルダ構造はuser/_userみたいな感じです。その場合、次の対応でいけるっぽいです。
動的に生成するページ名をどうやってひっかけるか。
— 個人開発作家 まったりんneru (@neruplan) March 3, 2022
フォルダ名が入るのでこれでいけるっぽい。思いつきなので他にも方法があるかもしれませんが(?)
v-if=”this.$route.name.includes(‘user’)”#vuejs #nuxt #プログラミング独学 #プログラミング初学者と繋がりたい #プログラミング教育 #個人開発
Twitterでもたまに簡単なことがつぶやいています。
コンポーネント設計の記事参考
よさそうな記事があったので紹介だけ。
nuxt.jsのmixinとは
mixinとはVueのデフォの機能です。VueComponentのコードを再利用する際に共通化するのがmixin。クラスを継承するような感じです。用途としては、たとえばComponentにloading.vueを用意し、ページのloading画面を共通化します。
mixinを使わなくても、injectなどの代替手段もあります。
mixiinの使い方下記の記事が参考になりました。ありがとうございます。
補足すると、data、computed、watch、created、methodsなどを共通化できます。
pagesとpluginのmixinに同じデータがあった場合、pagesのデータにマージされるので注意してください。
処理的にはmixiin、pagesの順番に呼ばれます。
注意事項としては下記があります。
ミックスインは継承ツリーを持たないため、オブジェクト指向言語の継承と違います。
mixinかコンポーネントかどちらかと言われれば、基本コンポーネント。やむ得ない事情があるときmixinを使うことがありますが、どちらかというと避ける方向性です。やむ得ないときと、ここぞというときのみに絞り使った方がよさそうです。
以下のツイートが参考になります。
持論だけど、vue.jsのmixinは一見便利そうだけど、実はカオスコードを産みやすい側面があると思う。
— ヒラッサー@ドラム、作曲担当 (@m_hirasaki1985) October 17, 2021
mixinは使わない方が良い。面倒でもそれぞれのコンポーネントでcomputedやmethodなどを定義すべき。機能を共通化したい場合は$emitで親コンポーネント、もしくはvuexのactionでする。
Nuxt.jsでPageの下にもContainer Component切ってるんだけど、子から親(Page)へemitするより直接Storeにdispatchしちゃった方が良かった😭となってる。
— suzu.4 (@suzu415) September 17, 2019
Componentのロジック共通化するよりStoreにgetterとかロジック寄せてった方が良い設計になる事が多い。
やっぱFluxは偉大だし、mixinは悪習。
:classや:styleの条件分岐
おまけです。classの条件分岐は、いろいろな方法がありまますが、三項演算子を使う場合が多くシンプルですね。
bool ? true : false;
<div :class="getData.name.includes('neru') === true ? 'bule' : 'green'">色変え</div>
あとは.bule{}と.green{}の2つのスタイルを用意すればOKです。
フッターページのトップだけ色を変えたい場合はこんなサンプルになります。
<div :class="this.$route.name === 'index' ? 'footer-top' : 'footer'">
</div>
さらに子コンポーネントだけClassを変えたい場合は三項演算子に加えて上記のpropsを使えばOKです。
:styleにも適応できます。
:style="!getData.types === true ? 'display:none;' : ''"
参考になれば幸いです。
コメント