28 搜索功能+话题相关页面+我的页面(js-slice,vuex的...mapState)
搜索功能+话题相关页面+我的页面
(js-slice,vuex的...mapState)
十一 js splice(指定索引为n往后删除或者增加,并返回包含已删除元素(如果有)的数组)
// 从索引为n的位置开始删除n个,添加x1,x2
----1 指定索引为n开始往后删除 ----------
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.splice(0, 1);
// 删除 fruits 中的第一个元素,
// 输出:["Orange", "Apple", "Mango"];
// 返回:['Banana',]
----2 指定索引为n开始往后增加-------------
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.splice(2, 0, "Lemon", "Kiwi");
// 在索引为2的位置开始增加"Lemon", "Kiwi",
//输出:["Banana", "Orange", "Lemon", "Kiwi", "Apple", "Mango"]
----3 指定索引为n开始往后删除,往后增加------
// 又删又增
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.splice(2, 2, "Lemon", "Kiwi");
// 输出: ["Banana", "Orange","Lemon", "Kiwi" ]
// 返回:['Apple','Mango']
十二 搜索文章功能实现
效果图:
功能点:
1 支持根据关键字搜索信息。
1 支持根据关键字下拉刷新。
2 支持上拉加载++页码获取更多信息。
3 搜索历史做了缓存,并且动态排在第一位
思路
遇到这种需求思考路径
1 有几种搜索方式。这个案例有3种
2 先一种一种写,然后想办法复用获取信息(包括获取信息产生的任何效果)代码。
3 比如第一种 点击搜索获取信息获取的就是分页码第一页
4 比如第二种 下拉刷新信息也是获取分页码第一页
5 比如第三种 上拉加载更多就是++分页码获取信息。
要点代码
精炼支持三种搜索复用的getdata
// 监听点击导航搜索按钮
onNavigationBarButtonTap(e) {
if (e.index === 0) {
this.searchEvent()
}
},
// 监听下拉刷新
onPullDownRefresh() {
if(this.searchText == ''){
return uni.stopPullDownRefresh()
}
// 请求数据
this.getData(true,()=>{
uni.stopPullDownRefresh()
})
},
// 监听上拉加载更多
onReachBottom() {
if(this.loadmore != '上拉加载更多'){
return;
}
this.loadmore = '加载中...'
this.getData(false)
},
methods(){
// 搜索事件
searchEvent(){
// 收起键盘
uni.hideKeyboard()
// 添加搜索历史
let index = this.historyList.findIndex(v => v===this.searchText)
if (index!=-1){
this.$U.__toFirst(this.historyList,index)
}else{
// unshift 在原来数据的基础上添加第一个元素。
this.historyList.unshift(this.searchText)
}
// 添加到本地缓存
uni.setStorageSync(this.type+'historyList',JSON.stringify(this.historyList))
// 请求搜索到的数据
this.getData()
},
// 请求数据
getData(isrefresh=true,callback=false){
// isrefresh : 是否从第一页加载?
// 显示loading状态
uni.showLoading({
title: '加载中...',
mask: false
})
this.page = isrefresh ? 1 : this.page+1
// 请求搜索
this.$H.post('/search/'+this.type,{
keyword:this.searchText,
page:this.page
}).then(res=>{
// console.log(res)
let list = res.list.map(v => {
return this.$U.formatCommonList(v)
})
// 渲染页面
this.searchList = isrefresh ? list : [...this.searchList, ...list]
// 加载情况
this.loadmore = list.length < 10 ? '没有更多了':'上拉加载更多'
// 关掉普通加载中动画
uni.hideLoading()
// 给下拉刷新使用的,也是一种思路
if (typeof callback === 'function'){
callback()
}
}).catch(err=>{
this.page--
// 关掉普通加载中动画
uni.hideLoading()
// 给下拉刷新使用的,也是一种思路
if (typeof callback === 'function'){
callback()
}
})
}
}
# ps:
// 数组置顶
__toFirst(arr,index){
if (index != 0) {
arr.unshift(arr.splice(index,1)[0])
}
return arr
}
全部代码
Search.vue
<template>
<view>
<template v-if="searchList.length === 0">
<!-- 搜索历史 -->
<view class="py-2 font-md px-2">搜索历史</view>
<view class="flex flex-wrap">
<view class="border rounded font mx-2 my-1 px-2"
v-for="(item,index) in historyList" :key="index"
hover-class="bg-light"
@click="clickSearchHistory(item)">{{item}}</view>
</view>
</template>
<template v-else>
<!-- 数据列表 -->
<block v-for="(item,index) in searchList" :key="index">
<template v-if="type ==='post'">
<!-- 帖子 -->
<common-list :item="item" :index="index"></common-list>
</template>
<template v-else-if="type === 'topic'">
<!-- 话题 -->
<topic-list :item="item" :index="index"></topic-list>
</template>
<template v-else>
<!-- 用户 -->
<user-list :item="item" :index="index"></user-list>
</template>
</block>
<!-- 上拉加载 -->
<load-more :loadmore="loadmore"></load-more>
</template>
</view>
</template>
<script>
import commonList from '@/components/common/common-list.vue';
import topicList from '@/components/news/topic-list.vue';
import userList from '@/components/user-list/user-list.vue';
import loadMore from '@/components/common/load-more.vue';
export default {
components: {
commonList,
topicList,
userList,
loadMore
},
data() {
return {
searchText:"",
historyList:[],
// 搜索结果
searchList:[],
// 当前搜索类型
type:"post",
page:1,
loadmore:"上拉加载更多"
}
},
// 监听导航输入
onNavigationBarSearchInputChanged(e){
this.searchText = e.text
// console.log(e.text)
},
// 监听点击导航搜索按钮
onNavigationBarButtonTap(e) {
if (e.index === 0) {
this.searchEvent()
}
},
// 监听下拉刷新
onPullDownRefresh() {
if(this.searchText == ''){
return uni.stopPullDownRefresh()
}
// 请求数据
this.getData(true,()=>{
uni.stopPullDownRefresh()
})
},
// 监听上拉加载更多
onReachBottom() {
if(this.loadmore != '上拉加载更多'){
return;
}
this.loadmore = '加载中...'
this.getData(false)
},
onLoad(e) {
if (e.type) {
this.type = e.type
}
let pageTitle = '帖子'
switch (this.type){
case 'post':
pageTitle = '帖子'
break;
case 'topic':
pageTitle = '话题'
break;
case 'user':
pageTitle = '用户'
break;
}
// 修改搜索占位
// #ifdef APP-PLUS
let currentWebview = this.$mp.page.$getAppWebview();
let tn = currentWebview.getStyle().titleNView;
tn.searchInput.placeholder = '搜索'+pageTitle;
currentWebview.setStyle({
titleNView: tn
})
// #endif
// 取出搜索历史
let list = uni.getStorageSync(this.type+'historyList')
if (list) {
this.historyList = JSON.parse(list)
}
},
methods: {
// 点击搜索历史
clickSearchHistory(text){
this.searchText = text
this.searchEvent()
},
// 搜索事件
searchEvent(){
// 收起键盘
uni.hideKeyboard()
// 添加搜索历史
let index = this.historyList.findIndex(v => v===this.searchText)
if (index!=-1){
this.$U.__toFirst(this.historyList,index)
}else{
// unshift 在原来数据的基础上添加第一个元素。
this.historyList.unshift(this.searchText)
}
// 添加到本地缓存
uni.setStorageSync(this.type+'historyList',JSON.stringify(this.historyList))
// 请求搜索到的数据
this.getData()
},
// 请求数据
getData(isrefresh=true,callback=false){
// isrefresh : 是否从第一页加载?
// 显示loading状态
uni.showLoading({
title: '加载中...',
mask: false
})
this.page = isrefresh ? 1 : this.page+1
// 请求搜索
this.$H.post('/search/'+this.type,{
keyword:this.searchText,
page:this.page
}).then(res=>{
// console.log(res)
let list = res.list.map(v => {
return this.$U.formatCommonList(v)
})
// 渲染页面
this.searchList = isrefresh ? list : [...this.searchList, ...list]
// 加载情况
this.loadmore = list.length < 10 ? '没有更多了':'上拉加载更多'
// 关掉普通加载中动画
uni.hideLoading()
// 给下拉刷新使用的,也是一种思路
if (typeof callback === 'function'){
callback()
}
}).catch(err=>{
this.page--
// 关掉普通加载中动画
uni.hideLoading()
// 给下拉刷新使用的,也是一种思路
if (typeof callback === 'function'){
callback()
}
})
}
}
}
</script>
<style>
</style>
十三 话题页
区域效果图:
核心代码:
onLoad() {
uni.getSystemInfo({
success: res => { // 可用屏幕长度理论上(总长-原生导航栏-原生底部栏)当前案例无原生导航栏
// 可用屏幕长度(总长-原生底部栏) - 状态栏长度 - 导航栏长度
this.scrollH = res.windowHeight - res.statusBarHeight - 44
console.log(this.scrollH)
}
})
// 加载测试数据
this.list = demo
// 获取热门分类
this.getTopicNav()
// 获取最近更新话题
this.getHotTopic()
// 获取轮播图
this.getSwipers()
},
methods: {
// 获取热门分类
getTopicNav(){
this.$H.get('/topicclass').then(res=>{
console.log(res)
this.hotCate = res.list.map(item=>{
return {
id:item.id,
name:item.classname
}
})
})
},
// 获取热门话题,后端并没有真正做出来热门话题得效果
getHotTopic(){
this.$H.get('/hottopic').then(res=>{
console.log(res)
this.topicListData = res.list.map(item=>{
return {
id:item.id,
cover:item.titlepic,
title:item.title,
desc:item.desc,
today_count:item.todaypost_count,// 该话题今日发布的文章数量
news_count:item.post_count // 该话题总共的文章数量
}
})
})
},
// 获取轮播图
getSwipers(){
this.$H.get('/adsense/0').then(res=>{
console.log(res)
this.swiperList = res.list
})
},
全部代码:
<template>
<view>
<uni-nav-bar :border="false" :fixed="true" :statusBar="true" @click-right="openAddInput">
<view class="flex align-center justify-center font-weight-bold w-100">
<view class="mx-1" @click="changeTab(index)" :class="tabIndex === index ? 'text-main font-lg':'font-md text-light-muted'"
v-for="(item,index) in tabBars" :key="index">
{{item.name}}
</view>
</view>
<template slot="right">
<text class="iconfont icon-fatie_icon"></text>
</template>
</uni-nav-bar>
<swiper :duration="150" :current="tabIndex" @change="onChangeTab" :style="'height:'+scrollH+'px'">
<!-- 关注 -->
<!-- 会默认分配索引 0 1 2 3 4 5 -->
<swiper-item>
<scroll-view scroll-y="true" :style="'height:'+scrollH+'px;'" @scrolltolower="loadmoreEvent">
<view v-for="(item,index) in list" :key="index">
<common-list :item="item" :index="index" @doSupport="doSupport"></common-list>
<divider></divider>
</view>
<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" @click="openSearch">
<view class="rounded w-100 flex align-center justify-center py-2" style="background-color: #F1F1F1;">
<text class="iconfont icon-sousuo"></text>
搜索话题
</view>
</view>
<!-- 轮播图 -->
<swiper class="p-2"
:indicator-dots="true" :autoplay="true"
:interval="3000" :duration="1000">
<swiper-item v-for="(item,index) in swiperList" :key="index">
<image :src="item.src"
style="height: 300rpx;" class="w-100 rounded"></image>
</swiper-item>
</swiper>
<divider></divider>
<!-- 最近更新 -->
<view class="p-2 font-md">热门话题</view>
<!-- 话题列表 -->
<block v-for="(item,index) in topicListData" :key="index">
<topic-list :item="item" :index="index"></topic-list>
</block>
</scroll-view>
</swiper-item>
</swiper>
</view>
</template>
<script>
const demo = [{
username: "昵称",
userpic: "/static/default.jpg",
newstime: "2019-10-20 下午04:30",
isFollow: true,
title: "我是标题",
titlepic: "/static/demo/datapic/11.jpg",
support: {
type: "support", // 顶
support_count: 1,
unsupport_count: 2
},
comment_count: 2,
share_num: 2
},
{
username: "昵称",
userpic: "/static/default.jpg",
newstime: "2019-10-20 下午04:30",
isFollow: true,
title: "我是标题",
titlepic: "",
support: {
type: "unsupport", // 踩
support_count: 1,
unsupport_count: 2
},
comment_count: 2,
share_num: 2
},
{
username: "昵称",
userpic: "/static/default.jpg",
newstime: "2019-10-20 下午04:30",
isFollow: true,
title: "我是标题",
titlepic: "",
support: {
type: "", // 未操作
support_count: 1,
unsupport_count: 2
},
comment_count: 2,
share_num: 2
}
];
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 {
components: {
uniNavBar,
commonList,
loadMore,
hotCate,
topicList
},
data() {
return {
tabIndex: 0,
tabBars: [{
name: "关注"
}, {
name: "话题"
}],
scrollH: 500,
list: [],
loadmore:'下拉加载更多',
hotCate:[],
topicListData:[],
swiperList:[]
}
},
onLoad() {
uni.getSystemInfo({
success: res => { // 可用屏幕长度理论上(总长-原生导航栏-原生底部栏)当前案例无原生导航栏
// 可用屏幕长度(总长-原生底部栏) - 状态栏长度 - 导航栏长度
this.scrollH = res.windowHeight - res.statusBarHeight - 44
console.log(this.scrollH)
}
})
// 加载测试数据
this.list = demo
// 获取热门分类
this.getTopicNav()
// 获取最近更新话题
this.getHotTopic()
// 获取轮播图
this.getSwipers()
},
methods: {
// 获取热门分类
getTopicNav(){
this.$H.get('/topicclass').then(res=>{
console.log(res)
this.hotCate = res.list.map(item=>{
return {
id:item.id,
name:item.classname
}
})
})
},
// 获取热门话题,后端并没有真正做出来热门话题得效果
getHotTopic(){
this.$H.get('/hottopic').then(res=>{
console.log(res)
this.topicListData = res.list.map(item=>{
return {
id:item.id,
cover:item.titlepic,
title:item.title,
desc:item.desc,
today_count:item.todaypost_count,// 该话题今日发布的文章数量
news_count:item.post_count // 该话题总共的文章数量
}
})
})
},
// 获取轮播图
getSwipers(){
this.$H.get('/adsense/0').then(res=>{
console.log(res)
this.swiperList = res.list
})
},
openSearch(){
uni.navigateTo({
url:'../search/search?type=topic'
})
},
changeTab(index) {
this.tabIndex = index
},
openAddInput() {
uni.navigateTo({
url: '../add-input/add-input'
})
},
onChangeTab(e) {
this.tabIndex = e.detail.current
},
// 子组件触发的点赞点踩
// 顶踩操作
doSupport(e) {
// 拿到当前队对象
let item = this.list[e.index]
let msg = e.type === 'support' ? '顶' : '踩'
if (item.support.type === '') {
item.support[e.type + '_count']++
} else if (item.support.type === 'support' && e.type === 'unsupport') {
// 顶 -1
item.support.support_count--;
// 踩 +1
item.support.unsupport_count++;
} else if (item.support.type === 'unsupport' && e.type === 'support') {
// 踩 -1
item.support.unsupport_count--;
// 顶 +1
item.support.support_count++;
}
item.support.type = e.type
uni.showToast({
title: msg + '成功'
})
},
// 触发触底事件
loadmoreEvent(){
// 修改当前加载状态
this.loadmore = '加载中。。。'
// 模拟数据请求
setTimeout(()=>{
// 加载数据
// ... 相当于取出来当前对象可以遍历出来的内容放到了当前对象里面。
// 这个可以粗糙的理解为把合并了两个一摸一样的列表,列表里面原来的内容*2了
this.list = [...this.list,...this.list]
this.loadmore = '上拉加载更多'
},2000)
},
},
}
</script>
<style>
</style>
十四 话题分类页实现
效果图
思路:
同标题六首页效果图一样。
全部代码:
<template>
<view>
<!-- 顶部选项卡 -->
<scroll-view scroll-x :scroll-into-view="scrollInto" scroll-with-animation
class="scroll-row border-bottom border-light-secondary"
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.classname}}</view>
</scroll-view>
<swiper :duration="150" :current="tabIndex" @change="onChangeTab"
:style="'height:'+scrollH+'px;'">
<swiper-item v-for="(item,index) in newsList" :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-if="!item.firstLoad">
<view class="text-light-muted flex align-center justify-center font-md" style="height: 200rpx;">加载中...</view>
</template>
<!-- 无数据 -->
<template v-else>
<no-thing></no-thing>
</template>
</scroll-view>
</swiper-item>
</swiper>
</view>
</template>
<script>
import topicList from '@/components/news/topic-list.vue';
import loadMore from '@/components/common/load-more.vue';
export default {
components: {
topicList,
loadMore
},
data() {
return {
// 列表高度
scrollH:600,
// 顶部选项卡
scrollInto:"",
tabIndex:0,
tabBars: [],
newsList:[]
}
},
// 监听点击导航栏搜索框
onNavigationBarSearchInputClicked() {
uni.navigateTo({
url: '../search/search',
})
},
// 监听导航按钮点击事件
onNavigationBarButtonTap() {
uni.navigateTo({
url: '../add-input/add-input',
})
},
onLoad() {
uni.getSystemInfo({
success:res=>{
this.scrollH = res.windowHeight - uni.upx2px(101)
}
})
// 根据选项生成列表
this.getData()
},
methods: {
// 获取数据
getData(){
// 获取分类
this.$H.get('/topicclass').then(res=>{
// 渲染分类
this.tabBars = res.list
var arr = []
for (let i = 0; i < this.tabBars.length; i++) {
// 生成列表模板
let obj = {
// 1.上拉加载更多 2.加载中... 3.没有更多了
loadmore:"上拉加载更多",
list:[],
page:1,
firstLoad:false // 是否经过第一次加载?
}
arr.push(obj)
}
this.newsList = arr
// 获取当前tabIndex的分类的数据
if (this.tabBars.length) {
this.getList()
}
})
},
// 获取指定分类下的列表
getList(){
let index = this.tabIndex
let id = this.tabBars[index].id
let page = this.newsList[index].page
let isrefresh = page === 1
this.$H.get('/topicclass/'+id+'/topic/'+page)
.then(res=>{
let list = res.list.map(v=>{
return {
id:v.id,
cover:v.titlepic,
title:v.title,
desc:v.desc,
today_count:v.todaypost_count,
news_count:v.post_count
}
})
this.newsList[index].list = isrefresh ? [...list] : [...this.newsList[index].list,...list];
this.newsList[index].loadmore = list.length < 10 ? '没有更多了' : '上拉加载更多';
if (isrefresh) {
this.newsList[index].firstLoad = true
}
}).catch(err=>{
if(!isrefresh){
this.newsList[index].page--;
}
})
},
// 监听滑动
onChangeTab(e){
this.changeTab(e.detail.current)
},
// 切换选项
changeTab(index){
if (this.tabIndex === index) {
return;
}
this.tabIndex = index
// 滚动到指定元素
this.scrollInto = 'tab'+index
// 获取当前分类下的列表数据
if (!this.newsList[this.tabIndex].firstLoad) {
this.getList()
}
},
// 上拉加载更多
loadmore(index){
// 拿到当前列表
let item = this.newsList[index]
// 判断是否处于可加载状态(上拉加载更多)
if (item.loadmore !== '上拉加载更多') return;
// 修改当前列表加载状态
item.loadmore = '加载中...'
// 请求数据
item.page++;
this.getList()
}
}
}
</script>
<style>
</style>
十五 话题详情交互实现
效果图:
思路:
1 正常onload会获取哪些数据分析好
2 主要长的数据列表哪几个场景会调用?并且兼容几种调用方式。
全部代码:
<template>
<!-- 导航图 -->
<view>
<!-- 标题信息组件 -->
<topic-info :info="info"></topic-info>
<divider></divider>
<!-- 置顶帖子 -->
<view class="p-2 flex align-center border-bottom">
<text class="iconfont icon-xihuan text-main "></text>
<text class="font text-ellipsis">【新人必读】uni-app实战第二季商城类项目开发实战第二季商城类项目开发</text>
</view>
<view class="p-2 flex align-center border-bottom">
<text class="iconfont icon-xihuan text-main "></text>
<text class="font text-ellipsis">【新人必读】uni-app实战第二季商城类项目开发实战第二季商城类项目开发</text>
</view>
<divider></divider>
<!-- 默认更新选项卡 -->
<view class="p-2 flex">
<view class="font flex-1 flex align-center justify-center font-weight-bold"
v-for="(item,index) in tabBars" :key="index"
:class="index===tabIndex?'text-main font-lg':''"
@click="changeTab(index)"
>{{item.name}}</view>
</view>
<!-- 列表组件 -->
<!-- 这个列表组件的联动逻辑是通过计算属性,统一循环一个计算变量,这个变量的值是由tabList决定的 -->
<template v-if="listData.length >0">
<block v-for="(item,index) in listData" :key="index">
<common-list :item="item" :index="index"></common-list>
</block>
</template>
<template v-else>
<no-thing></no-thing>
<no-thing></no-thing>
<no-thing></no-thing>
</template>
<!-- 上拉加载 -->
<load-more :loadmore="loadtext"></load-more>
</view>
</template>
<script>
const demo = [{
username:"昵称",
userpic:"/static/default.jpg",
newstime:"2019-10-20 下午04:30",
isFollow:false,
title:"我是标题",
titlepic:"/static/demo/datapic/11.jpg",
support:{
type:"support", // 顶
support_count:1,
unsupport_count:2
},
comment_count:2,
share_num:2
},
{
username:"昵称",
userpic:"/static/default.jpg",
newstime:"2019-10-20 下午04:30",
isFollow:false,
title:"我是标题",
titlepic:"",
support:{
type:"unsupport", // 踩
support_count:1,
unsupport_count:2
},
comment_count:2,
share_num:2
},
{
username:"昵称",
userpic:"/static/default.jpg",
newstime:"2019-10-20 下午04:30",
isFollow:false,
title:"我是标题",
titlepic:"",
support:{
type:"", // 未操作
support_count:1,
unsupport_count:2
},
comment_count:2,
share_num:2
}];
import topicInfo from '@/components/topic-detail/topic-info.vue'
import commonList from '@/components/common/common-list.vue'
import loadMore from '@/components/common/load-more.vue'
export default {
components:{
topicInfo,
commonList,
loadMore
},
data() {
return {
info:{},
tabBars:[{
name:"默认"
},{
name:"最新"
}],
tabIndex:0,
list1:[],
loadtext1:"上拉加载更多",
firstLoad1:false, // 是否经过第一次加载了?
page1:1,
list2:[],
loadtext2:"上拉加载更多",
firstLoad2:false,
page2:1
}
},
computed:{
listData(){
if (this.tabIndex===0){
return this.list1
}
return this.list2
},
loadtext(){
if (this.tabIndex === 0){
return this.loadtext1
}
return this.loadtext2
}
},
onLoad(e){
if (e.detail) {
this.info = JSON.parse(e.detail)
uni.setNavigationBarTitle({
title:this.info.title
})
}
this.getData();
},
// 触底事件
onReachBottom(){
this.loadmorefunc()
},
methods: {
changeTab(index){
this.tabIndex = index
// 切换tag有可能调用,已经第一次加载过了就不要再调用了
if (!this['firstLoad'+(index+1)]){
this.getData()
}
},
// 打开页面调用一次
// 下拉加载调用
// 切换tag有可能调用
getData(){
let no = this.tabIndex+1
let page = this['page'+no]
this.$H.get('/topic/'+this.info.id+'/post/'+page).then(res=>{
//console.log(res)
let list = res.list.map(v=>{
return this.$U.formatCommonList(v)
})
// 是否经过第一次加载了?
this['list'+no] = this['firstLoad'+no] ? [...this['list'+no],...list] : [...list],
this['loadtext'+no] = list<10 ? '没有更多了' : '上拉加载更多'
// 如果是第一次的情况会走这里,需要把加载状态,变成第一次已经加载过。
if (!this['firstLoad'+no]){
this['firstLoad'+no] = true
}
}).catch(err=>{
// 如果第一次已经加载过了,就是下拉加载更多的情况,请求失败就应该--
if (this['firstLoad'+no]){
this['page'+no]--
}
})
},
loadmorefunc(){
// 拿到当前索引
let index = this.tabIndex
// 判断是否处于可加载状态
if (this['loadtext'+(index+1)] !== '上拉加载更多') return;
// 设置上拉加载状态处于加载中。。。
this['loadtext'+(index+1)] = "加载中..."
// 模拟请求数据
this['page'+(index+1)]++
this.getData()
}
}
}
</script>
<style>
</style>
十六 搜索话题交互实现
修改原来search.vue的代码。加了个swich case 兼容了搜索话题。
// 请求数据
getData(isrefresh=true,callback=false){
// isrefresh : 是否从第一页加载?
// 显示loading状态
uni.showLoading({
title: '加载中...',
mask: false
})
this.page = isrefresh ? 1 : this.page+1
// 请求搜索
this.$H.post('/search/'+this.type,{
keyword:this.searchText,
page:this.page
}).then(res=>{
let list = []
switch (this.type){
case 'post':
list = res.list.map(v => {
return this.$U.formatCommonList(v)
})
break;
case 'topic':
list = res.list.map(v=>{
return {
id:v.id,
cover:v.titlepic,
title:v.title,
desc:v.desc,
today_count:v.todaypost_count,
news_count:v.post_count
}
})
break;
case 'user':
break;
}
// 渲染页面
this.searchList = isrefresh ? list : [...this.searchList, ...list]
// 加载情况
this.loadmore = list.length < 10 ? '没有更多了':'上拉加载更多'
// 关掉普通加载中动画
uni.hideLoading()
// 给下拉刷新使用的,也是一种思路
if (typeof callback === 'function'){
callback()
}
}).catch(err=>{
this.page--
// 关掉普通加载中动画
uni.hideLoading()
// 给下拉刷新使用的,也是一种思路
if (typeof callback === 'function'){
callback()
}
})
十六 我的页面完善(涉及vuex知识点:...mapState)
效果图:
要点:
监听vuex 里面的state ,以及修改state里面的相关用法。
<script>
import uniListItem from '@/components/uni-ui/uni-list-item/uni-list-item.vue'
// 导入vuex的助手函数
import outerLogin from '@/components/common/outer-login.vue';
import { mapState } from 'vuex'
export default {
components:{
uniListItem,
outerLogin
},
data() {
return {
myData:[{
name:"帖子",
num:1
},{
name:"动态",
num:1
},{
name:"评论",
num:2
},{
name:"粉丝",
num:0
}]
}
},
// 监听导航条按钮
onNavigationBarButtonTap(){
uni.navigateTo({
url:'../user-set/user-set'
})
},
computed:{
// 看这里 看这里 看这里
// 1 放到计算属性是为了更精准的监听state里面的变化
// 2 放到mapState里面是为了少些几行代码,相当于语法糖吧更加方便管理(当然了直接写成普通的计算属性也行) // 如:count () { return this.$store.state.count }
// 3 为了和其他的计算属性不冲突需要+...进行打散
...mapState({
// 4 这相当于loginStatus 是vue的那个loginstatus了 ,他地方就可以this.调用
loginStatus:state=>state.loginStatus,
// 5 如果名字一样也可以 不用对象可以直接写...mapState(['loginStatus'])
})
// 6 多说一点改变vuex里面的state里面的数据,一定要用commit的形式,方便vue追踪数据变化。
},
methods: {
}
}
</script>
全部代码:
<template>
<view >
<!-- 为了测试login页面 -->
<!-- <navigator url="../login/login">
</navigator> -->
<template v-if="!loginStatus">
<view class="flex align-center justify-center font font-weight-bold my-2">
登录社区,体验更多功能
</view>
<outer-login></outer-login>
<view class="flex align-center justify-center font text-secondary my-2">
账号/邮箱/手机登录 <text class="ml-1 iconfont icon-jinru"></text>
</view>
</template>
<view v-else class="flex px-2 py-3 align-center">
<image src="/static/default.jpg" class="rounded-circle mr-2" style="height: 100rpx;width: 100rpx;" mode=""></image>
<view class="flex-1 flex flex-column ">
<text class="font-lg font-weight-bold">123123123123</text>
<view class="font text-muted">
<text class="mr-3 ">总帖子 1</text>
<text>今日发帖 0</text>
</view>
</view>
<text class="iconfont icon-jinru font-lg"></text>
</view>
<view class="flex align-center px-2">
<view class="flex-1 flex flex-column align-center justify-center"
v-for="(item,index) in myData" :key="index">
<text class="font-lg font-weight-bold">{{item.num}}</text>
<text class="font text-muted">{{item.name}}</text>
</view>
</view>
<!-- 广告栏 -->
<view class="px-2 py-3">
<image src="/static/demo/banner2.jpg"
class="w-100 rounded"
style="height: 170rpx;" mode="aspectFill"></image>
</view>
<!-- 三个小列表 -->
<uni-list-item :show-extra-icon="true" title="浏览历史">
<text slot="myicon" class="iconfont icon-liulan"></text>
</uni-list-item>
<uni-list-item :show-extra-icon="true" title="社区认证">
<text slot="myicon" class="iconfont icon-huiyuanvip"></text>
</uni-list-item>
<uni-list-item :show-extra-icon="true" title="审核帖子">
<text slot="myicon" class="iconfont icon-keyboard"></text>
</uni-list-item>
</view>
</template>
<script>
import uniListItem from '@/components/uni-ui/uni-list-item/uni-list-item.vue'
// 导入vuex的助手函数
import outerLogin from '@/components/common/outer-login.vue';
import { mapState } from 'vuex'
export default {
components:{
uniListItem,
outerLogin
},
data() {
return {
myData:[{
name:"帖子",
num:1
},{
name:"动态",
num:1
},{
name:"评论",
num:2
},{
name:"粉丝",
num:0
}]
}
},
// 监听导航条按钮
onNavigationBarButtonTap(){
uni.navigateTo({
url:'../user-set/user-set'
})
},
computed:{
// 看这里 看这里 看这里
// 1 放到计算属性是为了更精准的监听state里面的变化
// 2 放到mapState里面是为了少些几行代码,相当于语法糖吧更加方便管理(当然了直接写成普通的计算属性也行)
// 3 为了和其他的计算属性不冲突需要+...进行打散
...mapState({
// 4 这相当于loginStatus 是vue的那个loginstatus了 ,他地方就可以this.调用
loginStatus:state=>state.loginStatus,
// 5 如果名字一样也可以 不用对象可以直接写...mapState(['loginStatus'])
})
// 6 多说一点改变vuex里面的state里面的数据,一定要用commit的形式,方便vue追踪数据变化。
},
methods: {
}
}
</script>
<style>
</style>