小说项目增添了内容左右滑动需求,于是用了 uni-app 内置的 swiper 来做左右滑动
HTML代码:
<view
class="content-text"
id="box"
:style="{fontSize: fontSize + 'px'}"
v-if="topRight"
>
<view id="data">
<rich-text :nodes="contentData"></rich-text>
</view>
</view>
<swiper
v-if="topRight"
:style="{ backgroundColor: novelBgStyle, color: novelColor,fontSize: fontSize + 'px' }"
class="swiper1"
:duration="500"
:current = "swiper_index"
@animationfinish = 'swiperChange'
>
<swiper-item
v-for="(item,index) in sliderContent" :key='index'
:item-id=""
>
<view class="swiper-item" v-html=""></view>
</swiper-item>
</swiper>
原本是用 v-show 显示隐藏,后来发现时好时坏,于是改用 v-if 。
最上面的 view 盒子是用来测量内容高度的,外面还有一个父盒子是视窗高度,层级显示在最后面。
1.数据填充进第一个盒子后获取内容高度
uni.request({
url: this.urls + '/app/bookDetail/content?ids=' + send_id,
success: res => {
let swiper_title_init = `<h3 style="margin-bottom:20px">${res.data.data[0].title}</h3>`;
this.contentData = swiper_title_init + res.data.data[0].content;
var box = uni.createSelectorQuery().select('#box'); //获取父盒子高度
box.boundingClientRect(data => {
this.boxHeight = Math.floor(data.height / 26) * 26;
setTimeout(()=>{ // setTimeout后才能获取到填充了内容的盒子高度
var text = uni.createSelectorQuery().select('#data'); //获取内容高度
text.fields({size:true} , data => {
this.textHeight = data.height;
let len = Math.ceil(this.textHeight/this.boxHeight); // 内容分成len个视窗(父盒子)的高度
// 每个视窗含有的字符个数
let throat = Math.ceil((this.boxHeight/this.textHeight)*this.contentData.length);
for (let i = 0; i < len ; i++){
this.countText(throat,i,send_id);
}
if(callback){
callback();
}
}).exec();
})
}).exec()
}
});
2.根据获取的高度裁剪内容后填充
countText(throat,index,id){
let tempstr = '';
let arr = '';
let str = this.contentData.charAt(throat);
let id_and_index = id+'-'+index;
let put_data = {};
// 判断截取部分是否是<p></p>标签和<br/>标签 具体自己编写~我的代码还没精简 就发个简单版的
if(str == '<') {
if(this.contentData.charAt(throat+2) == '>'){
tempstr = this.contentData.slice(0, throat+3);
arr = this.contentData.split("");
arr.splice(0, throat+3);
}
}
this.contentData = arr.join(""); // 截取后删掉原数据被截取部分
put_data.text = tempstr;
put_data.id = id_and_index; //这里下面说明
this.sliderContent.push(put_data);
}
放入id和index 是这一章内容的id 和 这一章分页截取后的页数,后面会放到 swiper-item 的 item-id 属性当中(:item-id=“”) 就可以在 swiper @change 或者 @animationfinish 的调用中 取到 到时候方便调用记录和返回历史;
推荐用 @animationfinish 监听加载更多,这样看起来不会卡顿。
基本的滑动功能 这里就说完了!
补个坑点:
H5端测试没问题 手机端滑动后 更换章节时 swiper会卡死 数据什么的获取填充都是正常的 但是显示正常,
这时候用 v-if 的好处就出来了
this.topRight = false; //v-if
this.sliderContent = [];
setTimeout(()=>{
this.topRight = true; //v-if
this.sliderPage(id);
})
先用 v-if 销毁 DOM 然后重新创建渲染 必须用 setTimeout 打个时间差,不然不管用,实测!!!这问题找了好久,才找出来。