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']

十二 搜索文章功能实现

效果图:

image-20200423152256819

功能点:

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>

十三 话题页

区域效果图:

image-20200423152350083

核心代码:

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>

十四 话题分类页实现

效果图

image-20200423170108621

思路:

同标题六首页效果图一样。

全部代码:

<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>

十五 话题详情交互实现

效果图:

image-20200423183440846

思路:

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)

效果图:

image-20200423212816465

image-20200423212853740

要点:

监听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>

posted @ 2020-04-24 12:42  张明岩  阅读(165)  评论(0编辑  收藏  举报