最初始的swiper组件封装:
<body>
<div id="box">
<swiper></swiper>
</div>
<script>
Vue.component("swiper", {
template: `
<div class="swiper">
<div class="swiper-wrapper">
<div class="swiper-slide">11111</div>
<div class="swiper-slide">22222</div>
<div class="swiper-slide">33333</div>
</div>
<div class="swiper-pagination"></div>
</div>
`,
mounted(){
new Swiper(".swiper", {
loop: true, // 循环模式选项
// 如果需要分页器
pagination: {
el: '.swiper-pagination',
}
})
}
})
new Vue({
el: "#box",
data: {
}
})
</script>
</body>
但是这样的问题是:
他人想根据需求创建自己的dom, 也就是想把下面的111,222内容换掉,轮播自己的东西;
<div class="swiper-slide">11111</div>
<div class="swiper-slide">22222</div>
<div class="swiper-slide">33333</div>
那我们就可以在 “<div class="swiper-wrapper">”中间插上插槽slot,让别人插上自己的想轮播的东西:
<div id="box">
<swiper>
<div class="swiper-slide">11111</div>
<div class="swiper-slide">22222</div>
<div class="swiper-slide">33333</div>
</swiper>
</div>
template: `
<div class="swiper">
<div class="swiper-wrapper">
<slot></slot>
</div>
<div class="swiper-pagination"></div>
</div>
`,
但是这样做也是有问题的,这样做的话,我们就把 “class="swiper-slide"”组件内部的东西暴露在外面了;
解决办法是:把别人想插入的dom,封装到组件里:
<div id="box">
<swiper>
<swiper-item>11111</swiper-item>
<swiper-item>22222</swiper-item>
<swiper-item>33333</swiper-item>
</swiper>
</div>
Vue.component("swiperItem",{
template:`
<div class="swiper-slide">
<slot></slot>
</div>
`
})
这样就很不错了。
dom结构按照上面封装组件就可以了,不过在mounted中定义swiper,解决不了异步问题:
所以接下来我们看看:异步从后端请求数据的写法:
<body>
<div id="box">
<swiper :key="datalist.length">
<swiper-item v-for="data in datalist">
<img :src="data" alt="">
</swiper-item>
</swiper>
</div>
<script>
Vue.component("swiperItem",{
template:`
<div class="swiper-slide">
<slot></slot>
</div>
`
})
Vue.component("swiper", {
template: `
<div class="swiper">
<div class="swiper-wrapper">
<slot></slot>
</div>
<div class="swiper-pagination"></div>
</div>
`,
mounted(){
new Swiper(".swiper", {
loop: true, // 循环模式选项
// 如果需要分页器
pagination: {
el: '.swiper-pagination',
}
})
}
})
new Vue({
el: "#box",
data: {
datalist:[]
},
mounted() {
//ajax请求回来的数据
setTimeout(() => {
//后端的返回的数据用数组接收
this.datalist = ["https://static.maizuo.com/pc/v5/usr/movie/e856bdc65507b99800f22e47801fa781.jpg",
"https://p0.pipi.cn/mmdb/25bfd6ddb53c7e5015d23c5bc24d876c03d41.jpg?imageView2/1/w/160/h/220",
"https://p0.pipi.cn/mmdb/25bfd692ddd7e13139313954ee2938728ad6a.jpg?imageView2/1/w/160/h/220"]
}, 2000)
},
})
</script>
</body>
注意点:
在子组件swiper中用mounted会出现定义swiper过早的问题,但是用updated的话会出现别的状态更新也会再执行swiper初始化的过程,会出现bug;
所以相比较下来还是使用mounted,因为它只会执行一次;
mounted(){
new Swiper(".swiper", {
loop: true, // 循环模式选项
// 如果需要分页器
pagination: {
el: '.swiper-pagination',
}
})
}
那怎么解决定义swiper过早的问题:
有两种办法:
(1)swiper组件调用时增加:“ :key="datalist.length" ”;
<swiper :key="datalist.length">
原因是:刚开始因为异步还没拿到datalist的值,所以datalist.length=0,组件执行一遍,不能用;
后面当异步执行完,拿到datalist的值,datalist.length不等于0,因为状态更新了,而且发现和上一局一样,还是datalist.length,所以把上面创建的组件销毁了,新创建了swiper组件,这时候已经拿到异步数据了,再执行swiper初始化,就可以了。
(2)swiper组件调用时增加:“ v-if ="datalist.length" ”;
<swiper v-if ="datalist.length">
这样加上v-if,如果为假就不执行,如果为真才调用swiper组件,所以只能等异步拿完数据,datalist. length不等于0,才进行调用swiper组件,才开始进行swiper初始化,就不会出现过早定义的问题了。
完整代码:异步请求数据,swiper组件化:
<!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>Document</title>
<link rel="stylesheet" href="./swiper/swiper-bundle.min.css">
<script src="./swiper/swiper-bundle.min.js"></script>
<script src="./lib/vue.js"></script>
</head>
<body>
<div id="box">
<!-- <swiper :key="datalist.length"> -->
<swiper v-if ="datalist.length">
<swiper-item v-for="data in datalist">
<img :src="data" alt="">
</swiper-item>
</swiper>
</div>
<script>
Vue.component("swiperItem",{
template:`
<div class="swiper-slide">
<slot></slot>
</div>
`
})
Vue.component("swiper", {
template: `
<div class="swiper">
<div class="swiper-wrapper">
<slot></slot>
</div>
<div class="swiper-pagination"></div>
</div>
`,
mounted(){
new Swiper(".swiper", {
loop: true, // 循环模式选项
// 如果需要分页器
pagination: {
el: '.swiper-pagination',
}
})
}
})
new Vue({
el: "#box",
data: {
datalist:[]
},
mounted() {
//ajax请求回来的数据
setTimeout(() => {
//后端的返回的数据用数组接收
this.datalist = ["https://static.maizuo.com/pc/v5/usr/movie/e856bdc65507b99800f22e47801fa781.jpg",
"https://p0.pipi.cn/mmdb/25bfd6ddb53c7e5015d23c5bc24d876c03d41.jpg?imageView2/1/w/160/h/220",
"https://p0.pipi.cn/mmdb/25bfd692ddd7e13139313954ee2938728ad6a.jpg?imageView2/1/w/160/h/220"]
}, 2000)
},
})
</script>
</body>
</html>
结果: