序文
マルチレベルコンポーネントがネストされており、データを転送する必要がある場合、一般的に使用される方法はvuexを使用する方法です。中間処理なしでデータのみを渡す場合は、vuex処理を使用します。これは、ニワトリをやや殺します。Vueのバージョン2.4は、v-bind =” $ attrs”を使用して、親コンポーネントのpropsプロパティバインディングとは見なされない属性を子コンポーネントに渡す別のメソッドを提供し、通常はオプションinteritAttrsと一緒に使用されます。これら2つの属性に言及する理由は、2つの出現により、コンポーネント間のコンポーネント間の通信が、vuexとイベントバスに依存せずに簡潔かつビジネス上明確になるためです。
最初に、次のアプリケーションシナリオを分析します。
AコンポーネントとBコンポーネント間の通信:(父子コンポーネント)
上の図に示すように、3つのコンポーネントA、B、Cは順番にネストされています。Vueの開発習慣に従って、親子コンポーネントの通信は次の方法で実現できます。
A to Bはプロップを介してサブコンポーネントに渡され、B to AはBコンポーネントの$
エミットとAコンポーネントのv-onを介して実装されます。グローバルVuex共有状態を設定することにより、データは計算された属性とcommitミューテーションによって計算されます。親コンポーネントと子コンポーネント間の通信の目的を達成するために取得および更新します。
Vue Event Busは、Vueインスタンスを使用して、イベントを監視および公開し、コンポーネント間で通信します。
多くの場合、データがグローバルな状況を必要とせず、親子コンポーネントのみが通信する場合、最初の方法が満たされます。
AおよびCコンポーネント間の通信:(複数のレベルのコンポーネントの入れ子関係全体)
上の図に示すように、AコンポーネントとCコンポーネントは複数のレベルのコンポーネントにネストされています。以前は、2つのコンポーネント間の通信が必要な場合、以下の方法で実装されていました。
Bコンポーネントの転送では、プロップは上から下に、下から上に順に送信され、$放出イベントの送信は、レベルを超えたコンポーネント通信の効果を実現します
。Vueのグローバル状態共有
Vueイベントバスの助けを借りて、Vueインスタンスを使用してイベントを監視しますそして、リリースして、コンポーネント間の転送を実現します。
明らかに、最初のメソッドは、propsと$ emitを使用して、コンポーネント間のビジネスロジックを肥大化させ、コンポーネントBはトランジットステーションとしてのみ機能します。2番目のVuex方式を使用する場合、場合によっては少しやり過ぎに見えることがあります(データ共有の概念ではなく、コンポーネント間のデータ転送を実現するためだけ)。3番目の状況の使用は、実際のプロジェクトの運用で見られます。イベントの監視と解放の管理が達成されていない場合、データフローの混乱を招くことがよくあります。複数の人のコラボレーションプロジェクトでは、プロジェクトのメンテナンスに役立ちません。
$ attrsと$ listenersの出現は、最初のケースの問題を解決します。Bコンポーネントを通過するプロップとイベントのプロセスでは、追加のコードを記述する必要はありません。$ attrsと$ listenersを上下に渡すだけです。ええ
サンプルコードは
次のとおりです。
コンポーネント(App.vue)
<template>
<div id="app">
<child1
:p-child1="child1"
:p-child2="child2"
v-on:test1="onTest1" //此处监听了两个事件,可以在B组件或者C组件中直接触发
v-on:test2="onTest2">
</child1>
</div>
</template>
<script>
import Child1 from './Child1.vue';
export default {
data () {
return {};
},
components: { Child1 },
methods: {
onTest1 () {
console.log('test1 running...');
},
onTest2 () {
console.log('test2 running');
}
}
};
</script>
Bコンポーネント(Child1.vue)
<template>
<div class="child-1">
<p>in child1:</p>
<p>props: {{pChild1}}</p>
<p>$attrs: {{$attrs}}</p>
<hr>
<!-- C组件中能直接触发test的原因在于 B组件调用C组件时 使用 v-on 绑定了$listeners 属性 -->
<!-- 通过v-bind 绑定$attrs属性,C组件可以直接获取到A组件中传递下来的props(除了B组件中props声明的) -->
<child2 v-bind="$attrs" v-on="$listeners"></child2>
</div>
</template>
<script>
import Child2 from './Child2.vue';
export default {
props: ['pChild1'],
data () {
return {};
},
inheritAttrs: false,
components: { Child2 },
mounted () {
this.$emit('test1');
}
};
</script>
結果:
child1の場合:
小道具:v_child1
$ attrs:{「p-child2」:「v_child2」}
Cコンポーネント(Child2.vue)
<template>
<div class="child-2">
<p>in child2:</p>
<p>props: {{pChild2}}</p>
<p>$attrs: {{$attrs}}</p>
<hr>
</div>
</template>
<script>
export default {
props: ['pChild2'],
data () {
return {};
},
inheritAttrs: false,
mounted () {
this.$emit('test2');
}
};
</script>
結果:
子2の場合:
小道具:v_child2
$ attrs:{}
知識のまとめ
$ attrsに
は、親スコープで考慮されていない(および予期されていない)小道具バインディング(クラスとスタイルを除く)が含まれます。コンポーネントがプロップを宣言しない場合、コンポーネントには親スコープのすべてのバインディング(クラスとスタイルを除く)が含まれ、v-bind =” $ attrs”を介して内部コンポーネントに渡すことができます。とても便利です。
//人間の言葉:子コンポーネントにSunコンポーネントを導入し、v-bind = "$ attrs"宣言を介してpropsデータを渡します。データがprops宣言によって渡される場合、宣言されていないコンポーネントのみをSunコンポーネントで取得できますデータ
$ listeners
親スコープにv-onイベントリスナーが含まれます(.nativeデコレーターなし)。v-on =” $ listeners”を介して内部コンポーネントに渡すことができます。これは、より高レベルのコンポーネントを作成するときに非常に役立ちます。
//人間の言葉:子コンポーネントに孫コンポーネントを導入し、v-on = "$ listeners"を介して宣言します。これにより、孫コンポーネントは、親コンポーネントがリッスンするイベントを発行できます。
inheritAttrs
デフォルトでは、親スコープの小道具とは見なされない属性バインディングは「フォールバック」し、通常のHTML機能として子コンポーネントのルート要素に適用されます。ターゲット要素または別のコンポーネントをラップするコンポーネントを記述する場合、これは常に期待される動作に準拠するとは限りません。inheritAttrsをfalseに設定すると、これらのデフォルトの動作が削除されます。そして、(同じく2.4で追加された)インスタンス属性$ attrsは、これらの機能を有効にし、v-bindを介して非ルート要素に明示的にバインドできます。
//人間の言葉:私の理解では、デフォルトの親スコープはレベルを超えた転送をサポートしていないということです。子コンポーネントとグランドコンポーネントでinheritAttrs:falseを宣言することで、プロップをレベル間で転送できます
上記の機能を使用すると、Vuexとイベントバスを使用せずに、コンポーネントのクロスレベルプロップとイベント配信の複雑さを完全に軽減できます。