vue親コンポーネントとサブコンポーネント間のパスprops
22201 ワード
親コンポーネント
import ConditionQuery from '@/views/financial/settlement-data-query/ConditionQuery';
import FileQuery from '@/views/financial/settlement-data-query/FileQuery';
import ChannelRange from '@/views/financial/settlement-data-query/ChannelRange';
import PushBizRange from '@/views/financial/settlement-data-query/PushBizRange';
import CountryRange from '@/views/financial/settlement-data-query/CountryRange';
export default {
components: {
ConditionQuery,
FileQuery,
ChannelRange,
PushBizRange,
CountryRange
}
}
<condition-query
v-if="formData.type === 1"
:tracks.sync="formData.searchData.tracks"
:albums.sync="formData.searchData.albums"
:artists.sync="formData.searchData.artists"
:cp-orgs.sync="formData.searchData.cpOrgs"
:labels.sync="formData.searchData.labels"
:is-can-edit="isCanEdit"
/>
<file-query
v-if="formData.type === 2"
:is-can-edit="isCanEdit"
:file-data.sync="formData.fileData"
/>
<push-biz-range
:push-biz-match-type="formData.searchRangeData.pushBizMatchType"
:push-bizs.sync="formData.searchRangeData.pushBizs"
:is-can-edit="isCanEdit"
@change="v => pushBizsChange(v)"
/>
場合によっては、propを「双方向バインド」する必要がある場合があります.残念なことに、真の双方向バインドは、サブコンポーネントが親コンポーネントを変更でき、親コンポーネントと子コンポーネントに明らかな変更ソースがないため、メンテナンス上の問題をもたらします.これもupdate:myPropNameのモードでイベントをトリガーすることをお勧めします.たとえば、title propを含む仮定のコンポーネントでは、
this.$emit('update:title', newTitle);
の新しい値を付与する意図を、親コンポーネントがそのイベントを傍受し、必要に応じてローカルのデータ属性を更新することができる方法で表すことができる.
便宜上、このパターンの略語を提供する.sync修飾子:
これはvueの公式ドキュメントの説明で、意味は実はです.sync修飾子は略語にすぎませんv-bind:title.sync=「doc.title」は、v-on:update:title=「doc.title=$event」に相当します.1つのオブジェクトで複数のpropを同時に設定場合、これも可能である.sync修飾子とv-bindの組み合わせ:
はdocオブジェクトの各属性(titleなど)を独立したpropとして転送し、更新用のv-onリスナーをそれぞれ追加します.v-bind.syncはv-bindのような字面量のオブジェクトに使用される.sync=「{title:doc.title}」は、このような複雑な式を解析する際に考慮すべきエッジが多いため、正常に動作しません.こんなにたくさん敷かれているので、サブアセンブリを見てみましょう.サブアセンブリは、まず、PushBizRange、CountryRangeを例に挙げたサブアセンブリを見る.<script>
export default {
props: {
pushBizMatchType: {
type: Number,
default: 1
},
pushBizs: {
type: Array,
default: () => []
},
isCanEdit: {
type: Boolean,
default: true
}
}
}
</script>
computed: {
value: {
get() {
return this.pushBizs;
},
set(v) {
this.$emit('change', v);
}
}
}
this.$emit('change', v); change , $emit change 。
, , change
change , pushBizsChange
@change="v => pushBizsChange(v)
pushBizsChange , formData.searchRangeData.pushBizs
pushBizsChange(v) {
this.formData.searchRangeData.pushBizs = v;
}
:
import LabelSearch from './LabelSearch';
export default {
components: {
SongSearch,
AbulmSearch,
ArtistSearch,
AuthrizationSearch,
LabelSearch,
CheckTrack
}
}
<label-search :labels.sync="labels" :is-can-edit="isCanEdit" @change="v => change(v, 'update:labels')" />
prop
:
export default {
props: {
labels: {
type: Array,
default: () => []
},
isCanEdit: {
type: Boolean,
default: true
}
}
}
:
computed: {
value: {
get() {
return this.labels;
},
set(v) {
this.$emit('change', v);
}
}
}
:
<el-select
v-model="value"
multiple
value-key="id"
filterable
:multiple-limit="1"
remote
:remote-method="remote"
:loading="remoteLoading"
style="width: 100%;"
popper-class="popper"
:disabled="!isCanEdit"
:placeholder="$t('financial.settlementQuery.inputlabelWords')"
@visible-change="changeSize"
@focus="changeSize"
>
<el-option v-for="item in remoteOptions" :key="item.id" :label="item.name" :value="item" class="r-el-option">
<span class="r-el-option_title">{{ item.name }}</span>
<br />
<span class="r-el-option_content">
<template v-if="item.id">
<label>id:</label>
<span style="margin-right:10px;">{{ item.id }}</span>
</template>
</span>
</el-option>
</el-select>
computed ,
set(v) {
// change 。
this.$emit('change', v);
}
: @change="v => change(v, 'update:labels')"
change change , 'update:labels'
change(v, ev) {
this.$emit(ev, v);
}
。