ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# 无缝焦点图 :-: ![](https://img.kancloud.cn/0a/a3/0aa36db21dc6a5531028d343c58d3a04_1201x462.png) ## 基本结构和样式 ``` <style> * {margin: 0;padding: 0; list-style: none;border: none;} .banner { width: 1200px; height: 460px; margin: 100px auto; position: relative; overflow: hidden;} .banner ul { position: absolute; left: 0; top: 0; width: 9999999px; height: 100%;} .banner ul li { float: left;} .banner ol { width: 100%; height: 12px; position: absolute;left: 0; bottom: 10px;text-align: center;} .banner ol li { width: 12px; height: 12px; background: pink; display: inline-block; vertical-align: top; border-radius: 6px; box-shadow: 0 0 3px; cursor: pointer;margin: 0 3px;} .banner .left,.banner .right{ width: 30px; height: 50px; position: absolute;top: 50%; margin-top: -25px;font-family: "黑体"; font-size: 30px; background: rgba(0,0,0,0.3); color: #fff; text-align: center; line-height: 50px; cursor: pointer;} .banner .left{left: 0;} .banner .right{right: 0;} </style> <div id="app"> <div class="banner"> <ul> <li><img src="./images/01.png" alt=""></li> <li><img src="./images/02.jpg" alt=""></li> <li><img src="./images/03.jpg" alt=""></li> <li><img src="./images/04.jpg" alt=""></li> </ul> <ol> <li></li><li></li><li></li><li></li> </ol> <div class="control"> <span class="left">&lt;</span> <span class="right">&gt;</span> </div> </div> </div> ``` ## 普通组件化 > 整个banner会将其做为一个组件。 ~~~ <div id="app"> <banner :data="banner"></banner> </div> <script src="js/vue.js"></script> <script> Vue.component('banner', { props:['data'], template: ` <div class="banner"> <ul> <li v-for="(item,index) in data"><img :src="item" alt=""> </ul> <ol> <li></li><li></li><li></li><li></li> </ol> <div class="control"> <span class="left">&lt;</span> <span class="right">&gt;</span> </div> </div>` }) var vm = new Vue({ el: "#app", data: { banner: ['./images/01.png', './images/02.jpg', './images/03.jpg', './images/04.jpg',] } }) </script> ~~~ ## 无缝实现 >[success] 其实就是将最后一张图,复制最后一下拿到第一张前面。我们在vue中制作时,是不操作dom的,而是希望操作数据。 ``` Vue.component('banner', { props:['data'], computed:{ image(){ var last = this.data[this.data.length-1] return [last].concat(this.data) } }, template: ` <div class="banner"> <ul> <li v-for="(item,index) in image"><img :src="item" alt=""></li> </ul> <ol> <li></li><li></li><li></li><li></li> </ol> <div class="control"> <span class="left">&lt;</span> <span class="right">&gt;</span> </div> </div>` }) ``` >[success] 我们要对外面传递的`data`进行修改一下。利用计算属性,将数组中的最后一项拷贝一份,然后再通过数组拼接形成`[4,1,2,3,4]`来完成。 ## 插槽 >[warning] 组件的作用是为了**封装:解耦、高内聚**,组件书写完毕后,尽可能的不再修改组件,那么如果组件内部的结构如`banner` 我们除了有图片之外我们还希望它有文本。 > 例如:**在首页焦点图,不仅有图片还有文本描述,在详情页我只要图片,而且仅有图片的这种用的比较多**!!如何实现这种组件? ``` <div id="app"> <banner :data="banner"> <img :src="item" alt=""> </banner> </div> <script src="js/vue.js"></script> <script> Vue.component('banner', { props:['data'], computed:{ image(){ var last = this.data[this.data.length-1] return [last].concat(this.data) } }, template: ` <div class="banner"> <ul> <li v-for="(item,index) in image"> <slot> <img :src="item" alt=""> </slot> </li> </ul> …… ` }) </script> ``` 代码改造成上面。我们来看一下产生的错误 ``` vue.js:584 [Vue warn]: Property or method "item" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property ``` >[warning] 原因是因为父组件 `<banner :data="banner"><img :src="item" alt=""> </banner>` 它处在编译作用域中,此时`item` 在实例中不存在这个数据。所以会报错。 >[success] 这个数据其实是子组件的数据,那么子组件来影响父组件插槽的数据,如何实现,在这里使用`作用域插槽` 就可以完美解决这个问题。 ~~~ <div id="app"> <banner :data="banner"> <template slot-scope="abc"> <img :src="abc.item" alt=""> </template> </banner> </div> <script src="js/vue.js"></script> <script> Vue.component('banner', { ……, template: ` <div class="banner"> <ul> <li v-for="(item,index) in image"> <slot :item="item"> <img :src="item" alt=""> </slot> </li> </ul> ……` }) var vm = new Vue({ el: "#app", data: { banner: ['./images/01.png', './images/02.jpg', './images/03.jpg', './images/04.jpg'] } }) </script> ~~~ ## 体验改造后的无缝焦点图组件 ``` .banner ul li { float: left;position: relative;} .banner ul li p{position: absolute; left: 0;bottom: 30px; width: 100%; height: 30px; background: #fff;} ``` ``` <banner :data="banner"> <template slot-scope="abc"> <img :src="abc.item" alt=""> </template> </banner> <banner :data="banner"> <template slot-scope="abc"> <img :src="abc.item" alt=""> <p>这是说明文本</p> </template> </banner> ``` ![](https://img.kancloud.cn/89/a5/89a5e1a339beaa78a9c819d0df7da0b9_965x820.png) ## 总结 至此组件化章节已经全部完成。