\
take a component
<component-name></component-name>
in html <a>ssfs</a>
like this we can write in betewen ending and starting tag <component-name>name</compoinent-name>
thats called slot
slots is a defailt html tag and it represents placeholder in the compoinetn tree
with attribut emethod
<app-button
name="vamsi"
></app-button>
<template>
<button>{{name}}</button>
</template>
<script>
export default {
name: 'App Button',
props:{
name:{
type: String,
required: true,
},
},
with html mehtod
<app-slot-button
>press me</app-slot-button>
<template>
<button><slot></slot></button>
</template>
<app-slot-button
@click="log"
const log = () =>{
console.log('works');
};
component
<template>
<button v-on="$listeners"><slot></slot></button>
</template>
<script>
export default {
name: 'App Slot Button',
props:{
},
components: {
},
data() {
return {
};
},
mounted(){
},
computed: {
},
methods:{
},
};
</script>
<app-slot-button
>press me</app-slot-button>
named slots
multiple slots in components
named slots
<app-layout
>
<template v-slot:header>slots are awesome </template>
<template v-slot:main>slots are main </template>
<app-slot-button
@click="log"
>press me</app-slot-button>
<template v-slot:footer>slots are footer </template>
</app-layout>
import AppSlotButton from '../../components/AppSlotButton.vue';
import AppLayout from '../../components/AppLayout.vue';
const log = () =>{
console.log('works');
};
<template>
<button>
<slot></slot></button>
</template>
<script>
export default {
name: 'App Slot Button',
props:{
},
components: {
},
data() {
return {
};
},
mounted(){
},
computed: {
},
methods:{
},
};
</script>
<template>
<header> <slot name="header" /></header>
<main> <slot name="main" /> </main>
<footer> <slot name="footer" /> </footer>
<button>
<slot></slot></button>
</template>
<script>
export default {
name: 'App Layout',
props:{
},
components: {
},
data() {
return {
};
},
mounted(){
},
computed: {
},
methods:{
},
};
</script>
short hand for named slots
<app-layout
>
<template #header>slots are awesome </template>
<template #main>slots are main </template>
<app-slot-button
@click="log"
>press me</app-slot-button>
<template #footer>slots are footer </template>
</app-layout>
passing data to parent component using scoped slot
attribute bound to slot elements that are alled slot props
<slot name="footer" :item="item" />
Refactor User List Component Using Slots
falll back content to slots
user.location.country
nesting slotsslot with condition
if slot not required we wil l not call that slot
in some components
with count
pass data to parent compoent
app.vue
https://github.com/vueschool/reusable-vuejs-components-with-slots
s
app.vue
<template>
<div class="page">
<select v-model="selected">
<option
v-for="option in options"
:value="option.value"
:key="option.value">
{{option.label}}
</option>
</select>
<AppUserList >
<template #secondrow="slotProps">{{slotProps}}</template>
<template #loading>
<b-spinner class="align-middle"></b-spinner>
</template>
</AppUserList>
</div>
</template>
<script>
import AppUserList from "../../components/AppUserListThree";
import AppUserCardsList from "../../components/AppUserCardsList";
export default {
components: {
AppUserList,
AppUserCardsList
},
data() {
return {
selected: 'first',
options: [
{ value: 'first', label: 'first name'},
{ value: 'last', label: 'last name'},
{ value: 'full', label: 'fullname'},
{ value: 'fullWithTitle', label: 'fullname with title'},
]
}
},
methods: {
getEmail(user) {
return user.email;
}
}
};
</script>
<style>
.page {
padding: 2rem;
}
.page > * + * {
margin-top: 2rem;
}
</style>
appuserlist.vue
<template>
<section>
<slot name="title">Users</slot>
<slot
name="userlist"
:count="data.results.length"
:list="data.results"
:remove="remove"
v-if="state === 'loaded'"
>
<ul class="userlist">
<li v-for="item in data.results" :key="item.email">
<slot name="listitem" :user="item">
<div>
<img
width="48"
height="48"
:src="item.picture.large"
:alt="item.name.first + ' ' + item.name.last"
/>
<div>
<div>{{ item.name.first }}</div>
<slot name="secondrow" :item="item"></slot>
<!-- {{secondrow(item)}} -->
</div>
</div>
</slot>
</li>
</ul>
</slot>
<slot v-else name="loading">
loading...
</slot>
<slot v-if="state === 'failed'" name="error">
Oops, something went wrong.
</slot>
</section>
</template>
<script>
const states = {
idle: "idle",
loading: "loading",
loaded: "loaded",
failed: "failed"
};
export default {
props: {
secondrow: {
type: Function,
default: () => {}
}
},
data() {
return {
state: "idle",
data: undefined,
error: undefined,
states
};
},
mounted() {
this.load();
},
methods: {
async load() {
this.state = "loading";
this.error = undefined;
this.data = undefined;
try {
setTimeout(async () => {
const response = await fetch("https://randomuser.me/api/?results=5");
const json = await response.json();
this.state = "loaded";
this.data = json;
return response;
}, 1000);
} catch (error) {
this.state = "failed";
this.error = error;
return error;
}
},
remove(item) {
this.data.results = this.data.results.filter(entry => entry.email !== item.email)
}
}
};
</script>
<style scoped>
.userlist {
margin: 10px;
}
.userlist img {
border-radius: 50%;
margin-right: 1rem;
}
.userlist li + li {
margin-top: 10px;
}
.userlist li > div {
display: flex;
align-items: center;
}
.userlist li div div {
flex: 1;
}
</style>
<template #listitem="{user}">
{{user}}
</template>
<slot name="listitem" :user="item">
<div>
<img
width="48"
height="48"
:src="item.picture.large"
:alt="item.name.first + ' ' + item.name.last"
/>
<div>
<div>{{ item.name.first }}</div>
<slot name="secondrow" :item="item"></slot>
<!-- {{secondrow(item)}} -->
</div>
</div>
</slot>
<template #userlist="{list, count}">
{{count}}
{{list}}
</template>
<slot
name="userlist"
:count="data.results.length"
:list="data.results"
:remove="remove"
v-if="state === 'loaded'"
>
<ul class="userlist">
<li v-for="item in data.results" :key="item.email">
<slot name="listitem" :user="item">
<div>
<img
width="48"
height="48"
:src="item.picture.large"
:alt="item.name.first + ' ' + item.name.last"
/>
<div>
<div>{{ item.name.first }}</div>
<slot name="secondrow" :item="item"></slot>
<!-- {{secondrow(item)}} -->
</div>
</div>
</slot>
</li>
</ul>
</slot>
<template #userlist="{list, count}">
{{count}}
<AppUserCardsList :list="list"/>
</template>
<template #secondrow="{remove, item:user}">
<button @click="remove(user)">{{user.name.first}}<button>
</template>
remove the user
<template #secondrow="{remove, item:user}">
<button @click="remove(user)">{{user.name.first}}</button>
</template>
<slot name="secondrow" :item="item" :remove="remove"></slot>
remove(item) {
this.data.results = this.data.results.filter(entry => entry.email !== item.email)
}
========
s
No comments:
Post a Comment