slot的说明就看vue的官方文档 但是有点模糊
理解:
解决什么问题:
正常情况下,<Child><span style=”color:red;”>hello world</span></Child>在组件标签Child中的span标签会被组件模板template内容替换掉,当想让组件标签Child中内容传递给组件时需要使用slot插槽;
通俗的讲:
是“占坑”,在组件模板中占好了位置,当使用该组件标签时候,组件标签里面的内容就会自动填坑(替换组件模板中<slot>位置),当插槽也就是坑<slot name=”mySlot”>有命名时,组件标签中使用属性slot=”mySlot”的元素就会替换该对应位置内容;
例如下面使用的例子
第一次使用slot 练习的一个小例子有问题大家指正
最先编码的时候没有做到上下收缩,只能是列表式的,如下图
代码:
<p class="title" style="text-align:left;font-weight:bold">特有属性</p> <div class="param-gap"> <label class="left" for="">圆角 :</label> <div class="right"> <input class="data-value" :keep-selected="true" placeholder="请输入(上,右,下,左)" @input="updateData"/> </div> </div>
但是后面实际需要的效果是可以进行上下伸缩的,如下图
所以这样就得每一个 p元素上写成一个组件,组件里面写点击弹出下面的div,这种方式肯定可以实现,但是这里我就使用了插槽,讲需要下拉的内容通过一个参数传过去,放到对应的slot坑中
首先:
用一个组件讲下方的元素进行包裹起来 collapse-item 组件里面的内容就可以当做一个插槽
<collapse-item title="点击我进行收缩的" :isShow="true"> <div class="param-gap"> <label class="left" for="" title="线型">线型:</label> <div class="right"> <select class="data-value" name="" id=""> <option value="1">线型一</option> <option value="2">线型二</option> <option value="3">线型三</option> <option value="4">线型四</option> <option value="5">线型五</option> </select> </div> </div> </collapse-item>
CollapseItem.vue进行正常引入
import CollapseItem from './CollapseItem'
CollapseItem.vue里面的代码
<template> <div style="100%" class="testbox" :class="{'collapsed': !isActive }"> <p class="click" @click="handleHeaderClick"> <span>{{title}}</span> <i class="arrow icon iconfont icon_down"></i> </p> <div v-show="isActive"> <slot></slot> </div> </div> </template>
slot里面的最终解析出来的html就是上面collapse-item标签里面包裹的元素
效果图(点击可以上下收缩,图标切换)
最后还使用了一个动画效果,讲小图标进行旋转
注意:
下面的css 如果直接切换class 为 collapsed 的时候,会导致点击的时候图标会有动画的效果,但是再点击一下会瞬间回到初始位置,不会出现动画
.collapsed .arrow { transition: transform 0.18s ease 0s; transform: rotate(-180deg) scale(1, 0.9); }
解决办法,就是让初始的位置就进行旋转180度,把图片icon原本是down换成up,这样初始的时候看起来就和原来一样,然后再在点击的时候切换 collapsed 具体看代码
CollapseItem.vue
<template> <div style="100%" class="testbox" :class="{'collapsed': !isActive }"> <p class="click" @click="handleHeaderClick"> <span>{{title}}</span> <i class="arrow icon iconfont icon_up"></i> </p> <div v-show="isActive"> <slot></slot> </div> </div> </template> <script> export default { name: 'CollapseItem', props:{ title:String,//指定title为string类型的 isShow: { type: Boolean, default() { return true } } }, data(){ return { isActive : true } }, methods: { handleHeaderClick(){ this.isActive = !this.isActive } } } </script> <style lang="scss" scoped > .click { display: flex; justify-content: space-between; } .arrow{ transition: transform 0.18s ease 0s; transform: rotate(-180deg) scale(1, 0.9); } .collapsed .arrow { transform: rotate(0deg) scale(1, 0.9); } </style>
hutest
<template> <div class="one"> <div class="box"> <p class="box-head">这是标题</p> <div class="box-content"> <collapse-item title="点击我进行收缩的" :isShow="true"> <div class="param-gap"> <label class="left" for="" title="线型">线型:</label> <div class="right"> <select class="data-value" name="" id=""> <option value="1">线型一</option> <option value="2">线型二</option> <option value="3">线型三</option> <option value="4">线型四</option> <option value="5">线型五</option> </select> </div> </div> </collapse-item> </div> </div> </div> </template> <script> import CollapseItem from './CollapseItem' export default { name:'hutest', components: { CollapseItem }, data() { return { } }, methods: { } } </script> <style lang="scss" scoped > .param-pannel input,.param-pannel select{ border:1px solid #ddd; width:100% } .param-pannel input[type=color]{ padding:0 } .one{ position: fixed; width:100%; height:100%; display: flex; justify-content: center; align-items: center; } .box{ width:400px; height: 400px; border: 1px solid #ddd; display: flex; flex-direction: column; .box-head{ flex: 0 0 auto; background-color: pink; } .box-content{ flex:1 1 0px; background-color: #eee; display: flex; } } </style>
注意图标使用的是element ui 所以需要引入,,如果不想引入,也可以直接写字体,或者键盘的尖括号,或者小于号旋转一下,然后将选装的样式进行调一下也可以达到类似的效果
尖括号举例
.collapsed .arrow { transform: translateX(-25%) translateY(25%) rotate(0deg) scale(1, 0.9); }
效果同上图
上面所使用的插槽是默认插槽,如果没有给插槽命名,那么默认就是拿组件中的第一个子元素进行填充
需求二:如果如下图,在特有属性中需要添加一个文本内容,这个时候为了方便就需要再添加了一个插槽
代码:
Hutest.vue
<template> <div class="one"> <div class="box"> <p class="box-head">这是标题</p> <div class="box-content"> <collapse-item title="样式" :isShow="true"> <div class="param-gap"> <label class="left" for="" title="线型">线型:</label> <div class="right"> <select class="data-value" name="" id=""> <option value="1">线型一</option> <option value="2">线型二</option> <option value="3">线型三</option> <option value="4">线型四</option> <option value="5">线型五</option> </select> </div> </div> </collapse-item> <collapse-item title="特有属性" :isShow="true"> <div class="param-gap" slot="before"> <label for="" class="left">文本内容 :</label> <div class="right"> <input class="data-value" placeholder="我是特有属性自己独有的 "/> </div> </div> <div class="param-gap"> <label class="left" for="" title="线型">线型:</label> <div class="right"> <select class="data-value" name="" id=""> <option value="1">线型一</option> <option value="2">线型二</option> <option value="3">线型三</option> <option value="4">线型四</option> <option value="5">线型五</option> </select> </div> </div> </collapse-item> </div> </div> </div> </template> <script> import CollapseItem from './CollapseItem' export default { name:'hutest', components: { CollapseItem }, data() { return { } }, methods: { } } </script> <style lang="scss" scoped > .param-pannel input,.param-pannel select{ border:1px solid #ddd; width:100% } .param-pannel input[type=color]{ padding:0 } .one{ position: fixed; width:100%; height:100%; display: flex; justify-content: center; align-items: center; } .box{ width:400px; height: 400px; border: 1px solid #ddd; display: flex; flex-direction: column; .box-head{ flex: 0 0 auto; background-color: pink; } .box-content{ flex:1 1 0px; background-color: #eee; display: flex; flex-direction: column } } </style>
CollapseItem.vue
<template> <div style="100%" class="testbox" :class="{'collapsed': !isActive }"> <p class="click" @click="handleHeaderClick"> <span >{{title}}</span> <i class="arrow icon iconfont icon_up"></i> </p> <div v-show="isActive"> <slot name="before"></slot> <slot></slot> </div> </div> </template> <script> export default { name: 'CollapseItem', props:{ title:String,//指定title为string类型的 isShow: { type: Boolean, default() { return true } } }, data(){ return { isActive : true } }, methods: { handleHeaderClick(){ this.isActive = !this.isActive } } } </script> <style lang="scss" scoped > .click { display: flex; justify-content: space-between; } .arrow{ transition: transform 0.18s ease 0s; transform: rotate(-180deg) scale(1, 0.9); } .collapsed .arrow { transform: rotate(0deg) scale(1, 0.9); } </style>