Vue.js - 부모 <-> 슬롯 통신
향후 프로젝트에서 사용할 라이브러리를 작성하기 위해 Vue 컴포넌트의 작은 컬렉션을 작성하려고 합니다만, 이 토픽은 매우 혼란스럽습니다.전혀 다른 접근방식이 필요할지도 모르지만...
정책 패턴에서 영감을 얻고 있습니다(이렇게 부릅니다).템플릿 컴포넌트를 만듭니다.템플릿 컴포넌트의 동작은 중첩된 컴포넌트에 따라 달라집니다.예를 들어 bkg 이미지를 변경하는 메서드를 소유하는 Preview 컴포넌트를 만들고 이 메서드를 호출할 수 있는 오버레이를 이 컴포넌트에 중첩하려고 합니다.이 오버레이는 슬롯을 통해 네스트되어 있으면 좋겠다고 생각했던 모든 것이 될 수 있기 때문에:
<template>
<div class="preview" :class="{active: active}">
<div class="content">
<slot name="content"></slot>
</div>
<div class="overlay"><slot></slot></div>
</div>
</template>
(img 목록을 통해 콘텐츠를 v-for로 만듭니다.)
그리고 js:
props: {
content: {default: function () { return [] }}
},
data: function () {
return {
preview: null
}
},
methods: {
setPreview: function (e) {
this.preview = e
}
}
}
다음으로 변경 온마우스 오버를 트리거하는 하위 구성 요소가 있습니다.
<template>
<div @mouseover="set">
<slot></slot> <!-- some random content -->
</div>
</template>
<script>
export default {
props: ['target']
methods: {
set: function () {
// figure a way to call "parent" setPreview
}
}
}
</script>
그리고 이 컴포넌트를 다음과 같이 사용합니다.
<preview>
<template slot="content">... a bounch of v-if bound images</template>
<template>
<change-preview-onover target="first-img">...</change-preview-onover>
<change-preview-onclick target="second-img">...</change-preview-onclick> <!-- different policy -->
</template>
</preview>
스코프 슬롯과 제공/인젝트라는 두 가지 접근 방식을 시도했습니다.스코프 슬롯에서는 다음과 같은 결과가 나옵니다.
//preview
<template>
<div class="preview" :class="{active: active}">
<div class="content">
<slot name="content"></slot>
</div>
<div class="overlay" :callback="{setPreview}"><slot></slot></div>
</div>
</template>
//js...
//overlay element
<template>
<div @mouseover="set">
<slot></slot> <!-- some random content -->
</div>
</template>
<script>
export default {
props: ['target', 'callback']
methods: {
set: function () {
this.callback.setPreview(this.target)
}
}
}
</script>
//usage
<preview>
<template slot="content">... a bounch of v-if bound images</template>
<template slot-scope={callback}>
<change-preview-onover :callback="callback" target="first-img">...</change-preview-onover>
<change-preview-onclick :callback="callback" target="second-img">...</change-preview-onclick>
</template>
</preview>
이 방법은 캡슐화가 깨지고(사용자는 콜백의 존재를 알고 모든 변경 미리보기 컴포넌트를 통해 콜백을 전달해야 함) 많은 용장 코드를 얻을 수 있기 때문에 좋아하지 않습니다.슬롯 스코프를 오버레이 컴포넌트 안쪽으로 옮기려고 했지만 잘 되지 않았습니다.제공/주입에 대해 읽은 적이 있는데, 기본적으로 다음과 같습니다.
//preview.js
provide: function () {
return {
setPreview: this.setPreview
}
}
//overlay.js
inject: ['setPreview'],
props: ['target'],
methods: {
set: function () {
this.setPreview(this.target)
}
}
이 방법은 매우 멋있어 보이지만 제공/주입이 그렇게 되어 있는지, 아니면 어디에서나 사용해도 괜찮은지(주로 퍼포먼스를 중시하고 있습니다), 부모<->슬롯 통신을 작성하기 위해서입니다.물론 슬롯은 의미론적으로 부모에 연결되어 있습니다.
편집 1
Vue.js에는 부모 자녀의 통신을 처리하는 표준 방법이 있습니다.
단, Vue가 컴포넌트의 범위를 처리하는 방법 때문에 슬롯에서는 동작하지 않습니다.이 예에서 미리보기는 구성요소 템플릿 내에 직접 중첩되지 않으므로 중첩의 상위 항목이 아닙니다.대신 이렇게 쓰면:
<template>
<div class="preview" :class="{active: active}">
<content>...<content> <!-- changes here -->
<overlay>...</overlay> <!-- and here -->
</div>
</template>
Overlay 및 Content는 이벤트를 내보내는 Preview와 자유롭게 통신할 수 있습니다.그러나 앞서 제안했던 첫 번째 예시와 같이 throught 슬롯은 콘텐츠와 오버레이(그리고 미리보기)는 모두 일반적인 앱 콘텐츠의 자식이기 때문에 미리보기가 아니라 앱(또는 미리보기 컴포넌트를 포함하는 것)으로 전송되므로 슬롯에서 부모로 또는 그 반대로 통신하는 새로운 방법이 필요합니다.
이 주제에 대한 주요 스레드: https://github.com/vuejs/vue/issues/4332 여기에서는 scope slot (ok, 하지만 끔찍한) 또는 $parent를 사용하고 있습니다.이 슬롯은 항상 참인 것은 아니기 때문에 사용할 수 없습니다.아마도 전환이나 다른 것을 추가하여 다음과 같은 것을 얻을 수 있습니다.
//Modal
<div>
<tr-fade> <!-- tr-fade is a registered comopnent and so it's the $parent of slot -->
<slot></slot>
</tr-fade>
</div>
질문입니다.제공/주입이 이 케이스에 대한 적절한 대처방법입니까?slot-scope는 imho가 캡슐화를 해제하고 장황하게 설명하더라도 더 적합할까요?또는 슬롯이 제공하는 커스터마이즈 수준을 포기하지 않고 이 '정책 패턴'을 실현하는 다른 방법이 있습니까?
슬롯 내에 자녀의 콘텍스트를 삽입하고 다음 콘텍스트에서 이벤트를 내보낼 수 있습니다.
// the child
<template>
<div>
<slot :context="thisContext"/>
</div>
</template>
<script>
export default
{
computed:
{
thisContext()
{
return this;
}
}
}
</script>
// the parent
<template>
<child @custom_event="handleCustom">
<template slot-scope="ctx">
<button @click="sendClick(ctx)">Click me</button>
</template>
</child>
</template>
<script>
export default
{
methods:
{
sendClick(ctx)
{
ctx.$emit('custom_event', {custom_data: 3});
},
handleCustom(payload)
{
console.log("Custom payload:", payload);
}
}
}
</script>
언급URL : https://stackoverflow.com/questions/51427841/vue-js-parent-slot-communication
'programing' 카테고리의 다른 글
정적 라이브러리를 공유 라이브러리로 변환하시겠습니까? (0) | 2022.08.31 |
---|---|
vuex 저장소 데이터를 그래프에 전달할 수 없음 (0) | 2022.08.31 |
Class.newInstance()를 컨스트럭터 인수와 함께 사용할 수 있습니까? (0) | 2022.08.31 |
C의 문자열에 문자 추가? (0) | 2022.08.31 |
vuej를 사용한 다른 모바일 및 데스크톱 레이아웃 (0) | 2022.08.31 |