【vue学习|Vue基础实现bilibili移动端页面】
Vue基础实现bilibili移动端页面
- 一、Vue基础实现bilibili移动端页面
一、Vue基础实现bilibili移动端页面 简述:对于已经学到vue的同学,bilibili的页面布置难度不大,仔细阅读仔细体悟;难点在于怎么做到使用vue‘不操作’dom,从而实现较为复杂的逻辑方法。由于是按头部-导航-轮播-视频-底部的顺序,所以并没有多少注释,但是也并不难阅读。
axios.js
可搜索自行下载//html
Document - 锐客网
src="https://www.it610.com/article/axios.js">
src="https://www.it610.com/article/request.js">
src="https://www.it610.com/article/vue.js">
width="62" height="28" viewBox="0 0 62 28" fill="#de698c">
width="12" height="18" viewBox="0 0 1024 1024">
>北冥有鱼,化而为鹏梵蒂冈连快递费过来付款定金
width="24" height="24" viewBox="0 0 80 80">
下载App
width="16" height="32" viewBox="0 0 1024 1024">
width="16" height="32" viewBox="0 0 1024 1024">
-
文章图片
viewBox="0 0 1024 1024">
{{ video.play }}
viewBox="0 0 1024 1024">
{{ video.rank }}
{{ video.title }}
>
const vm = new Vue({
el: '#app',
data: {
navList: [],
navHide: true,
navActiveIndex: 0,
bannerList: [],
bannerWidth: 350,
bannerStyle: {
left: 0,
transition: 'left .3s',
},
bannerActiveIndex: 0,
videoOldList: [],
videoOldList: [],
videoGettingData: false,
videoCount: 0,
},
computed: {
videoList () {
return this.videoOldList.map(video => {
video.play = video.play > 10000 ? video.play / 10000 + '万' : video.play;
video.rank = video.rank > 10000 ? video.rank / 10000 + '万' : video.rank;
return video;
})
}
},
methods: {
handleClick () {
this.navHide = !this.navHide;
},
handleNavClick (index) {
this.navActiveIndex = index;
},
autoMove () {
setTimeout(() => {
if(this.bannerActiveIndex === 0 ) {//判断轮播索引确定循环
this.bannerStyle.transition = 'left .3s';
}this.bannerActiveIndex ++;
this.bannerStyle.left = -this.bannerActiveIndex * this.bannerWidth + 'px';
}, 1500)
},
handleTransitionEnd () {
if(this.bannerActiveIndex === 3) {
this.bannerActiveIndex = 0;
this.bannerStyle.left = 0;
this.bannerStyle.transition = 'none';
}
this.autoMove();
},
handleScroll (e) {
const { scrollHeight, offsetHeight, scrollTop } = e.target;
const toBottomHeight = scrollHeight - offsetHeight - scrollTop;
//是否滑动到接近底部
const videoLength = this.videoList.length;
if(videoLength === this.videoCount) { return;
}
if(toBottomHeight < 200 && !this.videoGettingData) {//接近底部则再次请求数据
this.videoGettingData = https://www.it610.com/article/true;
axios.get('video', {
params: {
start: this.videoList.length,
offset: 12
}
}).then(res => {
this.videoOldList.push(...res.data);
//将多次视频数据拼接
this.videoGettingData = https://www.it610.com/article/false;
})}
},
getData () {
axios.all([
axios.get('nav'),//对导航的处理
axios.get('banner'),//对轮播的处理
axios.get('video', {//对视频信息的处理
params: {
start: 0,
offset: 12
}
})
]).then(axios.spread((navRes, bannerRes, videoRes) => {
this.initNavList(navRes);
this.initBannerList(bannerRes);
this.initVideo(videoRes);
}));
},
initNavList (navRes) {
this.navList = navRes;
},
initBannerList (bannerRes) {
const bannerLaseEle = {...bannerRes[0]};
bannerLaseEle.id = Math.floor(Math.random() * 10000000);
this.bannerList = [...bannerRes, bannerLaseEle];
},
initVideo (videoRes) {
this.videoCount = videoRes.count;
this.videoOldList = videoRes.data;
}
},
created () {
this.getData();
},
mounted () {
this.autoMove();
}
})
//index.css
html{
height: 100%;
}
body{
height: 100%;
}
#app{
height: 100%;
overflow-y: scroll;
}
.header {
position: fixed;
top: 0;
left: 0;
right: 0;
display: flex;
align-items: center;
justify-content: space-between;
padding-top: 10px;
padding-bottom: 15px;
z-index: 3;
background-color: #fff;
}.header .logo {
margin-left: 18px;
}.header .search-input {
width: 132px;
height: 24px;
margin-left: 5px;
display: flex;
align-items: center;
font-size: 10px;
color: #999;
background-color: #f4f4f4;
border-radius: 12px;
}.header .search-input svg {
margin-left: 10px;
}.header .search-input span {
width: 92px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}.header .avatar svg {
border-radius: 50%;
}.header .download-app {
-webkit-user-drag: 78px;
height: 23px;
padding-left: 10px;
padding-right: 10px;
margin-right: 12px;
line-height: 23px;
text-align: center;
color: #fff;
background-color: #fb7299;
font-size: 12px;
border-radius: 4px;
}.nav-box {
position: fixed;
top: 54px;
left: 0;
right: 0;
z-index: 1;
background-color: #fff;
}.nav-box .nav-list {
width: 85%;
white-space: nowrap;
overflow-x: scroll;
padding-left: 24px;
/* display: none;
*/
}.nav-box .nav-list::-webkit-scrollbar {
display: none;
}.nav-box .nav {
display: inline-block;
height: 30px;
line-height: 30px;
margin-right: 40px;
color: #757575;
font-size: 14px;
border-bottom: 2px solid transparent;
}.nav-box .nav.active {
border-color: #fb7299;
color: #fb7299;
}.nav-box .down {
position: absolute;
top: -3px;
right: 13px;
}.hide-nav-box {
position: fixed;
top: 54px;
left: 0;
right: 0;
padding-bottom: 20px;
z-index: 2;
transition: top .3s;
background-color: #fff;
}.hide-nav-box.hide {
top: -117px;
}.hide-nav-box .nav {
display: inline-block;
width: 32px;
text-align: center;
margin-left: 14px;
margin-right: 14px;
margin-bottom: 10px;
padding-top: 6px;
padding-bottom: 6px;
font-size: 14px;
color: #757575;
border-bottom: 2px solid transparent;
}.hide-nav-box .nav.big {
width: 46px;
margin-left: 7px;
margin-right: 7px;
}.hide-nav-box .nav.active {
border-color: #fb7299;
color: #fb7299;
}.hide-nav-box .up {
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
z-index: 1;
}.banner-box {
position: relative;
top: 90px;
left: 50%;
transform: translateX(-50%);
width: 350px;
height: 110px;
border-radius: 6px;
overflow: hidden;
}.banner-box .banner-list {
position: absolute;
left: 0;
width: calc(350px * 4);
transition: left .3s;
}.banner-box .banner {
float: left;
width: 350px;
height: 110px;
}.banner-box .poster {
width: 100%;
height: 100%;
}.banner-box .index-list {
position: absolute;
bottom: 3px;
left: 50%;
transform: translateX(-50%);
display: flex;
align-items: center;
height: 10px;
padding-left: 3px;
padding-right: 3px;
background-color: rgba(0, 0, 0, .5);
border-radius: 5px;
}.banner-box .index {
width: 5px;
height: 5px;
border-radius: 50%;
margin-left: 3px;
margin-right: 3px;
background-color: #fff;
}.banner-box .index.active {
background-color: #fb7299;
}
/* 视频区 */
.video-box{
margin-top: 100px;
padding-left: 6px;
padding-right: 6px;
}
.video-box .video-list::after{
display: block;
content: '';
clear: both;
}
.video-box .video{
width: 50%;
float: left;
}
.video-box .poster{
position: relative;
height: 106px;
margin-right: 6px;
margin-left: 6px;
border-radius: 6px;
overflow: hidden;
}
.video-box .poster img{
width: 100%;
height: 100%;
}
.video-box .poster .info{
position: absolute;
bottom: 0;
color: #fff;
padding-top: 8px;
padding-bottom: 2px;
height: 18px;
font-size: 12px;
background-image: linear-gradient(rgba(33,33,33,0),rgba(33,33,33,0.8));
}
.video-box .info div{
display: inline-flex;
align-items: center;
margin-left: 16px;
}
.video-box .info svg{
margin-right: 4px;
margin-top: 2px;
width: 14px;
height: 14px;
fill: #fff;
}
.video-box .title{
margin: 6px 6px 10px 6px;
height: 38px;
line-height: 20px;
font-size: 13px;
/* 单行文本溢出打点:
设置文本不换行
white-space: nowrap;
设置文字溢出用省略号代替
text-overflow: ellipsis;
*/
/* 多行文本溢出打点: */
overflow: hidden;
/* 设置盒子为伸缩盒 */
display: -webkit-box;
/* 设置伸缩盒内子元素的排列方式为vertical */
-webkit-box-orient: vertical;
/* 限制一个块元素内显示的文本行数 */
-webkit-line-clamp: 2;
}.footer {
margin-top: 40px;
}.footer p {
margin-bottom: 20px;
text-align: center;
font-size: 13px;
color: #999;
}
//request.js
axios.defaults.baseURL = 'https://developer.duyiedu.com/vue/bz/';
//默认配置请求地址公共部分
axios.interceptors.response.use((response) => {
const { status } = response;
const { baseURL, url } = response.config;
if(status === 200) {
if(url === baseURL + 'video') {
return {
count: response.data.count,
data: response.data.data
}
}
return response.data.data;
}
return response;
});
文章图片
推荐阅读
- vue|VUE哔哩哔哩移动端项目使用vant 实现发布功能(上传文件)
- css|40个适合初学者练习HTML和CSS的案例
- 视频教程|Web 前端视频资源分享(Bootstrap/Vue/小程序)
- java|Java五年,已财富自由,美人在手!
- VUE|VUE this.$nextTick()的使用场景
- vite-vue-ts axios请求
- vue|前端合并单元格,一看就会
- vite创建vue3+ts+ant design vue项目
- #|VUE_数据修改后调用 this.$nextTick