(二十六)、插槽 (slot)
1.问题探究
我们想复用一个组件,然而这个组件的各个数据是不同的。我们通过尝试发现:只能通过对复用的组件 v-show、v-if较为复杂的实现这个功能。否则不能实现
App.vue
<template> <div class="app"> <!-- 组件可以传递静态的也可以传递动态的 --> <Category title="游戏" :game_arr1="gamArr"/> <Category title="美食" :food_url1="foodURL"/> <Category/> </div> </template> <script> import Category from './components/Category.vue' export default { components:{ Category, }, data() { return { gamArr:[ {id:'001',name:'王者荣耀',price:100}, {id:'002',name:'刺激战场',price:100}, {id:'003',name:'创越火线',price:100}, {id:'004',name:'反恐精英和',price:100}, ], foodURL:'https://image.baidu.com/search/detail?ct=503316480&z=&tn=baiduimagedetail&ipn=d&word=%E7%83%A7%E7%83%A4%20200%2A100&step_word=&ie=utf-8&in=&cl=2&lm=-1&st=-1&hd=&latest=©right=&cs=3049322705,2682672783&os=365147000,2674100539&simid=3049322705,2682672783&pn=0&rn=1&di=7214885350303334401&ln=1783&fr=&fmq=1683463448132_R&ic=&s=undefined&se=&sme=&tab=0&width=&height=&face=undefined&is=0,0&istype=2&ist=&jit=&bdtype=0&spn=0&pi=0&gsm=1e&objurl=https%3A%2F%2Fview-cache.book118.com%2Fview6%2FM05%2F27%2F16%2FwKh2BGEgidOASTYzAAMVLqY5WWU809.png&rpstart=0&rpnum=0&adpicid=0&nojc=undefined&dyTabStr=MCwxLDYsMyw0LDUsMiw3LDgsOQ%3D%3D' } }, } </script> <style> .app{ width: 1000px; height: 400px; background-color: rgb(70, 193, 156); /* 横向展开 */ display: flex; /* 自适应排列 */ justify-content: space-around; } </style>
Category.vue
<template> <div class="cate"> <h3 class="t1">{{title}}分类</h3> <ul> <li v-for="ga_obj in game_arr1" :key="ga_obj.id">{{ga_obj.name}}</li> </ul> </div> </template> <script> export default { // TODO: 子组件可以接受传过来的动态数据、也可以接受动态的数据。 props:['game_arr1','title','food_url1'] } </script> <style> .cate { width:240px; height: 300px; background-color: aquamarine; } .t1 { text-align: center; } </style>
于是我们想: 这样好复杂啊。能不能直接在父组件中直接将一整个模板传递给子组件。
非自闭和标签:我们能够解析到组件中数据,但是不知道放到组件的哪个位置。所以只能弃掉!!!!
2.默认插槽
所以我们只要借助插槽就能够实现指定放的位置,然后开标签也就不会被丢弃。插槽放在哪里,就是放在哪里。
默认插槽都会接受掉…
App.vue
组件开区间
<template> <div class="app"> <!-- 组件可以传递静态的也可以传递动态的 --> <Category title="游戏"> <ul> <li v-for="ga_obj in gamArr" :key="ga_obj.id">{{ga_obj.name}}</li> </ul> </Category> <Category title="美食"> <img :src="foodURL" alt="122"> </Category> <Category title="视频"> <video controls :src="videoUL"></video> </Category> </div> </template> <script> import Category from './components/Category.vue' export default { components:{ Category, }, data() { return { gamArr:[ {id:'001',name:'王者荣耀',price:100}, {id:'002',name:'刺激战场',price:100}, {id:'003',name:'创越火线',price:100}, {id:'004',name:'反恐精英和',price:100}, ], foodURL:'https://image.baidu.com/search/detail?ct=503316480&z=&tn=baiduimagedetail&ipn=d&word=%E7%83%A7%E7%83%A4%20200%2A100&step_word=&ie=utf-8&in=&cl=2&lm=-1&st=-1&hd=&latest=©right=&cs=3049322705,2682672783&os=365147000,2674100539&simid=3049322705,2682672783&pn=0&rn=1&di=7214885350303334401&ln=1783&fr=&fmq=1683463448132_R&ic=&s=undefined&se=&sme=&tab=0&width=&height=&face=undefined&is=0,0&istype=2&ist=&jit=&bdtype=0&spn=0&pi=0&gsm=1e&objurl=https%3A%2F%2Fview-cache.book118.com%2Fview6%2FM05%2F27%2F16%2FwKh2BGEgidOASTYzAAMVLqY5WWU809.png&rpstart=0&rpnum=0&adpicid=0&nojc=undefined&dyTabStr=MCwxLDYsMyw0LDUsMiw3LDgsOQ%3D%3D', videoUL:'https://www.bilibili.com/video/BV12h4y1n7tt?t=3.5' } } } </script> <style> .app{ width: 1000px; height: 400px; background-color: rgb(70, 193, 156); /* 横向展开 */ display: flex; /* 自适应排列 */ justify-content: space-around; } video{ width: 100%; // 视频占的百分比 } </style>
Category.vue
默认插槽
<!-- 默认插槽 --> <slot></slot>
<template> <div class="cate"> <h3 class="t1">{{title}}分类</h3> <!-- 默认插槽 --> <slot></slot> </div> </template> <script> export default { // TODO: 子组件可以接受传过来的动态数据、也可以接受动态的数据。 props:['title'] } </script> <style> .cate { width:240px; height: 300px; background-color: aquamarine; } .t1 { text-align: center; } </style>
3.命名插槽
App.vue
内嵌一个template标签 <Category title="游戏"> <template slot="game"> <ul> <li v-for="ga_obj in gamArr" :key="ga_obj.id">{{ga_obj.name}}</li> </ul> </template> </Category>
<template> <div class="app"> <!-- 组件可以传递静态的也可以传递动态的 --> <Category title="游戏"> <template slot="game"> <ul> <li v-for="ga_obj in gamArr" :key="ga_obj.id">{{ga_obj.name}}</li> </ul> </template> </Category> <Category title="美食"> <template slot="food"> <img :src="foodURL" alt="122"> </template> </Category> <Category title="视频"> <template slot="vido"> <video controls :src="videoUL"></video> </template> </Category> </div> </template> <script> import Category from './components/Category.vue' export default { components:{ Category, }, data() { return { gamArr:[ {id:'001',name:'王者荣耀',price:100}, {id:'002',name:'刺激战场',price:100}, {id:'003',name:'创越火线',price:100}, {id:'004',name:'反恐精英和',price:100}, ], foodURL:'https://image.baidu.com/search/detail?ct=503316480&z=&tn=baiduimagedetail&ipn=d&word=%E7%83%A7%E7%83%A4%20200%2A100&step_word=&ie=utf-8&in=&cl=2&lm=-1&st=-1&hd=&latest=©right=&cs=3049322705,2682672783&os=365147000,2674100539&simid=3049322705,2682672783&pn=0&rn=1&di=7214885350303334401&ln=1783&fr=&fmq=1683463448132_R&ic=&s=undefined&se=&sme=&tab=0&width=&height=&face=undefined&is=0,0&istype=2&ist=&jit=&bdtype=0&spn=0&pi=0&gsm=1e&objurl=https%3A%2F%2Fview-cache.book118.com%2Fview6%2FM05%2F27%2F16%2FwKh2BGEgidOASTYzAAMVLqY5WWU809.png&rpstart=0&rpnum=0&adpicid=0&nojc=undefined&dyTabStr=MCwxLDYsMyw0LDUsMiw3LDgsOQ%3D%3D', videoUL:'https://www.bilibili.com/video/BV12h4y1n7tt?t=3.5' } } } </script> <style> .app{ width: 1000px; height: 400px; background-color: rgb(70, 193, 156); /* 横向展开 */ display: flex; /* 自适应排列 */ justify-content: space-around; } video{ width: 100%; } </style>
Category.vue
给插槽起名字,只有名字对应的插槽才能使用 <slot name="game"></slot> <slot name="food"></slot> <slot name="vido"></slot>
<template> <div class="cate"> <h3 class="t1">{{title}}分类</h3> <!-- 默认插槽 --> <slot name="game"></slot> <slot name="food"></slot> <slot name="vido"></slot> </div> </template> <script> export default { // TODO: 子组件可以接受传过来的动态数据、也可以接受动态的数据。 props:['title'] } </script> <style> .cate { width:240px; height: 300px; background-color: aquamarine; } .t1 { text-align: center; } </style>