17 uniapp-帖子详情页面(复用common-list组件,预览图片,数组map()函数,分享组件)

17 帖子详情页面(复用common-list组件,预览图片,数组map()函数,分享组件)

纵览效果图:

image-20200409163350932

image-20200409163331339

一 设置跳转+导航条

1 跳转到该页面

在components/common/common-list.vue里面

  • 点击标题跳转
  • 点击图片跳转
  • 点击评论跳转
  • 点击转发跳转
// 进入详情页
			openDetail(){
				uni.navigateTo({
					url:'../../pages/detail/detail?detail='+JSON.stringify(this.item)
				})
			},

2 pages.json配置

,{
            "path" : "pages/detail/detail",
            "style" : {
				"app-plus":{
					"titleNView":{
						"buttons":[{
							"type":"menu",
							"float":"right"
						}]
					}
				}
			}
        }

3 接受传来的参数

<template>
	<view>
		
	</view>
</template>

<script>
	export default {
		data() {
			return {
				
			}
		},
		// 接受传参
		onLoad(e) {
			// 初始化
			if (e.detail){
				this.__init(JSON.parse(e.detail))
			}
			
		},
		methods: {
			__init(data){
				// 修改标题
				uni.setNavigationBarTitle({
					title:data.title
				})
			}
		}
	}
</script>

<style>

</style>

二 大体实现详情页面(迭代服用组件思想)

迭代组件复用思想

如果已经有别的组件引用该组件了,尽量在不修改别的组件使用方法的基础上适配兼容新的组件。

效果图:

image-20200408215016741

image-20200408215043712

一 修改原有common-list.vue

设计插槽:

image-20200408215234901

<slot>
			<!-- 标题 -->
			<view class="font-md my-1" 
			@click="openDetail">{{item.title}}</view>
			<!-- 图片 -->
			<image v-if="item.titlepic" :src="item.titlepic" style="height: 350rpx;" class="rounded w-100"
			@click="openDetail"></image>
		</slot>

定制接受父组件传入参数(兼容原来的参数)

props: {
			item: Object,
			index: {
				type:Number,
				default:-1
			},
			isdetail:{
				type:Boolean,
				default:false
			}
		},

修改进入详情页(为其增加前提以防止自己跳自己)

// 进入详情页
			openDetail(){
				if (this.isdetail) return;
				uni.navigateTo({
					url:'../../pages/detail/detail?detail='+JSON.stringify(this.item)
				})
			},

二 pages/detail/detai.vue

Ps:调用子组件中间的内容即为插槽内容。

<template>
	<view>
		<common-list :item='info' isdetail>
		
				<view class="flex font-md align-center">
					{{info.title}}
				</view>
				<view class="flex font align-center">
					{{info.content}}
				</view>
				<!-- widthFix这个只是裁剪方式,跟具体宽度无关 -->
				<image v-for="(item,index) in info.images" :key="index"
				:src="item.url" class='w-100' mode="widthFix"></image>
			
		</common-list>
	</view>
</template>

<script>
	import commonList from '@/components/common/common-list.vue'
	export default {
		components:{
			commonList
		},
		data() {
			return {
				// 当前帖子信息
				info:{
					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,
					content:"帝莎编程学院:uni-app第二季仿商城类实战项目开发,uni-app第二季仿微信实战项目开发",
					images:[{
						url:"https://tangzhe123-com.oss-cn-shenzhen.aliyuncs.com/Appstatic/qsbk/demo/datapic/4.jpg"
					},{
						url:"https://tangzhe123-com.oss-cn-shenzhen.aliyuncs.com/Appstatic/qsbk/demo/datapic/5.jpg"
					}]
				}
			}
		},
		// 接受传参
		onLoad(e) {
			// 初始化
			if (e.detail){
				this.__init(JSON.parse(e.detail))
			}
			
		},
		methods: {
			__init(data){
				// 修改标题
				console.log(data)
				uni.setNavigationBarTitle({
					title:data.title
				})
			}
		}
	}
</script>

<style>

</style>

三 点赞、点踩、关注、图片预览实现(预览图片,map()使用)

要点:

1 map()使用:

...
info:{
					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,
					content:"帝莎编程学院:uni-app第二季仿商城类实战项目开发,uni-app第二季仿微信实战项目开发",
					images:[{
						url:"https://tangzhe123-com.oss-cn-shenzhen.aliyuncs.com/Appstatic/qsbk/demo/datapic/4.jpg"
					},{
						url:"https://tangzhe123-com.oss-cn-shenzhen.aliyuncs.com/Appstatic/qsbk/demo/datapic/5.jpg"
					}]
				}

...

computed: {
			imagesList() {
							//数组取出来每个元素,然后每个元素进行操作后,组成新的数组。 
				return this.info.images.map(item=>item.url) 
			}
		},
...

2 预览图片:

// 预览图片
			preview(index){
				// 预览图片
				uni.previewImage({
					current:index,
					urls:this.imagesList
				})
			}

pages/detail/detai.vue 全部代码

<template>
	<view>
		<common-list :item='info' isdetail 
		@follow="follow"
		@doSupport="doSupport">
			
				<view class="flex font-md align-center">
					{{info.title}}
				</view>
				<view class="flex font align-center">
					{{info.content}}
				</view>
				<!-- widthFix这个只是裁剪方式,跟具体宽度无关 -->
				<image v-for="(item,index) in info.images" :key="index"
				:src="item.url" class='w-100' mode="widthFix"
				@click="preview(index)"></image>
		
		</common-list>
	</view>
</template>

<script>
	import commonList from '@/components/common/common-list.vue'
	export default {
		components:{
			commonList
		},
		data() {
			return {
				// 当前帖子信息
				info:{
					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,
					content:"帝莎编程学院:uni-app第二季仿商城类实战项目开发,uni-app第二季仿微信实战项目开发",
					images:[{
						url:"https://tangzhe123-com.oss-cn-shenzhen.aliyuncs.com/Appstatic/qsbk/demo/datapic/4.jpg"
					},{
						url:"https://tangzhe123-com.oss-cn-shenzhen.aliyuncs.com/Appstatic/qsbk/demo/datapic/5.jpg"
					}]
				}
			}
		},
		computed:{
			imagesList(){
				
								//数组取出来每个元素,然后每个元素进行操作后,组成新的数组。 
				return this.info.images.map(item=>item.url)
			}
		},
		// 接受传参
		onLoad(e) {
			// 初始化
			if (e.detail){
				this.__init(JSON.parse(e.detail))
			}
			
		},
		methods: {
			__init(data){
				// 修改标题
				console.log(data)
				uni.setNavigationBarTitle({
					title:data.title
				})
			},
			// 子组件触发的关注事件
			follow(){
				this.info.isFollow = true
				uni.showToast({
					title:'关注成功'
				})
			},
			// 子组件触发的顶踩事件
			doSupport(e){
				// 之前操作过
				if (this.info.support.type === e.type) {
					return uni.showToast({
						title: '你已经操作过了',
						icon: 'none'
					});
				}
				let msg = e.type === 'support' ? '顶' : '踩'
				// 之前没有操作过
				if (this.info.support.type === '') {
					this.info.support[e.type+'_count']++
				}else if(this.info.support.type === 'support' && e.type === 'unsupport'){				
					// 顶 - 1
					this.info.support.support_count--;
					// 踩 + 1
					this.info.support.unsupport_count++;
				}else if(this.info.support.type === 'unsupport' && e.type === 'support'){			   
					// 顶 + 1
					this.info.support.support_count++;
					// 踩 - 1
					this.info.support.unsupport_count--;
				}
				this.info.support.type = e.type
				uni.showToast({
					title: msg
				});
			},
			// 预览图片
			preview(index){
				// 预览图片
				uni.previewImage({
					current:index,
					urls:this.imagesList
				})
			}
		}
	}
</script>

<style>

</style>

四 评论输入框组件封装

一 把原来的pages/user-chart/user-chart.vue的输入框部分进行封装。

Components/common/bottom-input.vue

<template>
	<view style="height: 100rpx;"
	class="fixed-bottom flex align-center border-top bg-white">
	
		<input type="text" v-model="content" class="flex-1 rounded bg-light ml-2" style="padding: 5rpx;" placeholder="文明发言" @confirm="submit"/>
		
		<view class="iconfont icon-fabu flex align-center justify-center font-lg animated" hover-class="jello text-main" style="width: 100rpx;" @click="submit"></view>
		
	</view>
</template>

<script>
	export default {
		data() {
			return {
				content: ""
			}
		},
		methods: {
			submit() {
				// 是否为空
				if (this.content === '') {
					return uni.showToast({
						title: '消息不能为空',
						icon: 'none'
					});
				}
				this.$emit('submit',this.content)
				// 清空输入框
				this.content = ''
			}
		},
	}
</script>

<style>
</style>

pages/user-chart/user-chart.vue

...	
<!-- 底部操作条 -->
		<bottom-input @submit="submit"></bottom-input>
...
submit(data){
				let obj = {
					user_id:1,
					avatar:"/static/default.jpg",
					username:"昵称",
					type:"text", 
					data:data,
					create_time:(new Date()).getTime()
				}
				this.list.push(obj)
				// 滚动到底部
				this.pageToBottom()
			},

二 在详情页面嵌入评论组件和评论标签内容

效果图:

ps:并没有真的作出评论功能,只做了个样式

image-20200409220540135

代码:

		# 评论标签-------------
    # 评论标签代码是copy的hello-uniapp里的代码
		<divider></divider>
		<view class="p-2 font-md font-weight-bold">
			最新评论 3
		</view>
		<view class="px-2">
			<view class="uni-comment-list">
				<view class="uni-comment-face"><image src="https://img-cdn-qiniu.dcloud.net.cn/uniapp/images/uni@2x.png" mode="widthFix"></image></view>
				<view class="uni-comment-body">
					<view class="uni-comment-top">
						<text>小猫咪</text>
					</view>
					<view class="uni-comment-content">支持国产,支持DCloud!</view>
					<view class="uni-comment-date">
						<view>2天前</view>
					</view>
				</view>
			</view>
		</view>
		
		# 输入框---------------
		<!-- 占位 -->
		<view style="height: 100rpx;"></view>
		<bottom-input @submit="submit"></bottom-input>

五 分享弹出框

效果图:

image-20200409220406715

简单写死样式

<!-- 分享下拉弹出框 -->
		<uni-popup ref="popup" type="bottom">
			<view class="bg-light">
				<!-- 分享 -->
				<view class="text-center py-2 font-md border-bottom">
					分享到
				</view>
				<!-- 各个分享的图标 -->
				<view class="flex align-center">
					<view class="flex-1 flex flex-column align-center justify-center py-2">
						<view class="iconfont icon-QQ bg-primary text-white flex justify-center align-center font-lger rounded-circle"  style="width: 100rpx;height: 100rpx;">
		
						</view>
						<view class="font-sm mt-1 text-muted">
							qq好友
						</view>
					</view>
					
					<view class="flex-1 flex flex-column align-center justify-center py-2">
						<view class="iconfont icon-QQ bg-primary text-white flex justify-center align-center font-lger rounded-circle"  style="width: 100rpx;height: 100rpx;">
							
						</view>
						<view class="font-sm mt-1 text-muted">
							qq好友
						</view>
					</view>
					
					<view class="flex-1 flex flex-column align-center justify-center py-2">
						<view class="iconfont icon-QQ bg-primary text-white flex justify-center align-center font-lger rounded-circle"  style="width: 100rpx;height: 100rpx;">
							
						</view>
						<view class="font-sm mt-1 text-muted">
							qq好友
						</view>
					</view>
					
					<view class="flex-1 flex flex-column align-center justify-center py-2">
						<view class="iconfont icon-QQ bg-primary text-white flex justify-center align-center font-lger rounded-circle"  style="width: 100rpx;height: 100rpx;">
							
						</view>
						<view class="font-sm mt-1 text-muted">
							qq好友
						</view>
					</view>
				</view>
				<!-- 取消分享 -->
				<view class="text-center py-2 font-md border-top">
					取消
				</view>
</uni-popup>

封装分享组件(直接copy的,有空细细研究)

<template>
	<uni-popup ref="popup" type="bottom">
		<view class="bg-light">
			<view class="text-center py-2 font-md border-bottom border-light-secondary">分享到</view>
			<view class="flex align-center">
				<view class="flex-1 flex flex-column align-center justify-center py-2" v-for="(item,index) in providerList" :key="index" hover-class="bg-light" @tap="share(item)">
					<view class="iconfont text-white flex align-center justify-center font-lg rounded-circle" :class="item.icon + ' ' + item.color" style="width: 100rpx;height: 100rpx;"></view>
					<text class="font-sm mt-1 text-muted">{{item.name}}</text>
				</view>
			</view>
			<view class="text-center py-2 font-md border-top border-light-secondary" hover-class="bg-light">取消</view>
		</view>
		
	</uni-popup>
</template>

<script>
	import uniPopup from '@/components/uni-ui/uni-popup/uni-popup.vue';
	export default {
		components:{
			uniPopup
		},
		data() {
			return {
				title: 'share',
				shareText: 'uni-app可以同时发布成原生App、小程序、H5,邀请你一起体验!',
				href:"https://uniapp.dcloud.io",
				image: '',
				shareType:1,
				providerList:[],
			}
		},
		computed:{
			isDisableButton() {
				return function(item) {
					if(this.shareType === 0 && item.id === 'qq'){
						return true;
					}
					if(this.shareType === 5 && item.name !== '分享到微信好友'){
						return true;
					}
					return false;
				}
			}
		},
		onShareAppMessage() {
			return {
				title: this.shareText ? this.shareText : "欢迎体验uni-app",
				path: '/pages/tabBar/component/component',
				imageUrl:this.image ? this.image : 'https://img-cdn-qiniu.dcloud.net.cn/uniapp/app/share-logo@3.png'
			}
		},
		// 销毁之前
		beforeDestroy(){
			this.shareText='uni-app可以同时发布成原生App、小程序、H5,邀请你一起体验!',
			this.href = 'https://uniapp.dcloud.io',
			this.image='';
		},
		mounted() {
			
			uni.getProvider({
				service: 'share',
				success: (e) => {
					console.log('###',e);
					let data = []
					for (let i = 0; i < e.provider.length; i++) {
						switch (e.provider[i]) {
							case 'weixin':
								data.push({
									name: '微信好友',
									icon:"icon-weixin",
									color:"bg-success",
									id: 'weixin',
									sort:0
								})
								data.push({
									name: '朋友圈',
									icon:"icon-huati",
									color:"bg-dark",
									id: 'weixin',
									type:'WXSenceTimeline',
									sort:1
								})
								break;
							case 'sinaweibo':
								data.push({
									name: '新浪微博',
									icon:"icon-xinlangweibo",
									color:"bg-danger",
									id: 'sinaweibo',
									sort:2
								})
								break;
							case 'qq':
								data.push({
									name: 'QQ好友',
									icon:"icon-QQ",
									color:"bg-primary",
									id: 'qq',
									sort:3
								})
								break;
							default:
								break;
						}
					}
					this.providerList = data.sort((x,y) => {
						return x.sort - y.sort
					});
				},
				fail: (e) => {
					console.log('%%%%',e)
					uni.showModal({
						content:'获取分享通道失败',
						showCancel:false
					})
				}
			});
		},
		methods:{
			open(){
				console.log('xxxx')
				this.$refs.popup.open()
			},
			close(){
				this.$refs.popup.close()
			},
			async share(e) {
				console.log('分享通道:'+ e.id +'; 分享类型:' + this.shareType);
				
				if(!this.shareText && (this.shareType === 1 || this.shareType === 0)){
					uni.showModal({
						content:'分享内容不能为空',
						showCancel:false
					})
					return;
				}
				
				if(!this.image && (this.shareType === 2 || this.shareType === 0)){
					uni.showModal({
						content:'分享图片不能为空',
						showCancel:false
					})
					return;
				}
				
				let shareOPtions = {
					provider: e.id,
					scene: e.type && e.type === 'WXSenceTimeline' ? 'WXSenceTimeline' : 'WXSceneSession', //WXSceneSession”分享到聊天界面,“WXSenceTimeline”分享到朋友圈,“WXSceneFavorite”分享到微信收藏     
					type: this.shareType,
					success: (e) => {
						console.log('success', e);
						uni.showModal({
							content: '分享成功',
							showCancel:false
						})
					},
					fail: (e) => {
						console.log('fail', e)
						uni.showModal({
							content: e.errMsg,
							showCancel:false
						})
					},
					complete:function(){
						console.log('分享操作结束!')
					}
				}
				
				switch (this.shareType){
					case 0:
						shareOPtions.summary = this.shareText;
						shareOPtions.imageUrl = this.image;
						shareOPtions.title = '欢迎体验uniapp';
						shareOPtions.href = 'https://uniapp.dcloud.io';
						break;
					case 1:
						shareOPtions.summary = this.shareText;
						break;
					case 2:
						shareOPtions.imageUrl = this.image;
						break;
					case 5:
						shareOPtions.imageUrl = this.image ? this.image : 'https://img-cdn-qiniu.dcloud.net.cn/uniapp/app/share-logo@3.png'
						shareOPtions.title = '欢迎体验uniapp';
						shareOPtions.miniProgram = {
							id:'gh_33446d7f7a26',
							path:'/pages/tabBar/component/component',
							webUrl:'https://uniapp.dcloud.io',
							type:0
						};
						break;
					default:
						break;
				}
				
				if(shareOPtions.type === 0 && plus.os.name === 'iOS'){//如果是图文分享,且是ios平台,则压缩图片 
					shareOPtions.imageUrl = await this.compress();
				}
				if(shareOPtions.type === 1 && shareOPtions.provider === 'qq'){//如果是分享文字到qq,则必须加上href和title
					shareOPtions.href = 'https://uniapp.dcloud.io';
					shareOPtions.title = '欢迎体验uniapp';
				}
				uni.share(shareOPtions);
			},
			compress(){//压缩图片 图文分享要求分享图片大小不能超过20Kb
				console.log('开始压缩');
				let img = this.image;
				return new Promise((res) => {
					var localPath = plus.io.convertAbsoluteFileSystem(img.replace('file://', ''));
					console.log('after' + localPath);
					// 压缩size
					plus.io.resolveLocalFileSystemURL(localPath, (entry) => {
						entry.file((file) => {// 可通过entry对象操作图片 
							console.log('getFile:' + JSON.stringify(file));
							if(file.size > 20480) {// 压缩后size 大于20Kb
								plus.zip.compressImage({
									src: img,
									dst: img.replace('.jpg', '2222.jpg').replace('.JPG', '2222.JPG'),
									width: '10%',
									height: '10%',
									quality: 1,
									overwrite: true
								}, (event) => {
									console.log('success zip****' + event.size);
									let newImg = img.replace('.jpg', '2222.jpg').replace('.JPG', '2222.JPG');
									res(newImg);
								}, function(error) {
									uni.showModal({
										content:'分享图片太大,需要请重新选择图片!',
										showCancel:false
									})
								});
							}
						});
					}, (e) => {
						console.log('Resolve file URL failed: ' + e.message);
						uni.showModal({
							content:'分享图片太大,需要请重新选择图片!',
							showCancel:false
						})
					});
				})
			}
		}
	}
</script>

<style>
</style>
posted @ 2020-04-09 22:03  张明岩  阅读(702)  评论(0编辑  收藏  举报