반응형
슬롯이 있는 동적 컴포넌트
부모 컴포넌트의 동적 컴포넌트에서 명명된 슬롯을 사용하려면 어떻게 해야 합니까?
슬라이더 컴포넌트는 다음과 같은 동적 슬라이드 컴포넌트를 사용합니다.
<slider :slides="slides" />
각 슬라이드에는, 슬라이더로 사용하는 컨텐츠가 있는 슬롯이 있습니다.
<template>
<div class="slide">
<div slot="main">Slide 1 Main</div>
<div slot="meta">Slide 1 Meta</div>
</div>
</template>
슬라이더는 다음과 같은 슬롯을 사용합니다.
<template>
<div class="slider">
<div class="slider__slide" v-for="slide in slides">
<component :is="slide">
<div class="slider__slide__main">
<slot name="main" /><!-- show content from child's slot "main" -->
</div>
<div class="slider__slide__meta">
<slot name="meta" /><!-- show content from child's slot "meta" -->
</div>
</component>
</div>
</div>
</template>
그렇지만<component>
는 내부 내용을 무시하기 때문에 슬롯은 무시됩니다.
예:
https://codepen.io/anon/pen/WZjENK?editors=1010
이것이 불가능할 경우 슬라이드 컴포넌트에서 HTML 콘텐츠를 가져오는 슬라이더를 만들 수 있는 다른 방법이 있습니까?
메인/메타 섹션을 자체 구성요소로 분할하면 렌더링 기능을 비교적 쉽게 사용하여 원하는 섹션으로 분할할 수 있습니다.
console.clear()
const slide1Meta = {
template:`<div>Slide 1 Meta</div>`
}
const slide1Main = {
template: `<div>Slide 1 Main</div>`
}
const slide2Meta = {
template:`<div>Slide 2 Meta</div>`
}
const slide2Main = {
template: `<div>Slide 2 Main</div>`
}
Vue.component('slider', {
props: {
slides: {
type: Array,
required: true
}
},
render(h){
let children = this.slides.map(slide => {
let main = h('div', {class: "slider__slide__main"}, [h(slide.main)])
let meta = h('div', {class: "slider_slide_meta"}, [h(slide.meta)])
return h('div', {class: "slider__slide"}, [main, meta])
})
return h('div', {class: "slider"}, children)
}
});
new Vue({
el: '#app',
data: {
slides: [
{meta: slide1Meta, main: slide1Main},
{meta: slide1Meta, main: slide2Main}
]
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
<div id="app">
<slider :slides="slides" />
</div>
<script type="text/x-template" id="slide1-template">
<div class="slide">
<div slot="main">Slide 1 Main</div>
<div slot="meta">Slide 1 Meta</div>
</div>
</script>
<script type="text/x-template" id="slide2-template">
<div class="slide">
<div slot="main">Slide 2 Main</div>
<div slot="meta">Slide 2 Meta</div>
</div>
</script>
실제로 다이내믹 내의 슬롯component
요소가 작용합니다.저는 이 문제를 해결하기 위해 노력해왔고, 코드펜에서 패트릭 오더커의 사랑스러운 작은 예를 발견했습니다.패트릭은 그의 코드에 풍부하고 유용한 코멘트를 했고 나는 후세를 위해 여기에 말 그대로 붙인다.CodePen에서 찾을 수 있는 css를 생략했습니다.
const NoData = {
template: `<div>
This component ignores the data completely.
<p>But there are slots!</p>
<slot></slot>
<slot name="namedSlot"></slot>
</div>`
// In this component, I just ignore the props completely
}
const DefaultMessage = {
template: `<div>
This component will show the default msg: <div>{{parentData.msg}}</div>
</div>`,
// this component won't have posts like the Async Component, so we just ignore it
props: ['parentData']
}
const CustomMessage = {
template: `<div>
This component shows a custom msg: <div>{{parentData.msg}}</div>
</div>`,
// this component won't have posts like the Async Component, so we just ignore it
props: ['parentData']
}
const Async = {
template: `<div>
<h2>Posts</h2>
<p>{{parentData.msg}}</p>
<section v-if="parentData.posts.length > 0">
<ul>
<li class="postInfo" v-for="post in parentData.posts">
<div class="postInfo__title">
<strong>Title:</strong> {{post.title}}
</div>
</li>
</ul>
</section>
</div>`,
props: ['parentData']
}
/* Children should only affect parent properties via an EVENT (this.$emit) */
const ChangeMessage = {
template: `<div>
<p>Type here to change the message from the child component via an event.</p>
<div><input type="text" v-model="message" @input="updateDateParentMessage" /></div>
</div>`,
data() {
return {
// initialize our message with the prop from the parent.
message: this.parentData.msg ? this.parentData.msg : ''
}
},
props: ['parentData'],
/* Need to watch parentData.msg if we want to continue
to update this.message when the parent updates the msg */
watch: {
'parentData.msg': function (msg) {
this.message = msg
}
},
methods: {
updateDateParentMessage() {
this.$emit('messageChanged', this.message)
}
}
};
const Home = {
template: `<section>
<div class="wrap">
<div class="right">
<p><strong>Change the current component's message from the Home (parent) component:</strong></p>
<div><input type="text" v-model="dataForChild.msg" /></div>
<p><strong>Important!</strong> We do not change these props from the child components. You must use events for this.</p>
</div>
</div>
<div class="controls">
<button @click="activateComponent('NoData')">No Data</button>
<button @click="activateComponent('DefaultMessage')">DefaultMessage</button>
<button @click="activateComponent('CustomMessage', {posts: [], msg: 'This is component two'})">CustomMessage</button>
<button @click="getPosts">Async First</button>
<button @click="activateComponent('ChangeMessage', {msg: 'This message will be changed'})">Change Msg from Child</button>
<button @click="deactivateComponent">Clear</button>
</div>
<div class="wrap">
<div class="right">
<h2>Current Component - {{currentComponent ? currentComponent : 'None'}}</h2>
<!-- ATTN: Uncomment the keep-alive component to see what happens
when you change the message in ChangeMessage component and toggle
back and forth from another component. -->
<!-- <keep-alive> -->
<component
:is="currentComponent"
:parentData="dataForChild"
v-on:messageChanged="updateMessage">
<div class="slotData">This is a default slot</div>
<div slot="namedSlot" class="namedSlot">This is a NAMED slot</div>
<div slot="namedSlot" class="namedSlot"><p>Here we pass in the message via a slot rather than as a prop:</p>{{dataForChild.msg}}</div>
</component>
<!-- </keep-alive> -->
</div>
</div>
</section>`,
data() {
return {
currentComponent: false,
/* You don't NEED to put msg and posts here, but
I prefer it. It helps me keep track of what info
my dynamic components need. */
dataForChild: {
// All components:
msg: '',
// Async Component only
posts: []
}
}
},
methods: {
/**
* Set the current component and the data it requires
*
* @param {string} component The name of the component
* @param {object} data The data object that will be passed to the child component
*/
activateComponent(component, data = { posts: [], msg: 'This is a default msg.'}) {
this.dataForChild = data;
this.currentComponent = component;
},
deactivateComponent() {
this.dataForChild.msg = '';
this.currentComponent = false;
},
/* Hold off on loading the component until some async data is retrieved */
getPosts() {
axios.get('https://codepen.io/patrickodacre/pen/WOEXOX.js').then( resp => {
const posts = resp.data.slice(0, 10) // get first 10 posts only.
// activate the component ONLY when we have our results
this.activateComponent('Async', {posts, msg: `Here are your posts.`})
})
},
/**
* Update the message from the child
*
* @listens event:messageChanged
* @param {string} newMessage The new message from the child component
*/
updateMessage(newMessage) {
this.dataForChild.msg = newMessage
}
},
// must wire up your child components here
components: {
NoData,
CustomMessage,
DefaultMessage,
Async,
ChangeMessage
}
}
const routes = [
{ path: '/', name: 'home', component: Home}
];
const router = new VueRouter({
routes
});
const app = new Vue({
router
}).$mount("#app")
html,
<div id="app">
<h1>Vue.js Dynamic Components with Props, Events, Slots and Keep Alive</h1>
<p>Each button loads a different component, dynamically.</p>
<p>In the Home component, you may uncomment the 'keep-alive' component to see how things change with the 'ChangeMessage' component.</p>
<nav class="mainNav"></nav>
<!-- route outlet -->
<!-- component matched by the route will render here -->
<section class="mainBody">
<router-view></router-view>
</section>
</div>
언급URL : https://stackoverflow.com/questions/46465325/dynamic-components-with-slots
반응형
'source' 카테고리의 다른 글
Spring Rest Template - 요청/응답의 완전한 디버깅/로그를 활성화하려면 어떻게 해야 합니까? (0) | 2022.08.18 |
---|---|
화면 크기를 확대하기 위해 Vuetify 그리드 열 너비를 줄이는 방법 (0) | 2022.08.18 |
페이지 새로 고침 후 쿠키 저장소가 있는 Vuex 상태가 손실됨 (0) | 2022.08.18 |
전원 오퍼레이터(^)가 작동하지 않는 이유는 무엇입니까? (0) | 2022.08.18 |
Java 코멘트에서의 /** 및 /* (0) | 2022.08.18 |