文章目录
7、使用插槽和具名插槽解决组件内容传递问题
通过插槽向子组件传标签
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>hello vue</title>
<!-- 引入Vue库 -->
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
const app = Vue.createApp({
data(){
return{
}
},
// slot 插槽
template: `
<div>
<myform>
<!--这是插槽里的内容-->
<div>提交</div>
</myform>
<myform>
<!--这是插槽里的内容-->
<button>提交</button>
</myform>
</div>
`
});
app.component('myform',{
methods:{
handleClick(){
alert("大哥刘备驾到!");
}
},
template: `
<div>
<input />
<!--我这里不再真正地写一个 div 或者 button 而是写一个 slot-->
<!--<button @click="handleClick">提交</button>-->
<!--注意:slot 是无法直接绑定事件的,办法是在其外包括一个 span 标签-->
<span @click="handleClick">
<slot></slot>
</span>
</div>
`
})
const vm = app.mount('#root');
</script>
</html>
运行结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ldl29con-1624975950052)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a30b74979659449aba4144113323f866~tplv-k3u1fbpfcp-watermark.image)]
除了标签还可以传递字符串、子组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>hello vue</title>
<!-- 引入Vue库 -->
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
const app = Vue.createApp({
data(){
return{
}
},
// slot 插槽
template: `
<div>
<myform>
<!--这是插槽里的内容-->
<!--<div>提交</div>-->
<!--往插槽传字符串-->
我是字符串
</myform>
<myform>
<!--这是插槽里的内容-->
<!--<button>提交</button>-->
<!--往插槽传子组件-->
<test />
</myform>
</div>
`
});
app.component('test', {
template: `
<div>Hello World!</div>
`
});
app.component('myform',{
methods:{
handleClick(){
alert("大哥刘备驾到!");
}
},
template: `
<div>
<input />
<!--我这里不再真正地写一个 div 或者 button 而是写一个 slot-->
<!--<button @click="handleClick">提交</button>-->
<!--注意:slot 是无法直接绑定事件的,办法是在其外包括一个 span 标签-->
<span @click="handleClick">
<slot></slot>
</span>
</div>
`
})
const vm = app.mount('#root');
</script>
</html>
运行结果
一些说明
插槽的作用是将子组件标签内部的内容替换子组件内部的 slot 标签,但是<button>{{message}}</button>
中的 message 所使用的仍然是父组件里面的 message!
父组件里面里面调用的数据都是父组件里面的,子组件里面里面调用的数据都是子组件里面的!
slot插槽默认内容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>hello vue</title>
<!-- 引入Vue库 -->
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
const app = Vue.createApp({
data(){
return{
}
},
// slot 插槽
template: `
<div>
<myform>
<!--这是插槽里的内容-->
<!--<div>提交</div>-->
<!--往插槽传字符串-->
我是字符串
</myform>
<myform>
<!--这是插槽里的内容-->
<!--<button>提交</button>-->
<!--往插槽传子组件-->
<test />
</myform>
<myform>
<!--插槽里的内容是空的-->
</myform>
</div>
`
});
app.component('test', {
template: `
<div>Hello World!</div>
`
});
app.component('myform',{
methods:{
handleClick(){
alert("大哥刘备驾到!");
}
},
template: `
<div>
<input />
<!--我这里不再真正地写一个 div 或者 button 而是写一个 slot-->
<!--<button @click="handleClick">提交</button>-->
<!--注意:slot 是无法直接绑定事件的,办法是在其外包括一个 span 标签-->
<span @click="handleClick">
<slot>
<!--我们写一个默认的内容-->
<button>插槽默认按钮</button>
</slot>
</span>
</div>
`
})
const vm = app.mount('#root');
</script>
</html>
运行结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JUYjUY8h-1624975950057)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6a85d549f3fa4229ac359144d90402ef~tplv-k3u1fbpfcp-watermark.image)]
多个插槽
具名插槽
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>hello vue</title>
<!-- 引入Vue库 -->
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
const app = Vue.createApp({
data(){
return{
}
},
// slot 插槽
template: `
<div>
<myform>
<!--插槽里的内容-->
<template v-slot:header>
<div>header</div>
</template>
<template v-slot:third>
<div>third</div>
</template>
<template v-slot:footer>
<div>footer</div>
</template>
</myform>
</div>
`
});
app.component('myform',{
methods:{
handleClick(){
alert("大哥刘备驾到!");
}
},
template: `
<div>
<slot name="header"></slot>
<div>
body
<slot name="third"></slot>
</div>
<slot name="footer"></slot>
</div>
`
})
const vm = app.mount('#root');
</script>
</html>
运行结果
插槽的简写
使用 # 代替 v-slot:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>hello vue</title>
<!-- 引入Vue库 -->
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
const app = Vue.createApp({
data(){
return{
}
},
// slot 插槽
template: `
<div>
<myform>
<!--插槽里的内容,使用 # 代替 v-slot: -->
<template #header>
<div>header</div>
</template>
<template #third>
<div>third</div>
</template>
<template #footer>
<div>footer</div>
</template>
</myform>
</div>
`
});
app.component('myform',{
methods:{
handleClick(){
alert("大哥刘备驾到!");
}
},
template: `
<div>
<slot name="header"></slot>
<div>
body
<slot name="third"></slot>
</div>
<slot name="footer"></slot>
</div>
`
})
const vm = app.mount('#root');
</script>
</html>
运行结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zQvpUiIc-1624975950059)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/eecdbe6705f947549beb04f6f4e04f9e~tplv-k3u1fbpfcp-watermark.image)]
作用域插槽
父组件调用子组件里面的数据(子组件将数据传递给父组件)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>hello vue</title>
<!-- 引入Vue库 -->
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
const app = Vue.createApp({
data(){
return{
}
},
// slot 插槽
template: `
<div>
<!-- 我们使用 v-slot="slotProps" 来接收子组件传来的参数-->
<list v-slot="slotProps">
<!-- span 里面需要填入 item ,但是 item 在子组件中-->
<!-- span 里面填入子组件传过来的 item -->
<li>{{slotProps.item}}</li>
</list>
</div>
`
});
app.component('list',{
data(){
return{
list: [1, 2, 3, 4]
}
},
template: `
<!--我们不一定要使用 div 来完成循环-->
<!--<div v-for="item in list">{{item}}</div>-->
<!--在子组件中我们将 item 向上从传递给父组件-->
<slot v-for="item in list" :item="item"></slot>
`
})
const vm = app.mount('#root');
</script>
</html>
运行结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UstSL82n-1624975950060)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c905ff229c314e4ba1e91c9234c118c8~tplv-k3u1fbpfcp-watermark.image)]
作用域插槽解构写法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>hello vue</title>
<!-- 引入Vue库 -->
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
const app = Vue.createApp({
data(){
return{
}
},
// slot 插槽
template: `
<div>
<!-- 我们使用 v-slot="slotProps" 来接收子组件传来的参数-->
<!-- 解构简写 -->
<list v-slot="{item}">
<!-- span 里面需要填入 item ,但是 item 在子组件中-->
<!-- span 里面填入子组件传过来的 item -->
<li>{{item}}</li>
</list>
</div>
`
});
app.component('list',{
data(){
return{
list: [1, 2, 3, 4]
}
},
template: `
<!--我们不一定要使用 div 来完成循环-->
<!--<div v-for="item in list">{{item}}</div>-->
<!--在子组件中我们将 item 向上从传递给父组件-->
<slot v-for="item in list" :item="item"></slot>
`
})
const vm = app.mount('#root');
</script>
</html>