小编目前在做毕业设计,主题为“高考志愿信息交流平台”,面向高中生和大学生,辛苦各位读者大佬朋友们填下问卷,点击链接https://www.wjx.cn/jq/98944127.aspx或扫描二维码、微信小程序码均可,希望各位能提供一些调查数据,先在这里谢过各位了(*^_^*)
本文主要介绍了动态页的开发,主要包括4部分:
顶部导航栏的开发;
关注列表页的开发,包括滑动滚动区域、联动、顶踩事件和上拉加载;
话题专题和分类页开发,包括热门分类组件、搜索框、轮播图、话题列表组件和话题分类页;
话题详情页开发,包括数据传递、话题介绍组件、精华帖子列表、列表选项卡组件和上拉加载更多。
动态页包括顶部导航栏、关注列表和话题列表。
顶部导航栏需要实现自定义,news.vue如下:
<template>
<view>
<uni-nav-bar>
<view class="flex align-center justify-center font-weight-bold w-100">
<view class="font-lg text-main mx-1">关注view>
<view class="font-md text-light-muted mx-1">话题view>
view>
<text slot="right" class="iconfont icon-fatie_icon">text>
uni-nav-bar>
view>
template>
<script>
import uniNavBar from '@/components/uni-ui/uni-nav-bar/uni-nav-bar.vue';
export default {
data() {
return {
}
},
components: {
uniNavBar
},
methods: {
}
}
script>
<style>
style>
base.css如下:
/* 内外边距 */
.p-2 {
padding: 20rpx;
}
/* flex布局 */
.flex {
/* #ifndef APP-APP-PLUS-NVUE */
display: flex;
/* #endif */
flex-direction: row;
}
.flex-wrap {
flex-wrap: wrap;
}
.flex-column {
flex-direction: column;
}
.align-center {
align-items: center;
}
.justify-between {
justify-content: space-between;
}
.justify-center {
justify-content: center;
}
.flex-1 {
flex: 1;
}
/* 圆角 */
.rounded-circle {
border-radius: 100%;
}
.rounded {
border-radius: 8rpx;
}
/* margin */
.mr-2 {
margin-right: 20rpx;
}
.my-1 {
margin-top: 10rpx;
margin-bottom: 10rpx;
}
.mx-2 {
margin-left: 20rpx;
margin-right: 20rpx;
}
.mx-1 {
margin-left: 10rpx;
margin-right: 10rpx;
}
.mt-1 {
margin-top: 10rpx;
}
.ml-auto {
margin-left: auto;
}
/* padding */
.p-2 {
padding-left: 20rpx;
padding-right: 20rpx;
padding-top: 20rpx;
padding-bottom: 20rpx;
}
.px-5 {
padding-left: 50rpx;
padding-right: 50rpx;
}
.px-3 {
padding-left: 30rpx;
padding-right: 30rpx;
}
.px-2 {
padding-left: 20rpx;
padding-right: 20rpx;
}
.px-1 {
padding-left: 10rpx;
padding-right: 10rpx;
}
.py-3 {
padding-top: 30rpx;
padding-bottom: 30rpx;
}
.py-2 {
padding-top: 20rpx;
padding-bottom: 20rpx;
}
.pt-7 {
padding-top: 70rpx;
}
.pb-2 {
padding-bottom: 20rpx;
}
/* 边框 */
.border {
border-width: 1rpx;
border-style: solid;
border-color: #DEE2E6;
}
.border-bottom {
border-bottom: 1rpx solid #DEE2E6;
}
.border-light-secondary {
border: 1rpx solid #AAA8AB;
}
/* 字体 */
.font-lg {
font-size: 40rpx;
}
.font-md {
font-size: 35rpx;
}
.font {
font-size: 30rpx;
}
.font-sm {
font-size: 25rpx;
}
.font-weight-bold {
font-weight: bold;
}
/* 文字颜色 */
.text-white {
color: #FFFFFF;
}
.text-light-muted {
color: #A9A5A0;
}
/* 文字换行溢出处理 */
.text-ellipsis {
/* #ifndef APP-PLUS-APP-PLUS-NVUE */
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
/* #endif */
/* #ifdef APP-PLUS-APP-PLUS-NVUE */
lines: 1;
/* #endif */
}
/* 宽度 */
/* #ifndef APP-PLUS-NVUE */
.w-100 {
width: 100%;
}
/* #endif */
/* scroll-view */
/* #ifndef APP-PLUS-NVUE */
.scroll-row {
width: 100%;
white-space: nowrap;
}
.scroll-row-item {
display: inline-block !important;
}
/* #endif */
/* 背景 */
.bg-light {
background-color: #F8F9FA;
}
.bg-white {
background-color: #FFFFFF;
}
.bg-dark {
background-color: #333333;
}
/* 定位 */
.position-relative {
position: relative;
}
.position-absolute {
position: absolute;
}
.position-fixed {
position: fixed;
}
/* 定位-固定顶部 */
.fixed-top {
position: fixed;
top: 0;
right: 0;
left: 0;
z-index: 1030;
}
/* 定位-固定底部 */
.fixed-bottom {
position: fixed;
right: 0;
bottom: 0;
left: 0;
z-index: 1030;
}
.top-0 {
top: 0;
}
.left-0 {
left: 0;
}
.right-0 {
right: 0;
}
.bottom-0 {
bottom: 0;
}
common.css如下:
/* 本项目全局样式 */
/* 背景 */
.bg-main {
background-color: #FF4A6A;
}
/* 文本颜色 */
.text-main {
color: #FF4A6A;
}
.text-secondry {
color: #AAA8AB;
}
.text-dark {
color: #333333;
}
可以看到,已经搭建好初步页面。
再完善样式,news.vue中给自定义导航栏取消边界、固定位置、添加状态栏,如下:
<uni-nav-bar :border="false" :fixed="true" :statusBar="true">
<view class="flex align-center justify-center font-weight-bold w-100">
<view class="font-lg text-main mx-1">关注view>
<view class="font-md text-light-muted mx-1">话题view>
view>
<text slot="right" class="iconfont icon-fatie_icon">text>
uni-nav-bar>
同时在pages.json中禁止原生导航栏,如下:
{
"path" : "pages/news/news",
"style" :
{
"navigationBarTitleText": "",
"enablePullDownRefresh": false,
"app-plus": {
"titleNView": false
}
}
}
显然,此时更加美观。
再添加点击事件,如下:
<template>
<view>
<uni-nav-bar :border="false" :fixed="true" :statusBar="true" @clickRight="openAddInput">
<view class="flex align-center justify-center font-weight-bold w-100">
<view class="mx-1" v-for="(item, index) in tabBars" :key="index" :class="tabIndex === index ? 'font-lg text-main' : 'font-md text-light-muted'" @click="changeTab(index)">{
{item.name}}view>
view>
<text slot="right" class="iconfont icon-fatie_icon">text>
uni-nav-bar>
view>
template>
<script>
import uniNavBar from '@/components/uni-ui/uni-nav-bar/uni-nav-bar.vue';
export default {
data() {
return {
tabBars: [{
name: '关注'
},
{
name: '话题'
}
],
tabIndex: 0
}
},
components: {
uniNavBar
},
methods: {
// 打开发布页
openAddInput() {
uni.navigateTo({
url: '../add-input/add-input'
});
},
// 切换选项卡
changeTab(index) {
this.tabIndex = index;
}
}
}
script>
<style>
style>
显然,可以实现点击切换。
关注和话题页面也是滚动区域,也是通过swiper
嵌套scroll-view
实现。
计算时,需要整体可用高度减去状态栏和自定义导航栏高度,如下:
<template>
<view>
<uni-nav-bar :border="false" :fixed="true" :statusBar="true" @clickRight="openAddInput">
<view class="flex align-center justify-center font-weight-bold w-100">
<view class="mx-1" v-for="(item, index) in tabBars" :key="index" :class="tabIndex === index ? 'font-lg text-main' : 'font-md text-light-muted'" @click="changeTab(index)">{
{item.name}}view>
view>
<text slot="right" class="iconfont icon-fatie_icon">text>
uni-nav-bar>
<swiper :duration="150" :style="'height: '+scrollH+'px;'">
<swiper-item>
<scroll-view scroll-y="true" :style="'height: '+scrollH+'px;'">
<view v-for="i in 50">{
{i}}: https://blog.csdn.net/CUFEECRview>
scroll-view>
swiper-item>
swiper>
view>
template>
<script>
import uniNavBar from '@/components/uni-ui/uni-nav-bar/uni-nav-bar.vue';
export default {
data() {
return {
tabBars: [{
name: '关注'
},
{
name: '话题'
}
],
tabIndex: 0,
scrollH: 500
}
},
components: {
uniNavBar
},
onLoad() {
uni.getSystemInfo({
success: function(res) {
console.log(res);
this.scrollH = res.windowHeight - res.statusBarHeight - 44;
}
})
},
methods: {
// 打开发布页
openAddInput() {
uni.navigateTo({
url: '../add-input/add-input'
});
},
// 切换选项卡
changeTab(index) {
this.tabIndex = index;
}
}
}
script>
<style>
style>
显示:
可以看到,计算出了正确高度,显示出了模拟的列表项。
导航栏和列表的联动主要通过tabIndex
进行关联,即tabIndex
的变化同时影响导航栏和列表,实现同步变化。
news.vue如下:
<template>
<view>
<uni-nav-bar :border="false" :fixed="true" :statusBar="true" @clickRight="openAddInput">
<view class="flex align-center justify-center font-weight-bold w-100">
<view class="mx-1" v-for="(item, index) in tabBars" :key="index" :class="tabIndex === index ? 'font-lg text-main' : 'font-md text-light-muted'" @click="changeTab(index)">{
{item.name}}view>
view>
<text slot="right" class="iconfont icon-fatie_icon">text>
uni-nav-bar>
<swiper :current="tabIndex" :duration="150" :style="'height: '+scrollH+'px;'" @change="onChangeTab">
<swiper-item>
<scroll-view scroll-y="true" :style="'height: '+scrollH+'px;'">
<block v-for="(item, index) in list" :key="index">
<common-list :item="item" :index="index">common-list>
<divider>divider>
block>
scroll-view>
swiper-item>
<swiper-item>
<scroll-view scroll-y="true" :style="'height: '+scrollH+'px;'">
话题
scroll-view>
swiper-item>
swiper>
view>
template>
<script>
// 测试数据
const test_data = [{
username: "Corley",
userpic: "/static/img/userpic/12.jpg",
newstime: "2021-01-24 上午11:30",
isFollow: false,
title: "uni-app入门教程",
titlepic: "/static/img/datapic/42.jpg",
support: {
type: "support", // 顶
support_count: 1,
unsupport_count: 2
},
comment_count: 2,
share_count: 2
},
{
username: "Brittany",
userpic: "/static/img/userpic/16.jpg",
newstime: "2021-01-24 下午14:00",
isFollow: false,
title: "商业数据分析从入门到入职",
support: {
type: "unsupport", // 踩
support_count: 2,
unsupport_count: 3
},
comment_count: 5,
share_count: 1
},
{
username: "Jessica",
userpic: "/static/img/userpic/7.jpg",
newstime: "2021-01-24 下午14:44",
isFollow: true,
title: "Django+Vue开发生鲜电商平台",
titlepic: "/static/img/datapic/11.jpg",
support: {
type: "", // 未操作
support_count: 2,
unsupport_count: 7
},
comment_count: 0,
share_count: 2
},
{
username: "Ashley",
userpic: "/static/img/userpic/20.jpg",
newstime: "2021-01-24 下午18:20",
isFollow: true,
title: "uni-app实战之社区交友APP",
titlepic: "/static/img/datapic/30.jpg",
support: {
type: "support",
support_count: 5,
unsupport_count: 1
},
comment_count: 3,
share_count: 0
}
];
import uniNavBar from '@/components/uni-ui/uni-nav-bar/uni-nav-bar.vue';
import commonList from '@/components/common/common-list.vue';
export default {
data() {
return {
tabBars: [{
name: '关注'
},
{
name: '话题'
}
],
tabIndex: 0,
scrollH: 500,
// 关注列表
list: []
}
},
components: {
uniNavBar,
commonList
},
onLoad() {
uni.getSystemInfo({
success: function(res) {
console.log(res);
this.scrollH = res.windowHeight - res.statusBarHeight - 44;
}
}),
// 加载测试数据
this.list = test_data;
},
methods: {
// 打开发布页
openAddInput() {
uni.navigateTo({
url: '../add-input/add-input'
});
},
// 切换选项卡
changeTab(index) {
this.tabIndex = index;
},
// 滑动
onChangeTab(e) {
this.tabIndex = e.detail.current;
}
}
}
script>
<style>
style>
显示:
显然,实现了联动变化和列表显示。
现实现顶踩、关注和上拉加载功能。
因为是在关注列表中,所有用户均为已关注用户,因此不需要实现关注功能。
先实现顶踩功能,如下:
<template>
<view>
<uni-nav-bar :border="false" :fixed="true" :statusBar="true" @clickRight="openAddInput">
<view class="flex align-center justify-center font-weight-bold w-100">
<view class="mx-1" v-for="(item, index) in tabBars" :key="index" :class="tabIndex === index ? 'font-lg text-main' : 'font-md text-light-muted'" @click="changeTab(index)">{
{item.name}}view>
view>
<text slot="right" class="iconfont icon-fatie_icon">text>
uni-nav-bar>
<swiper :current="tabIndex" :duration="150" :style="'height: '+scrollH+'px;'" @change="onChangeTab">
<swiper-item>
<scroll-view scroll-y="true" :style="'height: '+scrollH+'px;'">
<block v-for="(item, index) in list" :key="index">
<common-list :item="item" :index="index" @doSupport="doSupport">common-list>
<divider>divider>
block>
scroll-view>
swiper-item>
<swiper-item>
<scroll-view scroll-y="true" :style="'height: '+scrollH+'px;'">
话题
scroll-view>
swiper-item>
swiper>
view>
template>
<script>
// 测试数据
const test_data = [{
username: "Corley",
userpic: "/static/img/userpic/12.jpg",
newstime: "2021-01-24 上午11:30",
isFollow: true,
title: "uni-app入门教程",
titlepic: "/static/img/datapic/42.jpg",
support: {
type: "support", // 顶
support_count: 1,
unsupport_count: 2
},
comment_count: 2,
share_count: 2
},
{
username: "Brittany",
userpic: "/static/img/userpic/16.jpg",
newstime: "2021-01-24 下午14:00",
isFollow: true,
title: "商业数据分析从入门到入职",
support: {
type: "unsupport", // 踩
support_count: 2,
unsupport_count: 3
},
comment_count: 5,
share_count: 1
},
{
username: "Jessica",
userpic: "/static/img/userpic/7.jpg",
newstime: "2021-01-24 下午14:44",
isFollow: true,
title: "Django+Vue开发生鲜电商平台",
titlepic: "/static/img/datapic/11.jpg",
support: {
type: "", // 未操作
support_count: 2,
unsupport_count: 7
},
comment_count: 0,
share_count: 2
},
{
username: "Ashley",
userpic: "/static/img/userpic/20.jpg",
newstime: "2021-01-24 下午18:20",
isFollow: true,
title: "uni-app实战之社区交友APP",
titlepic: "/static/img/datapic/30.jpg",
support: {
type: "support",
support_count: 5,
unsupport_count: 1
},
comment_count: 3,
share_count: 0
}
];
import uniNavBar from '@/components/uni-ui/uni-nav-bar/uni-nav-bar.vue';
import commonList from '@/components/common/common-list.vue';
export default {
data() {
return {
tabBars: [{
name: '关注'
},
{
name: '话题'
}
],
tabIndex: 0,
scrollH: 500,
// 关注列表
list: []
}
},
components: {
uniNavBar,
commonList
},
onLoad() {
uni.getSystemInfo({
success: function(res) {
console.log(res);
this.scrollH = res.windowHeight - res.statusBarHeight - 44;
}
}),
// 加载测试数据
this.list = test_data;
},
methods: {
// 打开发布页
openAddInput() {
uni.navigateTo({
url: '../add-input/add-input'
});
},
// 切换选项卡
changeTab(index) {
this.tabIndex = index;
},
// 滑动
onChangeTab(e) {
this.tabIndex = e.detail.current;
},
// 顶踩操作
doSupport(e) {
console.log(e);
// 获取当前列表项
let item = this.list[e.index];
let msg = e.type === 'support' ? '顶' : '踩';
// 之前未顶踩过
if (item.support.type === '') {
item.support[e.type + '_count']++;
}
// 之前已顶过并且现在的操作为踩,则顶-1、踩+1
else if (item.support.type === 'support' && e.type === 'unsupport') {
item.support.support_count--;
item.support.unsupport_count++;
}
// 之前已踩过并且现在的操作为顶,则踩-1、顶+1
else if (item.support.type === 'unsupport' && e.type === 'support') {
item.support.unsupport_count--;
item.support.support_count++;
}
item.support.type = e.type;
uni.showToast({
title: msg + '成功'
})
},
}
}
script>
<style>
style>
显示:
可以看到,也实现了顶踩功能。
再实现加载功能,如下:
<template>
<view>
<uni-nav-bar :border="false" :fixed="true" :statusBar="true" @clickRight="openAddInput">
<view class="flex align-center justify-center font-weight-bold w-100">
<view class="mx-1" v-for="(item, index) in tabBars" :key="index" :class="tabIndex === index ? 'font-lg text-main' : 'font-md text-light-muted'"
@click="changeTab(index)">{
{item.name}}view>
view>
<text slot="right" class="iconfont icon-fatie_icon">text>
uni-nav-bar>
<swiper :current="tabIndex" :duration="150" :style="'height: '+scrollH+'px;'" @change="onChangeTab">
<swiper-item>
<scroll-view scroll-y="true" :style="'height: '+scrollH+'px;'" @scrolltolower="loadmoreEvent">
<block v-for="(item, index) in list" :key="index">
<common-list :item="item" :index="index" @doSupport="doSupport">common-list>
<divider>divider>
block>
<load-more :loadmore="loadmore">load-more>
scroll-view>
swiper-item>
<swiper-item>
<scroll-view scroll-y="true" :style="'height: '+scrollH+'px;'">
话题
scroll-view>
swiper-item>
swiper>
view>
template>
<script>
// 测试数据
const test_data = [{
username: "Corley",
userpic: "/static/img/userpic/12.jpg",
newstime: "2021-01-24 上午11:30",
isFollow: true,
title: "uni-app入门教程",
titlepic: "/static/img/datapic/42.jpg",
support: {
type: "support", // 顶
support_count: 1,
unsupport_count: 2
},
comment_count: 2,
share_count: 2
},
{
username: "Brittany",
userpic: "/static/img/userpic/16.jpg",
newstime: "2021-01-24 下午14:00",
isFollow: true,
title: "商业数据分析从入门到入职",
support: {
type: "unsupport", // 踩
support_count: 2,
unsupport_count: 3
},
comment_count: 5,
share_count: 1
},
{
username: "Jessica",
userpic: "/static/img/userpic/7.jpg",
newstime: "2021-01-24 下午14:44",
isFollow: true,
title: "Django+Vue开发生鲜电商平台",
titlepic: "/static/img/datapic/11.jpg",
support: {
type: "", // 未操作
support_count: 2,
unsupport_count: 7
},
comment_count: 0,
share_count: 2
},
{
username: "Ashley",
userpic: "/static/img/userpic/20.jpg",
newstime: "2021-01-24 下午18:20",
isFollow: true,
title: "uni-app实战之社区交友APP",
titlepic: "/static/img/datapic/30.jpg",
support: {
type: "support",
support_count: 5,
unsupport_count: 1
},
comment_count: 3,
share_count: 0
}
];
import uniNavBar from '@/components/uni-ui/uni-nav-bar/uni-nav-bar.vue';
import commonList from '@/components/common/common-list.vue';
import loadMore from '../../components/common/load-more.vue';
export default {
data() {
return {
tabBars: [{
name: '关注'
},
{
name: '话题'
}
],
tabIndex: 0,
scrollH: 500,
// 关注列表
list: [],
loadmore: "上拉加载更多"
}
},
components: {
uniNavBar,
commonList,
loadMore
},
onLoad() {
uni.getSystemInfo({
success: function(res) {
console.log(res);
this.scrollH = res.windowHeight - res.statusBarHeight - 44;
}
}),
// 加载测试数据
this.list = test_data;
},
methods: {
// 打开发布页
openAddInput() {
uni.navigateTo({
url: '../add-input/add-input'
});
},
// 切换选项卡
changeTab(index) {
this.tabIndex = index;
},
// 滑动
onChangeTab(e) {
this.tabIndex = e.detail.current;
},
// 顶踩操作
doSupport(e) {
console.log(e);
// 获取当前列表项
let item = this.list[e.index];
let msg = e.type === 'support' ? '顶' : '踩';
// 之前未顶踩过
if (item.support.type === '') {
item.support[e.type + '_count']++;
}
// 之前已顶过并且现在的操作为踩,则顶-1、踩+1
else if (item.support.type === 'support' && e.type === 'unsupport') {
item.support.support_count--;
item.support.unsupport_count++;
}
// 之前已踩过并且现在的操作为顶,则踩-1、顶+1
else if (item.support.type === 'unsupport' && e.type === 'support') {
item.support.unsupport_count--;
item.support.support_count++;
}
item.support.type = e.type;
uni.showToast({
title: msg + '成功'
})
},
// 上拉加载更多
loadmoreEvent() {
// 验证当前是否处于可加载状态
if (this.loadmore !== '上拉加载更多') return;
// 设置加载状态
this.loadmore = '加载中...';
// 模拟请求数据
setTimeout(() => {
// 加载数据
this.list = [...this.list, ...this.list];
// 设置加载状态
this.loadmore = '上拉加载更多';
}, 2000)
}
}
}
script>
<style>
style>
显示:
可以看到,已经实现了动态加载更多。
话题专题页开发包括热门分类组件、轮播图、搜索框话题列表组件等开发。
为了本文项目练手所需,需要在https://www.iconfont.cn/中选择进入
、搜索
、置顶
等图标并更新icon.css
。
热门分类包括标题、跳转按钮和关键词等部分,如下:
<template>
<view>
<uni-nav-bar :border="false" :fixed="true" :statusBar="true" @clickRight="openAddInput">
<view class="flex align-center justify-center font-weight-bold w-100">
<view class="mx-1" v-for="(item, index) in tabBars" :key="index" :class="tabIndex === index ? 'font-lg text-main' : 'font-md text-light-muted'"
@click="changeTab(index)">{
{item.name}}view>
view>
<text slot="right" class="iconfont icon-fatie_icon">text>
uni-nav-bar>
<swiper :current="tabIndex" :duration="150" :style="'height: '+scrollH+'px;'" @change="onChangeTab">
<swiper-item>
<scroll-view scroll-y="true" :style="'height: '+scrollH+'px;'" @scrolltolower="loadmoreEvent">
<block v-for="(item, index) in list" :key="index">
<common-list :item="item" :index="index" @doSupport="doSupport">common-list>
<divider>divider>
block>
<load-more :loadmore="loadmore">load-more>
scroll-view>
swiper-item>
<swiper-item>
<scroll-view scroll-y="true" :style="'height: '+scrollH+'px;'">
<view class="flex align-center justify-between px-2">
<text class="font-md">热门分类text>
<view class="flex align-center font text-secondry animate__animated" hover-class="animate__jello">
更多<text class="iconfont icon-bangzhujinru">text>
view>
view>
<view class="flex align-center px-2 py-3 border-bottom">
<view class="border rounded bg-light mx-1 px-2 animate__animated" hover-class="animate__jello">
关注
view>
<view class="border rounded bg-light mx-1 px-2 animate__animated" hover-class="animate__jello">
推荐
view>
<view class="border rounded bg-light mx-1 px-2 animate__animated" hover-class="animate__jello">
体育
view>
<view class="border rounded bg-light mx-1 px-2 animate__animated" hover-class="animate__jello">
热点
view>
<view class="border rounded bg-light mx-1 px-2 animate__animated" hover-class="animate__jello">
财经
view>
<view class="border rounded bg-light mx-1 px-2 animate__animated" hover-class="animate__jello">
娱乐
view>
view>
scroll-view>
swiper-item>
swiper>
view>
template>
<script>
// 测试数据
const test_data = [{
username: "Corley",
userpic: "/static/img/userpic/12.jpg",
newstime: "2021-01-24 上午11:30",
isFollow: true,
title: "uni-app入门教程",
titlepic: "/static/img/datapic/42.jpg",
support: {
type: "support", // 顶
support_count: 1,
unsupport_count: 2
},
comment_count: 2,
share_count: 2
},
{
username: "Brittany",
userpic: "/static/img/userpic/16.jpg",
newstime: "2021-01-24 下午14:00",
isFollow: true,
title: "商业数据分析从入门到入职",
support: {
type: "unsupport", // 踩
support_count: 2,
unsupport_count: 3
},
comment_count: 5,
share_count: 1
},
{
username: "Jessica",
userpic: "/static/img/userpic/7.jpg",
newstime: "2021-01-24 下午14:44",
isFollow: true,
title: "Django+Vue开发生鲜电商平台",
titlepic: "/static/img/datapic/11.jpg",
support: {
type: "", // 未操作
support_count: 2,
unsupport_count: 7
},
comment_count: 0,
share_count: 2
},
{
username: "Ashley",
userpic: "/static/img/userpic/20.jpg",
newstime: "2021-01-24 下午18:20",
isFollow: true,
title: "uni-app实战之社区交友APP",
titlepic: "/static/img/datapic/30.jpg",
support: {
type: "support",
support_count: 5,
unsupport_count: 1
},
comment_count: 3,
share_count: 0
}
];
import uniNavBar from '@/components/uni-ui/uni-nav-bar/uni-nav-bar.vue';
import commonList from '@/components/common/common-list.vue';
import loadMore from '../../components/common/load-more.vue';
export default {
data() {
return {
tabBars: [{
name: '关注'
},
{
name: '话题'
}
],
tabIndex: 0,
scrollH: 500,
// 关注列表
list: [],
loadmore: "上拉加载更多"
}
},
components: {
uniNavBar,
commonList,
loadMore
},
onLoad() {
uni.getSystemInfo({
success: function(res) {
console.log(res);
this.scrollH = res.windowHeight - res.statusBarHeight - 44;
}
}),
// 加载测试数据
this.list = test_data;
},
methods: {
// 打开发布页
openAddInput() {
uni.navigateTo({
url: '../add-input/add-input'
});
},
// 切换选项卡
changeTab(index) {
this.tabIndex = index;
},
// 滑动
onChangeTab(e) {
this.tabIndex = e.detail.current;
},
// 顶踩操作
doSupport(e) {
console.log(e);
// 获取当前列表项
let item = this.list[e.index];
let msg = e.type === 'support' ? '顶' : '踩';
// 之前未顶踩过
if (item.support.type === '') {
item.support[e.type + '_count']++;
}
// 之前已顶过并且现在的操作为踩,则顶-1、踩+1
else if (item.support.type === 'support' && e.type === 'unsupport') {
item.support.support_count--;
item.support.unsupport_count++;
}
// 之前已踩过并且现在的操作为顶,则踩-1、顶+1
else if (item.support.type === 'unsupport' && e.type === 'support') {
item.support.unsupport_count--;
item.support.support_count++;
}
item.support.type = e.type;
uni.showToast({
title: msg + '成功'
})
},
// 上拉加载更多
loadmoreEvent() {
// 验证当前是否处于可加载状态
if (this.loadmore !== '上拉加载更多') return;
// 设置加载状态
this.loadmore = '加载中...';
// 模拟请求数据
setTimeout(() => {
// 加载数据
this.list = [...this.list, ...this.list];
// 设置加载状态
this.loadmore = '上拉加载更多';
}, 2000)
}
}
}
script>
<style>
style>
显示:
显然,已经显示了热点分类,并且添加了点击的动画效果。
再实现将热门分类组件进行封装,减少代码、更易于维护。
在components目录下新建news子目录,下新建hot-cate.vue如下:
<template>
<view>
<view class="flex align-center justify-between px-2">
<text class="font-md">热门分类text>
<view class="flex align-center font text-secondry animate__animated" hover-class="animate__jello" @click="openMore()">
更多<text class="iconfont icon-bangzhujinru">text>
view>
view>
<view class="flex align-center px-2 py-3 border-bottom">
<view class="border rounded bg-light mx-1 px-2 animate__animated" hover-class="animate__jello" v-for="(item, index) in hotCate" :key="index" @click="openDetail(item)">
{
{item.name}}
view>
view>
view>
template>
<script>
export default {
props: ['hotCate'],
methods: {
openMore() {
console.log('opening more');
},
openDetail(item) {
console.log('opening detail');
}
}
}
script>
<style>
style>
news.vue修改如下:
<template>
<view>
<uni-nav-bar :border="false" :fixed="true" :statusBar="true" @clickRight="openAddInput">
<view class="flex align-center justify-center font-weight-bold w-100">
<view class="mx-1" v-for="(item, index) in tabBars" :key="index" :class="tabIndex === index ? 'font-lg text-main' : 'font-md text-light-muted'"
@click="changeTab(index)">{
{item.name}}view>
view>
<text slot="right" class="iconfont icon-fatie_icon">text>
uni-nav-bar>
<swiper :current="tabIndex" :duration="150" :style="'height: '+scrollH+'px;'" @change="onChangeTab">
<swiper-item>
<scroll-view scroll-y="true" :style="'height: '+scrollH+'px;'" @scrolltolower="loadmoreEvent">
<block v-for="(item, index) in list" :key="index">
<common-list :item="item" :index="index" @doSupport="doSupport">common-list>
<divider>divider>
block>
<load-more :loadmore="loadmore">load-more>
scroll-view>
swiper-item>
<swiper-item>
<scroll-view scroll-y="true" :style="'height: '+scrollH+'px;'">
<hot-cate :hotCate="hotCate">hot-cate>
scroll-view>
swiper-item>
swiper>
view>
template>
<script>
// 测试数据
const test_data = [{
username: "Corley",
userpic: "/static/img/userpic/12.jpg",
newstime: "2021-01-24 上午11:30",
isFollow: true,
title: "uni-app入门教程",
titlepic: "/static/img/datapic/42.jpg",
support: {
type: "support", // 顶
support_count: 1,
unsupport_count: 2
},
comment_count: 2,
share_count: 2
},
{
username: "Brittany",
userpic: "/static/img/userpic/16.jpg",
newstime: "2021-01-24 下午14:00",
isFollow: true,
title: "商业数据分析从入门到入职",
support: {
type: "unsupport", // 踩
support_count: 2,
unsupport_count: 3
},
comment_count: 5,
share_count: 1
},
{
username: "Jessica",
userpic: "/static/img/userpic/7.jpg",
newstime: "2021-01-24 下午14:44",
isFollow: true,
title: "Django+Vue开发生鲜电商平台",
titlepic: "/static/img/datapic/11.jpg",
support: {
type: "", // 未操作
support_count: 2,
unsupport_count: 7
},
comment_count: 0,
share_count: 2
},
{
username: "Ashley",
userpic: "/static/img/userpic/20.jpg",
newstime: "2021-01-24 下午18:20",
isFollow: true,
title: "uni-app实战之社区交友APP",
titlepic: "/static/img/datapic/30.jpg",
support: {
type: "support",
support_count: 5,
unsupport_count: 1
},
comment_count: 3,
share_count: 0
}
];
import uniNavBar from '@/components/uni-ui/uni-nav-bar/uni-nav-bar.vue';
import commonList from '@/components/common/common-list.vue';
import loadMore from '../../components/common/load-more.vue';
import hotCate from '@/components/news/hot-cate.vue';
export default {
data() {
return {
tabBars: [{
name: '关注'
},
{
name: '话题'
}
],
tabIndex: 0,
scrollH: 500,
// 关注列表
list: [],
loadmore: "上拉加载更多",
hotCate: [
{
name: '关注'
},
{
name: '推荐'
},
{
name: '体育'
},
{
name: '热点'
},
{
name: '财经'
},
{
name: '娱乐'
}
]
}
},
components: {
uniNavBar,
commonList,
loadMore,
hotCate
},
onLoad() {
uni.getSystemInfo({
success: function(res) {
console.log(res);
this.scrollH = res.windowHeight - res.statusBarHeight - 44;
}
}),
// 加载测试数据
this.list = test_data;
},
methods: {
// 打开发布页
openAddInput() {
uni.navigateTo({
url: '../add-input/add-input'
});
},
// 切换选项卡
changeTab(index) {
this.tabIndex = index;
},
// 滑动
onChangeTab(e) {
this.tabIndex = e.detail.current;
},
// 顶踩操作
doSupport(e) {
console.log(e);
// 获取当前列表项
let item = this.list[e.index];
let msg = e.type === 'support' ? '顶' : '踩';
// 之前未顶踩过
if (item.support.type === '') {
item.support[e.type + '_count']++;
}
// 之前已顶过并且现在的操作为踩,则顶-1、踩+1
else if (item.support.type === 'support' && e.type === 'unsupport') {
item.support.support_count--;
item.support.unsupport_count++;
}
// 之前已踩过并且现在的操作为顶,则踩-1、顶+1
else if (item.support.type === 'unsupport' && e.type === 'support') {
item.support.unsupport_count--;
item.support.support_count++;
}
item.support.type = e.type;
uni.showToast({
title: msg + '成功'
})
},
// 上拉加载更多
loadmoreEvent() {
// 验证当前是否处于可加载状态
if (this.loadmore !== '上拉加载更多') return;
// 设置加载状态
this.loadmore = '加载中...';
// 模拟请求数据
setTimeout(() => {
// 加载数据
this.list = [...this.list, ...this.list];
// 设置加载状态
this.loadmore = '上拉加载更多';
}, 2000)
}
}
}
script>
<style>
style>
效果与之前相同。
先实现搜索框,如下:
<view class="p-2">
<view class="bg-light rounded flex align-center justify-center py-2 text-secondry">
<text class="iconfont icon-sousuo mr-2">text>搜索话题
view>
view>
显然,实现了搜索框。
再实现轮播图,使用swiper组件实现,如下:
<swiper class="px-2 pb-2" :indicator-dots="true" :autoplay="true" :interval="3000" :duration="1000">
<swiper-item>
<image src="../../static/img/banner/banner1.jpg" style="height: 300rpx;" class="w-100 rounded" mode="">image>
swiper-item>
<swiper-item>
<image src="../../static/img/banner/banner2.jpeg" style="height: 300rpx;" class="w-100 rounded" mode="">image>
swiper-item>
<swiper-item>
<image src="../../static/img/banner/banner3.jpg" style="height: 300rpx;" class="w-100 rounded" mode="">image>
swiper-item>
swiper>
显示:
显然,已经实现了轮播图效果。
如需轮播图图片素材等文件,可以直接点击加QQ群 963624318 ,在群文件夹uni-app实战之社区交友APP中下载即可。
最近更新下的内容即为话题列表,开发如下:
<view class="p-2 font-md">最近更新view>
<view class="flex align-center p-2">
<image class="rounded mr-2" src="/static/img/topicpic/14.jpeg" style="width: 150rpx; height: 150rpx;">image>
<view class="flex flex-column flex-1">
<text class="font-md text-dark">#话题名称#text>
<text class="font text-secondry">话题描述text>
<view class="flex align-center font text-secondry">
<text class="mr-2">动态:10text>
<text>今日:1text>
view>
view>
view>
可以看到,显示出了话题列表。
现进一步将话题列表封装为组件,先构建数据,如下:
<template>
<view>
<uni-nav-bar :border="false" :fixed="true" :statusBar="true" @clickRight="openAddInput">
<view class="flex align-center justify-center font-weight-bold w-100">
<view class="mx-1" v-for="(item, index) in tabBars" :key="index" :class="tabIndex === index ? 'font-lg text-main' : 'font-md text-light-muted'"
@click="changeTab(index)">{
{item.name}}view>
view>
<text slot="right" class="iconfont icon-fatie_icon">text>
uni-nav-bar>
<swiper :current="tabIndex" :duration="150" :style="'height: '+scrollH+'px;'" @change="onChangeTab">
<swiper-item>
<scroll-view scroll-y="true" :style="'height: '+scrollH+'px;'" @scrolltolower="loadmoreEvent">
<block v-for="(item, index) in list" :key="index">
<common-list :item="item" :index="index" @doSupport="doSupport">common-list>
<divider>divider>
block>
<load-more :loadmore="loadmore">load-more>
scroll-view>
swiper-item>
<swiper-item>
<scroll-view scroll-y="true" :style="'height: '+scrollH+'px;'">
<hot-cate :hotCate="hotCate">hot-cate>
<view class="p-2">
<view class="bg-light rounded flex align-center justify-center py-2 text-secondry">
<text class="iconfont icon-sousuo mr-2">text>搜索话题
view>
view>
<swiper class="px-2 pb-2" :indicator-dots="true" :autoplay="true" :interval="3000" :duration="1000">
<swiper-item>
<image src="/static/img/banner/banner1.jpg" style="height: 300rpx;" class="w-100 rounded" mode="">image>
swiper-item>
<swiper-item>
<image src="/static/img/banner/banner2.jpeg" style="height: 300rpx;" class="w-100 rounded" mode="">image>
swiper-item>
<swiper-item>
<image src="/static/img/banner/banner3.jpg" style="height: 300rpx;" class="w-100 rounded" mode="">image>
swiper-item>
swiper>
<view class="p-2 font-md">最近更新view>
<block v-for="(item, index) in topicList" :key="index">
<view class="flex align-center p-2">
<image class="rounded mr-2" :src="item.cover" style="width: 150rpx; height: 150rpx;">image>
<view class="flex flex-column flex-1">
<text class="font-md text-dark">#{
{item.title}}#text>
<text class="font text-secondry">{
{item.desc}}text>
<view class="flex align-center font text-secondry">
<text class="mr-2">动态:{
{item.news_count}}text>
<text>今日:{
{item.today_count}}text>
view>
view>
view>
block>
scroll-view>
swiper-item>
swiper>
view>
template>
<script>
// 测试数据
const test_data = [{
username: "Corley",
userpic: "/static/img/userpic/12.jpg",
newstime: "2021-01-24 上午11:30",
isFollow: true,
title: "uni-app入门教程",
titlepic: "/static/img/datapic/42.jpg",
support: {
type: "support", // 顶
support_count: 1,
unsupport_count: 2
},
comment_count: 2,
share_count: 2
},
{
username: "Brittany",
userpic: "/static/img/userpic/16.jpg",
newstime: "2021-01-24 下午14:00",
isFollow: true,
title: "商业数据分析从入门到入职",
support: {
type: "unsupport", // 踩
support_count: 2,
unsupport_count: 3
},
comment_count: 5,
share_count: 1
},
{
username: "Jessica",
userpic: "/static/img/userpic/7.jpg",
newstime: "2021-01-24 下午14:44",
isFollow: true,
title: "Django+Vue开发生鲜电商平台",
titlepic: "/static/img/datapic/11.jpg",
support: {
type: "", // 未操作
support_count: 2,
unsupport_count: 7
},
comment_count: 0,
share_count: 2
},
{
username: "Ashley",
userpic: "/static/img/userpic/20.jpg",
newstime: "2021-01-24 下午18:20",
isFollow: true,
title: "uni-app实战之社区交友APP",
titlepic: "/static/img/datapic/30.jpg",
support: {
type: "support",
support_count: 5,
unsupport_count: 1
},
comment_count: 3,
share_count: 0
}
];
import uniNavBar from '@/components/uni-ui/uni-nav-bar/uni-nav-bar.vue';
import commonList from '@/components/common/common-list.vue';
import loadMore from '../../components/common/load-more.vue';
import hotCate from '@/components/news/hot-cate.vue';
export default {
data() {
return {
tabBars: [{
name: '关注'
},
{
name: '话题'
}
],
tabIndex: 0,
scrollH: 500,
// 关注列表
list: [],
loadmore: "上拉加载更多",
hotCate: [
{
name: '关注'
},
{
name: '推荐'
},
{
name: '体育'
},
{
name: '热点'
},
{
name: '财经'
},
{
name: '娱乐'
}
],
topicList: [
{
cover: '/static/img/topicpic/14.jpeg',
title: '毛伟明当选湖南省人民政府省长',
desc: '毛伟明当选湖南省人民政府省长',
news_count: 10,
today_count: 1
},
{
cover: '/static/img/topicpic/2.jpeg',
title: '个别自美赴华乘客篡改阳性记录',
desc: '中国驻旧金山总领馆:个别自美赴华乘客篡改、隐瞒阳性记录',
news_count: 7,
today_count: 2
},
{
cover: '/static/img/topicpic/5.jpeg',
title: '中纪委披露安徽太和县骗保事件',
desc: '安徽省太和县发生骗保事件,中纪委网站披露骗保百般花样',
news_count: 21,
today_count: 3
},
{
cover: '/static/img/topicpic/8.jpeg',
title: '篮网正式签约佩莱',
desc: '对阵篮网4次封盖,13分钟7个篮板,怒帽小乔丹的佩莱加盟篮网',
news_count: 11,
today_count: 2
},
{
cover: '/static/img/topicpic/10.jpeg',
title: '被孟佳团队抄袭图片的模特发文',
desc: '孟佳团队背锅承认抄袭,外国模特发文回应:没有在第一时间联系',
news_count: 7,
today_count: 0
},
{
cover: '/static/img/topicpic/16.jpeg',
title: 'FF将通过并购在纳斯达克上市',
desc: 'FF将通过与PSAC合并在纳斯达克上市;传蚂蚁集团将重组为央行监管的...',
news_count: 15,
today_count: 4
},
{
cover: '/static/img/topicpic/11.jpeg',
title: '"现实版樊胜美"弟弟疑遭人肉网暴',
desc: '现实版樊胜美弟弟疑遭人肉网暴 挂出其母弟弟住址电话',
news_count: 6,
today_count: 0
}
]
}
},
components: {
uniNavBar,
commonList,
loadMore,
hotCate
},
onLoad() {
uni.getSystemInfo({
success: function(res) {
console.log(res);
this.scrollH = res.windowHeight - res.statusBarHeight - 44;
}
}),
// 加载测试数据
this.list = test_data;
},
methods: {
// 打开发布页
openAddInput() {
uni.navigateTo({
url: '../add-input/add-input'
});
},
// 切换选项卡
changeTab(index) {
this.tabIndex = index;
},
// 滑动
onChangeTab(e) {
this.tabIndex = e.detail.current;
},
// 顶踩操作
doSupport(e) {
console.log(e);
// 获取当前列表项
let item = this.list[e.index];
let msg = e.type === 'support' ? '顶' : '踩';
// 之前未顶踩过
if (item.support.type === '') {
item.support[e.type + '_count']++;
}
// 之前已顶过并且现在的操作为踩,则顶-1、踩+1
else if (item.support.type === 'support' && e.type === 'unsupport') {
item.support.support_count--;
item.support.unsupport_count++;
}
// 之前已踩过并且现在的操作为顶,则踩-1、顶+1
else if (item.support.type === 'unsupport' && e.type === 'support') {
item.support.unsupport_count--;
item.support.support_count++;
}
item.support.type = e.type;
uni.showToast({
title: msg + '成功'
})
},
// 上拉加载更多
loadmoreEvent() {
// 验证当前是否处于可加载状态
if (this.loadmore !== '上拉加载更多') return;
// 设置加载状态
this.loadmore = '加载中...';
// 模拟请求数据
setTimeout(() => {
// 加载数据
this.list = [...this.list, ...this.list];
// 设置加载状态
this.loadmore = '上拉加载更多';
}, 2000)
}
}
}
script>
<style>
style>
显示:
此时,已经有话题列表。
再封装组件,components/news下新建topic-list.vue如下:
<template>
<view class="flex align-center p-2">
<image class="rounded mr-2" :src="item.cover" style="width: 150rpx; height: 150rpx;">image>
<view class="flex flex-column flex-1">
<text class="font-md text-dark">#{
{item.title}}#text>
<text class="font text-secondry">{
{item.desc}}text>
<view class="flex align-center font text-secondry">
<text class="mr-2">动态:{
{item.news_count}}text>
<text>今日:{
{item.today_count}}text>
view>
view>
view>
template>
<script>
export default {
props: {
item: Object,
index: Number
},
}
script>
<style>
style>
news.vue如下:
<template>
<view>
<uni-nav-bar :border="false" :fixed="true" :statusBar="true" @clickRight="openAddInput">
<view class="flex align-center justify-center font-weight-bold w-100">
<view class="mx-1" v-for="(item, index) in tabBars" :key="index" :class="tabIndex === index ? 'font-lg text-main' : 'font-md text-light-muted'"
@click="changeTab(index)">{
{item.name}}view>
view>
<text slot="right" class="iconfont icon-fatie_icon">text>
uni-nav-bar>
<swiper :current="tabIndex" :duration="150" :style="'height: '+scrollH+'px;'" @change="onChangeTab">
<swiper-item>
<scroll-view scroll-y="true" :style="'height: '+scrollH+'px;'" @scrolltolower="loadmoreEvent">
<block v-for="(item, index) in list" :key="index">
<common-list :item="item" :index="index" @doSupport="doSupport">common-list>
<divider>divider>
block>
<load-more :loadmore="loadmore">load-more>
scroll-view>
swiper-item>
<swiper-item>
<scroll-view scroll-y="true" :style="'height: '+scrollH+'px;'">
<hot-cate :hotCate="hotCate">hot-cate>
<view class="p-2">
<view class="bg-light rounded flex align-center justify-center py-2 text-secondry">
<text class="iconfont icon-sousuo mr-2">text>搜索话题
view>
view>
<swiper class="px-2 pb-2" :indicator-dots="true" :autoplay="true" :interval="3000" :duration="1000">
<swiper-item>
<image src="/static/img/banner/banner1.jpg" style="height: 300rpx;" class="w-100 rounded" mode="">image>
swiper-item>
<swiper-item>
<image src="/static/img/banner/banner2.jpeg" style="height: 300rpx;" class="w-100 rounded" mode="">image>
swiper-item>
<swiper-item>
<image src="/static/img/banner/banner3.jpg" style="height: 300rpx;" class="w-100 rounded" mode="">image>
swiper-item>
swiper>
<view class="p-2 font-md">最近更新view>
<block v-for="(item, index) in topicList" :key="index">
<topic-list :item="item" :index="index">topic-list>
block>
scroll-view>
swiper-item>
swiper>
view>
template>
<script>
// 测试数据
const test_data = [{
username: "Corley",
userpic: "/static/img/userpic/12.jpg",
newstime: "2021-01-24 上午11:30",
isFollow: true,
title: "uni-app入门教程",
titlepic: "/static/img/datapic/42.jpg",
support: {
type: "support", // 顶
support_count: 1,
unsupport_count: 2
},
comment_count: 2,
share_count: 2
},
{
username: "Brittany",
userpic: "/static/img/userpic/16.jpg",
newstime: "2021-01-24 下午14:00",
isFollow: true,
title: "商业数据分析从入门到入职",
support: {
type: "unsupport", // 踩
support_count: 2,
unsupport_count: 3
},
comment_count: 5,
share_count: 1
},
{
username: "Jessica",
userpic: "/static/img/userpic/7.jpg",
newstime: "2021-01-24 下午14:44",
isFollow: true,
title: "Django+Vue开发生鲜电商平台",
titlepic: "/static/img/datapic/11.jpg",
support: {
type: "", // 未操作
support_count: 2,
unsupport_count: 7
},
comment_count: 0,
share_count: 2
},
{
username: "Ashley",
userpic: "/static/img/userpic/20.jpg",
newstime: "2021-01-24 下午18:20",
isFollow: true,
title: "uni-app实战之社区交友APP",
titlepic: "/static/img/datapic/30.jpg",
support: {
type: "support",
support_count: 5,
unsupport_count: 1
},
comment_count: 3,
share_count: 0
}
];
import uniNavBar from '@/components/uni-ui/uni-nav-bar/uni-nav-bar.vue';
import commonList from '@/components/common/common-list.vue';
import loadMore from '../../components/common/load-more.vue';
import hotCate from '@/components/news/hot-cate.vue';
import topicList from '@/components/news/topic-list.vue';
export default {
data() {
return {
tabBars: [{
name: '关注'
},
{
name: '话题'
}
],
tabIndex: 0,
scrollH: 500,
// 关注列表
list: [],
loadmore: "上拉加载更多",
hotCate: [{
name: '关注'
},
{
name: '推荐'
},
{
name: '体育'
},
{
name: '热点'
},
{
name: '财经'
},
{
name: '娱乐'
}
],
topicList: [{
cover: '/static/img/topicpic/14.jpeg',
title: '毛伟明当选湖南省人民政府省长',
desc: '毛伟明当选湖南省人民政府省长',
news_count: 10,
today_count: 1
},
{
cover: '/static/img/topicpic/2.jpeg',
title: '个别自美赴华乘客篡改阳性记录',
desc: '中国驻旧金山总领馆:个别自美赴华乘客篡改、隐瞒阳性记录',
news_count: 7,
today_count: 2
},
{
cover: '/static/img/topicpic/5.jpeg',
title: '中纪委披露安徽太和县骗保事件',
desc: '安徽省太和县发生骗保事件,中纪委网站披露骗保百般花样',
news_count: 21,
today_count: 3
},
{
cover: '/static/img/topicpic/8.jpeg',
title: '篮网正式签约佩莱',
desc: '对阵篮网4次封盖,13分钟7个篮板,怒帽小乔丹的佩莱加盟篮网',
news_count: 11,
today_count: 2
},
{
cover: '/static/img/topicpic/10.jpeg',
title: '被孟佳团队抄袭图片的模特发文',
desc: '孟佳团队背锅承认抄袭,外国模特发文回应:没有在第一时间联系',
news_count: 7,
today_count: 0
},
{
cover: '/static/img/topicpic/16.jpeg',
title: 'FF将通过并购在纳斯达克上市',
desc: 'FF将通过与PSAC合并在纳斯达克上市;传蚂蚁集团将重组为央行监管的...',
news_count: 15,
today_count: 4
},
{
cover: '/static/img/topicpic/11.jpeg',
title: '"现实版樊胜美"弟弟疑遭人肉网暴',
desc: '现实版樊胜美弟弟疑遭人肉网暴 挂出其母弟弟住址电话',
news_count: 6,
today_count: 0
}
]
}
},
components: {
uniNavBar,
commonList,
loadMore,
hotCate,
topicList
},
onLoad() {
uni.getSystemInfo({
success: function(res) {
console.log(res);
this.scrollH = res.windowHeight - res.statusBarHeight - 44;
}
}),
// 加载测试数据
this.list = test_data;
},
methods: {
// 打开发布页
openAddInput() {
uni.navigateTo({
url: '../add-input/add-input'
});
},
// 切换选项卡
changeTab(index) {
this.tabIndex = index;
},
// 滑动
onChangeTab(e) {
this.tabIndex = e.detail.current;
},
// 顶踩操作
doSupport(e) {
console.log(e);
// 获取当前列表项
let item = this.list[e.index];
let msg = e.type === 'support' ? '顶' : '踩';
// 之前未顶踩过
if (item.support.type === '') {
item.support[e.type + '_count']++;
}
// 之前已顶过并且现在的操作为踩,则顶-1、踩+1
else if (item.support.type === 'support' && e.type === 'unsupport') {
item.support.support_count--;
item.support.unsupport_count++;
}
// 之前已踩过并且现在的操作为顶,则踩-1、顶+1
else if (item.support.type === 'unsupport' && e.type === 'support') {
item.support.unsupport_count--;
item.support.support_count++;
}
item.support.type = e.type;
uni.showToast({
title: msg + '成功'
})
},
// 上拉加载更多
loadmoreEvent() {
// 验证当前是否处于可加载状态
if (this.loadmore !== '上拉加载更多') return;
// 设置加载状态
this.loadmore = '加载中...';
// 模拟请求数据
setTimeout(() => {
// 加载数据
this.list = [...this.list, ...this.list];
// 设置加载状态
this.loadmore = '上拉加载更多';
}, 2000)
}
}
}
script>
<style>
style>
效果与之前相同。
话题分类页和首页类似,可以复用。
需要先新建话题分类页面topic-nav(包括同名目录,本项目创建页面时默认创建同名目录)。
pages.json配置如下:
{
"path" : "pages/topic-nav/topic-nav",
"style" :
{
"navigationBarTitleText": "话题分类",
"enablePullDownRefresh": false
}
}
该页面需要从热点分类组件进入,hot-cate.vue如下:
openMore() {
console.log('opening more');
uni.navigateTo({
url: '../../pages/topic-nav/topic-nav'
});
},
topic-nav.vue页面如下:
<template>
<view>
<scroll-view scroll-x="true" class="scroll-row" :scroll-into-view="scrollInto" :scroll-with-animation="true" style="height: 100rpx;">
<view v-for="(item, index) in tabBars" :key="index" class="scroll-row-item px-3 py-2 font-md" :id="'tab'+index"
:class="tabIndex === index ? 'text-main font-lg font-weight-bold' : ''" @click="changeTab(index)">{
{item.name}}view>
scroll-view>
<swiper :duration="150" :current="tabIndex" @change="onChangeTab" :style="'height: '+scrollH+'px;'">
<swiper-item v-for="(item, index) in topicArray" :key="index">
<scroll-view scroll-y="true" :style="'height: '+scrollH+'px;'" @scrolltolower="loadMore(index)">
<template v-if="item.list.length > 0">
<block v-for="(item2, index2) in item.list" :key="index2">
<topic-list :item="item2" :index="index2">topic-list>
block>
<load-more :loadmore="item.loadmore">load-more>
template>
<template v-else>
<no-thing>no-thing>
template>
scroll-view>
swiper-item>
swiper>
view>
template>
<script>
// 测试数据
const test_data = [{
cover: '/static/img/topicpic/14.jpeg',
title: '毛伟明当选湖南省人民政府省长',
desc: '毛伟明当选湖南省人民政府省长',
news_count: 10,
today_count: 1
},
{
cover: '/static/img/topicpic/2.jpeg',
title: '个别自美赴华乘客篡改阳性记录',
desc: '中国驻旧金山总领馆:个别自美赴华乘客篡改、隐瞒阳性记录',
news_count: 7,
today_count: 2
},
{
cover: '/static/img/topicpic/5.jpeg',
title: '中纪委披露安徽太和县骗保事件',
desc: '安徽省太和县发生骗保事件,中纪委网站披露骗保百般花样',
news_count: 21,
today_count: 3
},
{
cover: '/static/img/topicpic/8.jpeg',
title: '篮网正式签约佩莱',
desc: '对阵篮网4次封盖,13分钟7个篮板,怒帽小乔丹的佩莱加盟篮网',
news_count: 11,
today_count: 2
},
{
cover: '/static/img/topicpic/10.jpeg',
title: '被孟佳团队抄袭图片的模特发文',
desc: '孟佳团队背锅承认抄袭,外国模特发文回应:没有在第一时间联系',
news_count: 7,
today_count: 0
},
{
cover: '/static/img/topicpic/16.jpeg',
title: 'FF将通过并购在纳斯达克上市',
desc: 'FF将通过与PSAC合并在纳斯达克上市;传蚂蚁集团将重组为央行监管的...',
news_count: 15,
today_count: 4
},
{
cover: '/static/img/topicpic/11.jpeg',
title: '"现实版樊胜美"弟弟疑遭人肉网暴',
desc: '现实版樊胜美弟弟疑遭人肉网暴 挂出其母弟弟住址电话',
news_count: 6,
today_count: 0
}
];
import topicList from '@/components/news/topic-list.vue';
import loadMore from '@/components/common/load-more.vue';
export default {
data() {
return {
topicArray: [],
// 顶部选项卡
tabBars: [{
name: '关注'
},
{
name: '推荐'
},
{
name: '体育'
},
{
name: '热点'
},
{
name: '财经'
},
{
name: '娱乐'
},
{
name: '军事'
},
{
name: '历史'
},
{
name: '本地'
}
],
tabIndex: 0,
scrollInto: '',
// 列表高度
scrollH: 600
}
},
components: {
topicList,
loadMore
},
onLoad() {
uni.getSystemInfo({
success: function(res) {
console.log(res);
this.scrollH = res.windowHeight - uni.upx2px(100);
}
}),
// 根据选项生成列表
this.getData();
},
methods: {
// 切换选项
changeTab(index) {
if (this.tabIndex === index) {
return;
}
this.tabIndex = index;
// 滚动到指定元素
this.scrollInto = 'tab' + index;
},
// 监听滑动
onChangeTab(e) {
console.log(e);
this.changeTab(e.detail.current);
},
// 获取数据
getData() {
var arr = [];
for (let i = 0; i < this.tabBars.length; i++) {
// 生成列表模板
let obj = {
// 3种状态:1.上拉加载更多;2.加载中...;3.没有更多了。
loadmore: "上拉加载更多",
list: []
}
if (i % 3 !== 2) {
obj.list = test_data;
}
arr.push(obj)
}
this.topicArray = arr;
},
// 上拉加载更多
loadMore(index) {
// 获取当前列表
let item = this.topicArray[index];
// 判断是否处于可加载状态
if (item.loadmore !== '上拉加载更多') return;
// 修改当前列表加载状态
item.loadmore = '加载中...';
// 模拟数据请求
setTimeout(() => {
// 加载数据
item.list = [...item.list, ...item.list];
// 恢复加载状态
this.topicArray[index].loadmore = '上拉加载更多';
}, 2000)
}
}
}
script>
<style>
style>
显示:
可以看到,实现了话题分类页开发。
先创建话题详情页topic-detail,如下:
<template>
<view>
话题详情
view>
template>
<script>
export default {
data() {
return {
}
},
onLoad(e) {
console.log(e);
if (e.detail) {
let res = JSON.parse(e.detail);
console.log(res);
}
},
methods: {
}
}
script>
<style>
style>
pages.json中配置导航栏样式如下:
{
"path" : "pages/topic-detail/topic-detail",
"style" :
{
"app-plus": {
"titleNView": {
"type":"transparent",
"buttons": [
{
"type":"menu"
}
]
}
}
}
}
topic_list.vue中传递数据如下:
<template>
<view class="flex align-center p-2" @click="open()">
<image class="rounded mr-2" :src="item.cover" style="width: 150rpx; height: 150rpx;">image>
<view class="flex flex-column flex-1">
<text class="font-md text-dark">#{
{item.title}}#text>
<text class="font text-secondry">{
{item.desc}}text>
<view class="flex align-center font text-secondry">
<text class="mr-2">动态:{
{item.news_count}}text>
<text>今日:{
{item.today_count}}text>
view>
view>
view>
template>
<script>
export default {
props: {
item: Object,
index: Number
},
methods: {
open() {
uni.navigateTo({
url: '../../pages/topic-detail/topic-detail?detail='+JSON.stringify(this.item)
});
}
}
}
script>
<style>
style>
topic_list页中在跳转路由后以关键字传参的方式将当前的话题项传递给topic-detail页,数据形式是以detail
为键的对象,topic-detail页中在onLoad()
生命周期中接收并解析获取到传递过来的数据。
显示:
显然,实现了传递数据并跳转到话题详情页。
话题详情页面顶部的话题介绍包括了颜色渐变的图片,下面包含话题的一些信息。
topic-detail.vue如下:
<template>
<view>
<view class="position-relative">
<image src="/static/img/topicpic/12.jpeg" style="height: 300rpx;" class="w-100 filter">image>
view>
<view class="position-relative bg-white px-2" style="z-index: 10;">
<view class="flex">
<image src="/static/img/topicpic/12.jpeg" style="width: 150rpx; height: 150rpx; margin-top: -75rpx;" class="rounded mr-2">image>
<text>#话题标题#text>
view>
<view class="flex align-center font text-secondry mt-1">
<text class="mr-2">动态:10text>
<text>今日:1text>
view>
<view class="font-md text-secondry">话题描述view>
view>
view>
template>
可以看到,话题介绍的布局已经设置好。
再将其封装为组件,components下新建目录topic-detail,下建topic-info.vue组件,如下:
<template>
<view >
<view class="position-relative">
<image :src="info.cover" style="height: 300rpx;" class="w-100 filter">image>
view>
<view class="position-relative bg-white px-2 pb-2" style="z-index: 10;">
<view class="flex">
<image :src="info.cover" style="width: 150rpx; height: 150rpx; margin-top: -75rpx;" class="rounded mr-2">image>
<text>#{
{info.title}}#text>
view>
<view class="flex align-center font text-secondry mt-1">
<text class="mr-2">动态:{
{info.news_count}}text>
<text>今日:{
{info.today_count}}text>
view>
<view class="font-md text-secondry">{
{info.desc}}view>
view>
view>
template>
<script>
export default {
props: ['info']
}
script>
<style>
style>
topic-detail.vue如下:
<template>
<view>
<topic-info :info="info">topic-info>
<divider>divider>
view>
template>
<script>
import topicInfo from '@/components/topic-detail/topic-info.vue';
export default {
data() {
return {
info: {
cover: '/static/img/topicpic/14.jpeg',
title: '毛伟明当选湖南省人民政府省长',
desc: '毛伟明当选湖南省人民政府省长',
news_count: 10,
today_count: 1
}
}
},
components: {
topicInfo
},
onLoad(e) {
console.log(e);
if (e.detail) {
let res = JSON.parse(e.detail);
console.log(res);
}
},
methods: {
}
}
script>
<style>
.filter {
filter: blur(10px);
}
style>
效果与之前相同。
精华帖子也是一个列表,如下:
<template>
<view>
<topic-info :info="info">topic-info>
<divider>divider>
<view class="p-2 flex align-center border-bottom" hover-class="bg-light">
<text class="iconfont icon-zhiding text-main">text>
<text class="font text-dark text-ellipsis">面试之算法基础系列(1)最长子字符串、字符串同构text>
view>
<view class="p-2 flex align-center border-bottom" hover-class="bg-light">
<text class="iconfont icon-zhiding text-main">text>
<text class="font text-dark text-ellipsis">uni-app开发 常见异常和解决办法text>
view>
view>
template>
显示出了精华帖子列表。
还可以优化如下:
<template>
<view>
<topic-info :info="info">topic-info>
<divider>divider>
<block v-for="(item, index) in hotList" :key="index">
<view class="p-2 flex align-center border-bottom" hover-class="bg-light">
<text class="iconfont icon-zhiding text-main">text>
<text class="font text-dark text-ellipsis">{
{item.title}}text>
view>
block>
<divider>divider>
view>
template>
<script>
import topicInfo from '@/components/topic-detail/topic-info.vue';
export default {
data() {
return {
info: {
cover: '/static/img/topicpic/14.jpeg',
title: '毛伟明当选湖南省人民政府省长',
desc: '毛伟明当选湖南省人民政府省长',
news_count: 10,
today_count: 1
},
hotList: [
{
title: '面试之算法基础系列(1)最长子字符串、字符串同构'
},
{
title: 'uni-app开发 常见异常和解决办法'
}
]
}
},
components: {
topicInfo
},
onLoad(e) {
console.log(e);
if (e.detail) {
let res = JSON.parse(e.detail);
console.log(res);
}
},
methods: {
}
}
script>
<style>
.filter {
filter: blur(10px);
}
style>
效果相同。
展示列表选项卡包括默认和最新,展示该话题下的内容。
先实现标签栏,如下:
<view class="flex align-center py-2">
<view class="flex-1 font-lg font-weight-bold text-main flex align-center justify-center">默认view>
<view class="flex-1 font-md flex align-center justify-center">最新view>
view>
已经展示出选项卡。
现进一步实现列表,如下:
<template>
<view>
<topic-info :info="info">topic-info>
<divider>divider>
<block v-for="(item, index) in hotList" :key="'hot'+index">
<view class="p-2 flex align-center border-bottom" hover-class="bg-light">
<text class="iconfont icon-zhiding text-main">text>
<text class="font text-dark text-ellipsis">{
{item.title}}text>
view>
block>
<divider>divider>
<view class="flex align-center py-2">
<view class="flex-1 flex align-center justify-center" v-for="(item ,index) in tabBars" :key="'tab'+index" :class="index === tabIndex ? 'font-lg font-weight-bold text-main' : 'font-md'" @click="changeTab(index)">{
{item.name}}view>
view>
<block v-for="(item, index) in list1" :key="index">
<common-list :item="item" :index="index">common-list>
block>
view>
template>
<script>
// 测试数据
const test_data = [{
username: "Corley",
userpic: "/static/img/userpic/12.jpg",
newstime: "2021-01-24 上午11:30",
isFollow: false,
title: "uni-app入门教程",
titlepic: "/static/img/datapic/42.jpg",
support: {
type: "support", // 顶
support_count: 1,
unsupport_count: 2
},
comment_count: 2,
share_count: 2
},
{
username: "Brittany",
userpic: "/static/img/userpic/16.jpg",
newstime: "2021-01-24 下午14:00",
isFollow: false,
title: "商业数据分析从入门到入职",
support: {
type: "unsupport", // 踩
support_count: 2,
unsupport_count: 3
},
comment_count: 5,
share_count: 1
},
{
username: "Jessica",
userpic: "/static/img/userpic/7.jpg",
newstime: "2021-01-24 下午14:44",
isFollow: true,
title: "Django+Vue开发生鲜电商平台",
titlepic: "/static/img/datapic/11.jpg",
support: {
type: "", // 未操作
support_count: 2,
unsupport_count: 7
},
comment_count: 0,
share_count: 2
},
{
username: "Ashley",
userpic: "/static/img/userpic/20.jpg",
newstime: "2021-01-24 下午18:20",
isFollow: true,
title: "uni-app实战之社区交友APP",
titlepic: "/static/img/datapic/30.jpg",
support: {
type: "support",
support_count: 5,
unsupport_count: 1
},
comment_count: 3,
share_count: 0
}
];
import topicInfo from '@/components/topic-detail/topic-info.vue';
import commonList from '@/components/common/common-list.vue';
export default {
data() {
return {
info: {
cover: '/static/img/topicpic/14.jpeg',
title: '毛伟明当选湖南省人民政府省长',
desc: '毛伟明当选湖南省人民政府省长',
news_count: 10,
today_count: 1
},
hotList: [
{
title: '面试之算法基础系列(1)最长子字符串、字符串同构'
},
{
title: 'uni-app开发 常见异常和解决办法'
}
],
tabIndex: 0,
tabBars: [
{
name: '默认'
},
{
name: '最新'
}
],
list1: [],
list2: []
}
},
components: {
topicInfo,
commonList
},
onLoad(e) {
console.log(e);
if (e.detail) {
let res = JSON.parse(e.detail);
console.log(res);
}
this.list1 = test_data;
this.list2 = test_data
},
methods: {
changeTab(index) {
this.tabIndex = index;
}
}
}
script>
<style>
.filter {
filter: blur(10px);
}
style>
显示:
已经实现了列表展示和标签栏点击。
再利用计算属性实现默认和最新列表切换,如下:
<template>
<view>
<topic-info :info="info">topic-info>
<divider>divider>
<block v-for="(item, index) in hotList" :key="'hot'+index">
<view class="p-2 flex align-center border-bottom" hover-class="bg-light">
<text class="iconfont icon-zhiding text-main">text>
<text class="font text-dark text-ellipsis">{
{item.title}}text>
view>
block>
<divider>divider>
<view class="flex align-center py-2">
<view class="flex-1 flex align-center justify-center" v-for="(item ,index) in tabBars" :key="'tab'+index" :class="index === tabIndex ? 'font-lg font-weight-bold text-main' : 'font-md'"
@click="changeTab(index)">{
{item.name}}view>
view>
<template v-if="listData.length > 0">
<block v-for="(item, index) in listData" :key="index">
<common-list :item="item" :index="index">common-list>
<divider>divider>
block>
template>
<template v-else>
<no-thing>no-thing>
template>
view>
template>
<script>
// 测试数据
const test_data = [{
username: "Corley",
userpic: "/static/img/userpic/12.jpg",
newstime: "2021-01-24 上午11:30",
isFollow: false,
title: "uni-app入门教程",
titlepic: "/static/img/datapic/42.jpg",
support: {
type: "support", // 顶
support_count: 1,
unsupport_count: 2
},
comment_count: 2,
share_count: 2
},
{
username: "Brittany",
userpic: "/static/img/userpic/16.jpg",
newstime: "2021-01-24 下午14:00",
isFollow: false,
title: "商业数据分析从入门到入职",
support: {
type: "unsupport", // 踩
support_count: 2,
unsupport_count: 3
},
comment_count: 5,
share_count: 1
},
{
username: "Jessica",
userpic: "/static/img/userpic/7.jpg",
newstime: "2021-01-24 下午14:44",
isFollow: true,
title: "Django+Vue开发生鲜电商平台",
titlepic: "/static/img/datapic/11.jpg",
support: {
type: "", // 未操作
support_count: 2,
unsupport_count: 7
},
comment_count: 0,
share_count: 2
},
{
username: "Ashley",
userpic: "/static/img/userpic/20.jpg",
newstime: "2021-01-24 下午18:20",
isFollow: true,
title: "uni-app实战之社区交友APP",
titlepic: "/static/img/datapic/30.jpg",
support: {
type: "support",
support_count: 5,
unsupport_count: 1
},
comment_count: 3,
share_count: 0
}
];
import topicInfo from '@/components/topic-detail/topic-info.vue';
import commonList from '@/components/common/common-list.vue';
import noThing from '@/components/common/no-thing.vue';
export default {
data() {
return {
info: {
cover: '/static/img/topicpic/14.jpeg',
title: '毛伟明当选湖南省人民政府省长',
desc: '毛伟明当选湖南省人民政府省长',
news_count: 10,
today_count: 1
},
hotList: [{
title: '面试之算法基础系列(1)最长子字符串、字符串同构'
},
{
title: 'uni-app开发 常见异常和解决办法'
}
],
tabIndex: 0,
tabBars: [{
name: '默认'
},
{
name: '最新'
}
],
// 默认
list1: [],
// 最新
list2: []
}
},
components: {
topicInfo,
commonList,
noThing
},
computed: {
listData() {
return this['list' + (this.tabIndex + 1)];
}
},
onLoad(e) {
console.log(e);
if (e.detail) {
let res = JSON.parse(e.detail);
console.log(res);
}
this.list1 = test_data;
},
methods: {
changeTab(index) {
this.tabIndex = index;
}
}
}
script>
<style>
.filter {
filter: blur(10px);
}
style>
显示:
可以看到,实现了联动动态显示。
这里因为列表不是用scroll-view
组件实现的,因此上拉加载也不能使用@scrolltolower
事件实现,需要使用页面上拉加载事件来实现,即onReachBottom
事件,这是页面滚动到底部的事件,不同于scroll-view滚到底,常用于下拉下一页数据。
topic-detail.vue如下:
<template>
<view>
<topic-info :info="info">topic-info>
<divider>divider>
<block v-for="(item, index) in hotList" :key="'hot'+index">
<view class="p-2 flex align-center border-bottom" hover-class="bg-light">
<text class="iconfont icon-zhiding text-main">text>
<text class="font text-dark text-ellipsis">{
{item.title}}text>
view>
block>
<divider>divider>
<view class="flex align-center py-2">
<view class="flex-1 flex align-center justify-center" v-for="(item ,index) in tabBars" :key="'tab'+index" :class="index === tabIndex ? 'font-lg font-weight-bold text-main' : 'font-md'"
@click="changeTab(index)">{
{item.name}}view>
view>
<template v-if="listData.length > 0">
<block v-for="(item, index) in listData" :key="index">
<common-list :item="item" :index="index">common-list>
<divider>divider>
block>
template>
<template v-else>
<no-thing>no-thing>
template>
<load-more :loadmore="loadtext">load-more>
view>
template>
<script>
// 测试数据
const test_data = [{
username: "Corley",
userpic: "/static/img/userpic/12.jpg",
newstime: "2021-01-24 上午11:30",
isFollow: false,
title: "uni-app入门教程",
titlepic: "/static/img/datapic/42.jpg",
support: {
type: "support", // 顶
support_count: 1,
unsupport_count: 2
},
comment_count: 2,
share_count: 2
},
{
username: "Brittany",
userpic: "/static/img/userpic/16.jpg",
newstime: "2021-01-24 下午14:00",
isFollow: false,
title: "商业数据分析从入门到入职",
support: {
type: "unsupport", // 踩
support_count: 2,
unsupport_count: 3
},
comment_count: 5,
share_count: 1
},
{
username: "Jessica",
userpic: "/static/img/userpic/7.jpg",
newstime: "2021-01-24 下午14:44",
isFollow: true,
title: "Django+Vue开发生鲜电商平台",
titlepic: "/static/img/datapic/11.jpg",
support: {
type: "", // 未操作
support_count: 2,
unsupport_count: 7
},
comment_count: 0,
share_count: 2
},
{
username: "Ashley",
userpic: "/static/img/userpic/20.jpg",
newstime: "2021-01-24 下午18:20",
isFollow: true,
title: "uni-app实战之社区交友APP",
titlepic: "/static/img/datapic/30.jpg",
support: {
type: "support",
support_count: 5,
unsupport_count: 1
},
comment_count: 3,
share_count: 0
}
];
import topicInfo from '@/components/topic-detail/topic-info.vue';
import commonList from '@/components/common/common-list.vue';
import noThing from '@/components/common/no-thing.vue';
import loadMore from '@/components/common/load-more.vue';
export default {
data() {
return {
info: {
cover: '/static/img/topicpic/14.jpeg',
title: '毛伟明当选湖南省人民政府省长',
desc: '毛伟明当选湖南省人民政府省长',
news_count: 10,
today_count: 1
},
hotList: [{
title: '面试之算法基础系列(1)最长子字符串、字符串同构'
},
{
title: 'uni-app开发 常见异常和解决办法'
}
],
tabIndex: 0,
tabBars: [{
name: '默认'
},
{
name: '最新'
}
],
// 默认
list1: [],
loadtext1: '上拉加载更多',
// 最新
list2: [],
loadtext2: '上拉加载更多'
}
},
components: {
topicInfo,
commonList,
noThing
},
computed: {
// 当前列表数据
listData() {
return this['list' + (this.tabIndex + 1)];
},
// 当前下拉加载
loadtext() {
return this['loadtext' + (this.tabIndex + 1)];
}
},
onLoad(e) {
console.log(e);
if (e.detail) {
let res = JSON.parse(e.detail);
console.log(res);
}
this.list1 = test_data;
},
// 触底事件
onReachBottom() {
console.log('Reaching bottom');
this.loadmore();
},
methods: {
changeTab(index) {
this.tabIndex = index;
},
// 上拉加载更多
loadmore() {
// 获取当前列表
let index = this.tabIndex;
// 是否处于可加载状态
if (this.loadtext !== '上拉加载更多') return;
// 设置上拉加载状态
this['loadtext' + (index + 1)] = '加载中...';
// 请求数据
setTimeout(() => {
this['list' + (index + 1)] = [...this['list' + (index + 1)], ...this['list' + (index + 1)]];
this['loadtext' + (index + 1)] = '上拉加载更多';
}, 2000);
}
}
}
script>
<style>
.filter {
filter: blur(10px);
}
style>
显示:
可以看到,实现了切换和加载更多。
使用了计算属性,可以很方便地切换list
和loadtext
。
随着项目的增大,需要对项目进行优化,比如将常用的元素封装为组件,可以提高代码的复用率,包括热门分类、话题列表组件和话题介绍组件等,大大优化了代码结构。