17 uniapp-帖子详情页面(复用common-list组件,预览图片,数组map()函数,分享组件)
17 帖子详情页面(复用common-list组件,预览图片,数组map()函数,分享组件)
纵览效果图:
一 设置跳转+导航条
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>
二 大体实现详情页面(迭代服用组件思想)
迭代组件复用思想
如果已经有别的组件引用该组件了,尽量在不修改别的组件使用方法的基础上适配兼容新的组件。
效果图:
一 修改原有common-list.vue
设计插槽:
<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:并没有真的作出评论功能,只做了个样式
代码:
# 评论标签-------------
# 评论标签代码是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>
五 分享弹出框
效果图:
简单写死样式
<!-- 分享下拉弹出框 -->
<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>