# 無縫焦點圖
:-: 
## 基本結構和樣式
```
<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"><</span>
<span class="right">></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"><</span>
<span class="right">></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"><</span>
<span class="right">></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>
```

## 總結
至此組件化章節已經全部完成。