本文先介绍了搜索结果页开发,包括搜索类型的传递、占位符设置和搜索功能实现; 再介绍了帖子详情页的开发,包括页面配置和通信、公共列表组件优化、关注顶踩功能完善、帖子内容和图片展示、评论输入框组件开发和封装、评论列表组件和分享功能组件开发等。
首页有搜索帖子、动态页有搜索话题、消息页有搜索用户,因此需要实现搜索页。
不同页面的搜索类型不同,需要通过标识进行区别,index.vue如下:
// 监听导航栏搜索框
onNavigationBarSearchInputClicked() {
uni.navigateTo({
url: '../search/search?type=post'
})
},
news.vue如下:
<!-- 搜索框 -->
<view class="p-2">
<view class="bg-light rounded flex align-center justify-center py-2 text-secondry" @click="openSearch()">
<text class="iconfont icon-sousuo mr-2"></text>搜索话题
</view>
</view>
// 打开搜索页
openSearch() {
uni.navigateTo({
url: '../search/search?type=topic'
});
}
user-list.vue如下:
// 监听点击输入框事件
onNavigationBarSearchInputClicked() {
uni.navigateTo({
url: '../search/search?type=user'
});
},
msg.vue如下:
// 弹出层选项点击事件
popupEvent(e) {
switch (e) {
case 'friend':
console.log('Adding friend');
uni.navigateTo({
url: '../search/search?type=user'
});
break;
case 'clear':
console.log('Clearing list');
break;
default:
break;
}
// 关闭弹出层
this.$refs.popup.close();
}
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" hover-class="bg-light" v-for="(item, index) in list" :key="index"
@click="clickSearchHistory(item)">{{item}}</view>
</view>
</template>
<template v-else>
<!-- 搜索结果列表 -->
<block v-for="(item, index) in searchList" :key="index">
<common-list :item="item" :index="index"></common-list>
</block>
</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: "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 commonList from '@/components/common/common-list.vue';
export default {
data() {
return {
list: [
'uni-app实战之社区交友APP',
'uni-app入门教程',
'面试之算法基础系列',
'Python全栈',
'商业数据分析从入门到入职',
'Python数据分析实战',
'Django+Vue开发生鲜电商平台'
],
searchText: '',
// 搜索结果
searchList: [],
// 当前搜索类型
type: 'post'
}
},
components: {
commonList
},
// 监听导航栏搜索框输入
onNavigationBarSearchInputChanged(e) {
console.log(e);
this.searchText = e.text;
},
// 监听点击导航栏搜索按钮
onNavigationBarButtonTap(e) {
console.log(e);
if (e.index === 0) {
this.searchEvent();
}
},
onLoad(e) {
console.log(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;
default:
break;
}
// 修改搜索占位
// #ifdef APP-PLUS
let currentWebview = this.$scope.$getAppWebview(); // 当前窗口实例
let tn = currentWebview.getStyle().titleNView; // 当前窗口原生导航栏
tn.searchInput.placeholder = '搜索' + pageTitle; // 修改placeholder
currentWebview.setStyle({
titleNView: tn
}); // 修改原生导航栏
// #endif
},
methods: {
// 搜索事件
searchEvent() {
// 收起键盘
uni.hideKeyboard();
// 显示loading状态
uni.showLoading({
title: '加载中...',
mask: false
});
// 请求搜索
setTimeout(() => {
this.searchList = test_data;
// 隐藏loading状态
uni.hideLoading();
}, 2500)
},
// 点击搜索历史
clickSearchHistory(text) {
this.searchText = text;
this.searchEvent();
}
}
}
</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;
}
.align-start {
align-items: flex-start;
}
.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;
}
.mr-1 {
margin-right: 10rpx;
}
.my-2 {
margin-top: 20rpx;
margin-bottom: 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;
}
.ml-2 {
margin-left: 20rpx;
}
/* 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-top {
border-top: 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-muted {
color: #B2B2B2;
}
.text-center {
text-align: center;
}
/* 文字换行溢出处理 */
.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-secondary {
background-color: #AAA8AB;
}
.bg-white {
background-color: #FFFFFF;
}
.bg-dark {
background-color: #333333;
}
.bg-green {
background-color: #1EBE9A;
}
.bg-brown {
background-color: #4E4E4E;
}
.bg-red {
background-color: #FB6B5A;
}
.bg-blue {
background-color: #4C82D1;
}
/* 定位 */
.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;
}
其中,$getAppWebview()
是用来获取当前webview的对象实例,从而可以实现对 webview 更强大的控制,这里是用来根据搜索类型改变导航栏搜索框占位符的。
显示:
可以看到,根据不同的搜索类型显示了不同的占位符placeholder。
需要根据不同的搜索类型搜索不同的内容,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" hover-class="bg-light" v-for="(item, index) in list" :key="index"
@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" :key="'user'+index"></common-list>
</template>
<!-- 话题搜索结果列表 -->
<template v-else-if="type === 'topic'">
<topic-list :item="item" :index="index" :key="'user'+index"></topic-list>
</template>
<!-- 用户搜索结果列表 -->
<template v-else>
<user-list :item="item" :index="index" :key="'user'+index"></user-list>
</template>
</block>
</template>
</view>
</template>
<script>
// 测试数据
const post_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: "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
}
];
const topic_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
}
];
const user_test_data = [{
avatar: '/static/img/userpic/15.jpg',
username: 'Corley',
sex: 1, // 0未知、1女性、2男性
age: 23,
isFollow: true
},
{
avatar: '/static/img/userpic/7.jpg',
username: 'Casey',
sex: 0,
age: 15,
isFollow: false
},
{
avatar: '/static/img/userpic/13.jpg',
username: 'Henry',
sex: 2,
age: 18,
isFollow: true
}
]
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';
export default {
data() {
return {
list: [
'uni-app实战之社区交友APP',
'uni-app入门教程',
'面试之算法基础系列',
'Python全栈',
'商业数据分析从入门到入职',
'Python数据分析实战',
'Django+Vue开发生鲜电商平台'
],
searchText: '',
// 搜索结果
searchList: [],
// 当前搜索类型
type: 'post'
}
},
components: {
commonList,
topicList,
userList
},
// 监听导航栏搜索框输入
onNavigationBarSearchInputChanged(e) {
console.log(e);
this.searchText = e.text;
},
// 监听点击导航栏搜索按钮
onNavigationBarButtonTap(e) {
console.log(e);
if (e.index === 0) {
this.searchEvent();
}
},
onLoad(e) {
console.log(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;
default:
break;
}
// 修改搜索占位
// #ifdef APP-PLUS
let currentWebview = this.$scope.$getAppWebview(); // 当前窗口实例
let tn = currentWebview.getStyle().titleNView; // 当前窗口原生导航栏
tn.searchInput.placeholder = '搜索' + pageTitle; // 修改placeholder
currentWebview.setStyle({
titleNView: tn
}); // 修改原生导航栏
// #endif
},
methods: {
// 搜索事件
searchEvent() {
// 收起键盘
uni.hideKeyboard();
// 显示loading状态
uni.showLoading({
title: '加载中...',
mask: false
});
// 请求搜索
setTimeout(() => {
switch (this.type) {
case 'post':
this.searchList = post_test_data;
break;
case 'topic':
this.searchList = topic_test_data;
break;
case 'user':
this.searchList = user_test_data;
break;
default:
break;
}
// 隐藏loading状态
uni.hideLoading();
}, 2500)
},
// 点击搜索历史
clickSearchHistory(text) {
this.searchText = text;
this.searchEvent();
}
}
}
</script>
<style>
</style>
显示:
可以看到,实现了根据不同的搜索类型显示不同的搜索内容。
先新建帖子详情页detail.vue,再在pages.json中配置页面右上角的菜单按钮,如下:
{
"path" : "pages/detail/detail",
"style" :
{
"navigationBarTitleText": "",
"enablePullDownRefresh": false,
"app-plus": {
"titleNView": {
"buttons": [
{
"type":"menu",
"float":"right"
}
]
}
}
}
}
帖子详情页一般从common-list组件进入,如下:
// 进入详情页
openDetail() {
uni.navigateTo({
url: '../../pages/detail/detail?detail='+JSON.stringify(this.item),
});
},
detail.vue修改如下:
onLoad(e) {
console.log(e);
// 初始化操作
if (e.detail) {
this.__init(JSON.parse(e.detail));
}
},
methods: {
__init(data) {
// 修改标题
uni.setNavigationBarTitle({
title:data.title
});
// 请求API
}
}
显示:
可以看到,页面的标题显示的是帖子的标题。
对公共列表组件功能进行优化,以使其可以兼容到帖子详情页头部,此时传的属性值增加一个值isdetail
用来判断是否是详情页,同时添加插槽用来插入帖子内容,common-list.vue如下:
<template>
<view class="p-2">
<!-- 头像、昵称和关注按钮 -->
<view class="flex align-center justify-between">
<view class="flex align-center">
<!-- 头像 -->
<image class="rounded-circle mr-2" :src="item.userpic" mode="" style="width: 65rpx; height: 65rpx;" @click="openSpace"
lazy-load></image>
<!-- 昵称和发布时间 -->
<view>
<view class="font" style="line-height: 1.5;">{{item.username}}</view>
<text class="font-sm text-light-muted" style="line-height: 1.5;">{{item.newstime}}</text>
</view>
</view>
<!-- 按钮 -->
<view v-if="!item.isFollow" class="flex align-center justify-center rounded bg-main text-white animate__animated animate__faster"
hover-class="animate__jello" style="width: 90rpx; height: 50rpx;" @click="follow">
关注
</view>
</view>
<!-- 标题 -->
<view class="font my-1" @click="openDetail">
{{item.title}}
</view>
<!-- 帖子详情 -->
<slot>
<!-- 图片 -->
<image v-if="item.titlepic" class="rounded w-100" :src="item.titlepic" style="height: 350rpx;" @click="openDetail"></image>
</slot>
<!-- 图标按钮 -->
<view class="flex align-center">
<!-- 顶 -->
<view class="flex align-center justify-center flex-1 animate__animated animate__faster" hover-class="animate__jello text-main"
@click="doSupport('support')" :class="item.support.type === 'support' ? 'support-active' : ''">
<text class="iconfont icon-dianzan mr-2"></text>
<text>{{item.support.support_count > 0 ? item.support.support_count : '支持'}}</text>
</view>
<!-- 踩 -->
<view class="flex align-center justify-center flex-1 animate__animated animate__faster" hover-class="animate__jello text-main"
@click="doSupport('unsupport')" :class="item.support.type === 'unsupport' ? 'support-active' : ''">
<text class="iconfont icon-cai mr-2"></text>
<text>{{item.support.unsupport_count > 0 ? item.support.unsupport_count : '反对'}}</text>
</view>
<view class="flex align-center justify-center flex-1 animate__animated animate__faster" hover-class="animate__jello text-main"
@click="openDetail">
<text class="iconfont icon-pinglun mr-2"></text>
<text>{{item.comment_count > 0 ? item.comment_count : '评论'}}</text>
</view>
<view class="flex align-center justify-center flex-1 animate__animated animate__faster" hover-class="animate__jello text-main"
@click="openDetail">
<text class="iconfont icon-fenxiang mr-2"></text>
<text>{{item.share_count > 0 ? item.share_count : '分享'}}</text>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
item: Object,
index: Number,
isdetail: {
type: Boolean,
default: false
}
},
methods: {
// 打开个人空间
openSpace() {
console.log('Space opened');
},
// 关注
follow() {
console.log('Followed');
// 通知父组件
this.$emit('follow', this.index);
},
// 进入详情页
openDetail() {
// 处于详情页
if (this.isdetail) return;
uni.navigateTo({
url: '../../pages/detail/detail?detail='+JSON.stringify(this.item),
});
},
// 顶踩操作
doSupport(type) {
console.log(type);
// 通知父组件
this.$emit('doSupport', {
type,
index: this.index
})
}
}
}
</script>
<style>
.support-active {
color: #FF4A6A;
}
</style>
detail.vue如下:
<template>
<view>
<!-- 帖子详情页 -->
<common-list :item="info" isdetail>
帖子详情
</common-list>
</view>
</template>
<script>
import commonList from '@/components/common/common-list.vue';
export default {
data() {
return {
// 当前帖子信息
info: {}
}
},
components: {
commonList
},
onLoad(e) {
console.log(e);
// 初始化操作
if (e.detail) {
this.__init(JSON.parse(e.detail));
}
},
methods: {
__init(data) {
// 修改标题
uni.setNavigationBarTitle({
title: data.title
});
// 请求API
this.info = data;
}
}
}
</script>
<style>
</style>
显示:
可以看到,实现了common-list组件的复用。
再给评论和分享按钮添加点击事件,如下:
<template>
<view class="p-2">
<!-- 头像、昵称和关注按钮 -->
<view class="flex align-center justify-between">
<view class="flex align-center">
<!-- 头像 -->
<image class="rounded-circle mr-2" :src="item.userpic" mode="" style="width: 65rpx; height: 65rpx;" @click="openSpace"
lazy-load></image>
<!-- 昵称和发布时间 -->
<view>
<view class="font" style="line-height: 1.5;">{{item.username}}</view>
<text class="font-sm text-light-muted" style="line-height: 1.5;">{{item.newstime}}</text>
</view>
</view>
<!-- 按钮 -->
<view v-if="!item.isFollow" class="flex align-center justify-center rounded bg-main text-white animate__animated animate__faster"
hover-class="animate__jello" style="width: 90rpx; height: 50rpx;" @click="follow">
关注
</view>
</view>
<!-- 标题 -->
<view class="font my-1" @click="openDetail">
{{item.title}}
</view>
<!-- 帖子详情 -->
<slot>
<!-- 图片 -->
<image v-if="item.titlepic" class="rounded w-100" :src="item.titlepic" style="height: 350rpx;" @click="openDetail"></image>
</slot>
<!-- 图标按钮 -->
<view class="flex align-center">
<!-- 顶 -->
<view class="flex align-center justify-center flex-1 animate__animated animate__faster" hover-class="animate__jello text-main"
@click="doSupport('support')" :class="item.support.type === 'support' ? 'support-active' : ''">
<text class="iconfont icon-dianzan mr-2"></text>
<text>{{item.support.support_count > 0 ? item.support.support_count : '支持'}}</text>
</view>
<!-- 踩 -->
<view class="flex align-center justify-center flex-1 animate__animated animate__faster" hover-class="animate__jello text-main"
@click="doSupport('unsupport')" :class="item.support.type === 'unsupport' ? 'support-active' : ''">
<text class="iconfont icon-cai mr-2"></text>
<text>{{item.support.unsupport_count > 0 ? item.support.unsupport_count : '反对'}}</text>
</view>
<view class="flex align-center justify-center flex-1 animate__animated animate__faster" hover-class="animate__jello text-main"
@click="doComment">
<text class="iconfont icon-pinglun mr-2"></text>
<text>{{item.comment_count > 0 ? item.comment_count : '评论'}}</text>
</view>
<view class="flex align-center justify-center flex-1 animate__animated animate__faster" hover-class="animate__jello text-main"
@click="doShare">
<text class="iconfont icon-fenxiang mr-2"></text>
<text>{{item.share_count > 0 ? item.share_count : '分享'}}</text>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
item: Object,
index: Number,
isdetail: {
type: Boolean,
default: false
}
},
methods: {
// 打开个人空间
openSpace() {
console.log('Space opened');
},
// 关注
follow() {
console.log('Followed');
// 通知父组件
this.$emit('follow', this.index);
},
// 进入详情页
openDetail() {
// 处于详情页
if (this.isdetail) return;
uni.navigateTo({
url: '../../pages/detail/detail?detail='+JSON.stringify(this.item),
});
},
// 顶踩操作
doSupport(type) {
console.log(type);
// 通知父组件
this.$emit('doSupport', {
type,
index: this.index
})
},
// 评论
doComment() {
if (!this.isdetail) {
return this.openDetail();
}
this.$emit('doComment');
},
// 分享
doShare() {
if (!this.isdetail) {
return this.openDetail();
}
this.$emit('doShare');
}
}
}
</script>
<style>
.support-active {
color: #FF4A6A;
}
</style>
detail.vue如下:
<template>
<view>
<!-- 帖子详情页 -->
<common-list :item="info" isdetail @doComment="doComment" @doShare="doShare">
帖子详情
</common-list>
</view>
</template>
<script>
import commonList from '@/components/common/common-list.vue';
export default {
data() {
return {
// 当前帖子信息
info: {}
}
},
components: {
commonList
},
onLoad(e) {
console.log(e);
// 初始化操作
if (e.detail) {
this.__init(JSON.parse(e.detail));
}
},
methods: {
__init(data) {
// 修改标题
uni.setNavigationBarTitle({
title: data.title
});
// 请求API
this.info = data;
},
// 点击评论
doComment() {
console.log('Commenting...');
},
// 点击分享
doShare() {
console.log('Sharing...');
}
}
}
</script>
<style>
</style>
显示:
可以看到,在贴子列表页点击评论和分享按钮时进入帖子详情页,在帖子详情页点击时会触发评论和分享事件。
在详情页实现关注和顶踩功能,如下:
<template>
<view>
<!-- 帖子详情页 -->
<common-list :item="info" isdetail @doComment="doComment" @doShare="doShare" @follow="follow" @doSupport="doSupport">
帖子详情
</common-list>
</view>
</template>
<script>
import commonList from '@/components/common/common-list.vue';
export default {
data() {
return {
// 当前帖子信息
info: {}
}
},
components: {
commonList
},
onLoad(e) {
console.log(e);
// 初始化操作
if (e.detail) {
this.__init(JSON.parse(e.detail));
}
},
methods: {
__init(data) {
// 修改标题
uni.setNavigationBarTitle({
title: data.title
});
// 请求API
this.info = data;
},
// 关注
follow() {
this.info.isFollow = true;
uni.showToast({
title: '关注成功'
});
},
// 顶踩操作
doSupport(e) {
let msg = e.type === 'support' ? '顶' : '踩';
// 之前操作过
if(this.info.support.type === e.type) {
return uni.showToast({
title: '您已经' + msg + '过了'
});
}
// 之前未操作过
if(this.info.support.type === '') {
this.info.support[e.type + '_count']++;
}
// 之前已顶过并且现在的操作为踩,则顶-1、踩+1
else if(this.info.support.type === 'support' && e.type === 'unsupport') {
this.info.support.support_count--;
this.info.support.unsupport_count++;
}
// 之前已踩过并且现在的操作为顶,则踩-1、顶+1
else if(this.info.support.type === 'unsupport' && e.type === 'support') {
this.info.support.unsupport_count--;
this.info.support.support_count++;
}
this.info.support.type = e.type;
uni.showToast({
title: msg + '成功'
});
},
// 点击评论
doComment() {
console.log('Commenting...');
},
// 点击分享
doShare() {
console.log('Sharing...');
}
}
}
</script>
<style>
</style>
index.vue如下:
// 切换选项
changeTab(index) {
if (this.tabIndex === index) {
return;
}
this.tabIndex = index;
this.list = this.newsList[this.tabIndex].list;
// 滚动到指定元素
this.scrollInto = 'tab' + index;
},
// 获取数据
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.newsList = arr;
this.list = this.newsList[this.tabIndex].list;
},
显示:
显然,已经实现了在首页和详情页进行关注和顶踩功能。
给帖子数据增加content字段用于保存帖子内容、images字段(数组)用于保存图片,index.vue中测试数据如下:
// 测试数据
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,
content: 'uni-app是DCloud官方推出的使用Vue.js开发跨平台应用的前端框架,一套代码可编译到iOS、Android、微信小程序等多个平台,学习和开发成本较低。在进行uni-app开发之前需要先搭建环境,下载并安装HBuilderX、微信开发者工具;新建项目时选择类型,创建之后会自动生成项目的默认目录,可以通过多种方式编译运行。一个典型的项目包括App.vue、main.js等文件和pages、static等目录;uni-app遵守Vue单文件组件规范,vue文件包括模板、脚本和样式3个顶级语言块。更多内容可点击https://blog.csdn.net/CUFEECR/article/details/111088889。',
images: [
{
url: 'https://img-blog.csdnimg.cn/20210202134847418.png'
},
{
url: 'https://img-blog.csdnimg.cn/20210202135211479.png'
}
]
},
{
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
}
];
detail.vue如下:
<template>
<view>
<!-- 帖子详情页 -->
<common-list :item="info" isdetail @doComment="doComment" @doShare="doShare" @follow="follow" @doSupport="doSupport">
<view>{{info.content}}</view>
<view class="">
<block v-for="(item, index) in info.images">
<image :src="item.url" class="w-100" mode="widthFix" @click="preview(index)"></image>
</block>
</view>
</common-list>
</view>
</template>
<script>
import commonList from '@/components/common/common-list.vue';
export default {
data() {
return {
// 当前帖子信息
info: {}
}
},
components: {
commonList
},
computed: {
imagesList() {
return this.info.images.map(item=>item.url);
}
},
onLoad(e) {
console.log(e);
// 初始化操作
if (e.detail) {
this.__init(JSON.parse(e.detail));
}
},
methods: {
__init(data) {
// 修改标题
uni.setNavigationBarTitle({
title: data.title
});
// 请求API
this.info = data;
},
// 关注
follow() {
this.info.isFollow = true;
uni.showToast({
title: '关注成功'
});
},
// 顶踩操作
doSupport(e) {
let msg = e.type === 'support' ? '顶' : '踩';
// 之前操作过
if(this.info.support.type === e.type) {
return uni.showToast({
title: '您已经' + msg + '过了'
});
}
// 之前未操作过
if(this.info.support.type === '') {
this.info.support[e.type + '_count']++;
}
// 之前已顶过并且现在的操作为踩,则顶-1、踩+1
else if(this.info.support.type === 'support' && e.type === 'unsupport') {
this.info.support.support_count--;
this.info.support.unsupport_count++;
}
// 之前已踩过并且现在的操作为顶,则踩-1、顶+1
else if(this.info.support.type === 'unsupport' && e.type === 'support') {
this.info.support.unsupport_count--;
this.info.support.support_count++;
}
this.info.support.type = e.type;
uni.showToast({
title: msg + '成功'
});
},
// 点击评论
doComment() {
console.log('Commenting...');
},
// 点击分享
doShare() {
console.log('Sharing...');
},
// 预览图片
preview(index) {
uni.previewImage({
urls: this.imagesList,
current: index
})
}
}
}
</script>
<style>
</style>
显示:
可以看到,显示了帖子内容,还可以预览图片。
评论输入框和聊天页输入框类似,在components/common下新建组件bottom-input抽离底部输入框,如下:
<template>
<view style="height: 100rpx;" class="fixed-bottom flex align-center border-top bg-white">
<input type="text" v-model="content" value="" class="flex-1 rounded bg-light ml-2" style="padding: 5rpx 0;" placeholder="文明发言" @confirm="submit()" />
<view class="iconfont icon-fasong flex align-center justify-center font-lg animate__animated" hover-class="animate__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>
user-chat.vue如下:
<template>
<view>
<!-- 聊天消息列表 -->
<scroll-view scroll-y="true" style="position: absolute; left: 0; top: 0; right: 0; bottom: 100rpx;" :scroll-into-view="scrollInto" scroll-with-animation>
<block v-for="(item, index) in list">
<view :id="'chat'+index">
<user-chat-list :item="item" :index="index" :preTime="index > 0 ? list[index-1].create_time : 0"></user-chat-list>
</view>
</block>
</scroll-view>
<!-- 底部操作条 -->
<bottom-input @submit="submit"></bottom-input>
</view>
</template>
<script>
import userChatList from '@/components/user-chat/user-chat-list.vue';
import bottomInput from '@/components/common/bottom-input.vue';
export default {
data() {
return {
list: [
{
user_id: 2,
username: 'Natalia',
avatar: '/static/img/userpic/14.jpg',
data: '大佬,你好',
type: 'text', // text、image、video、audio、link
create_time: 1612156712
},
{
user_id: 2,
username: 'Corley',
avatar: '/static/img/userpic/14.jpg',
data: '我想请教一个关于uni-app的问题,不知道是否方便?',
type: 'text',
create_time: 1612156872
},
{
user_id: 1,
username: 'Natalia',
avatar: '/static/img/userpic/11.jpg',
data: '你好啊,大佬不敢当?',
type: 'text',
create_time: 1612156905
},
{
user_id: 1,
username: 'Corley',
avatar: '/static/img/userpic/11.jpg',
data: '有什么你就说吧',
type: 'text',
create_time: 1612157023
},
{
user_id: 1,
username: 'Corley',
avatar: '/static/img/userpic/11.jpg',
data: '只要我会的都会解答',
type: 'text',
create_time: 1612157029
},
{
user_id: 2,
username: 'Corley',
avatar: '/static/img/userpic/14.jpg',
data: '有几个问题',
type: 'text',
create_time: 1612157411
},
{
user_id: 2,
username: 'Natalia',
avatar: '/static/img/userpic/14.jpg',
data: '1.在导航栏上单击搜索输入监听搜索框的事件该写在什么位置啊,为什么我写的触发不了?',
type: 'text',
create_time: 1612157439
},
{
user_id: 2,
username: 'Corley',
avatar: '/static/img/userpic/14.jpg',
data: '2.关注顶踩的动画css怎么获取到的啊?',
type: 'text',
create_time: 1612157455
},
{
user_id: 2,
username: 'Natalia',
avatar: '/static/img/userpic/14.jpg',
data: '3.首页开发最后代码写完,再点击关注和点赞,踩,就会报错。辛苦看一看啊',
type: 'text',
create_time: 1612157503
},
{
user_id: 1,
username: 'Corley',
avatar: '/static/img/userpic/11.jpg',
data: '好的,我马上看',
type: 'text',
create_time: 1612157821
}
],
scrollInto: '',
username: ''
}
},
components: {
userChatList,
bottomInput
},
onLoad(e) {
console.log(e);
this.username = e.username;
},
// 页面加载完成
onReady() {
this.pageToBottom();
uni.setNavigationBarTitle({
title: this.username
});
},
methods: {
// 发送消息
submit(data) {
let obj = {
user_id: 1,
username: 'Corley',
avatar: '/static/img/userpic/11.jpg',
data: data,
type: 'text',
create_time: (new Date()).getTime()
}
this.list.push(obj);
// 滚动到底部
this.pageToBottom();
},
// 滚动到底部
pageToBottom() {
let lastIndex = this.list.length - 1;
if (lastIndex < 0) return;
this.scrollInto = 'chat' + lastIndex;
}
}
}
</script>
<style>
</style>
detail.vue如下:
<template>
<view>
<!-- 帖子详情页 -->
<common-list :item="info" isdetail @doComment="doComment" @doShare="doShare" @follow="follow" @doSupport="doSupport">
<view>{{info.content}}</view>
<view class="">
<block v-for="(item, index) in info.images">
<image :src="item.url" class="w-100" mode="widthFix" @click="preview(index)"></image>
</block>
</view>
</common-list>
<!-- 占位 -->
<view style="height: 100rpx;"></view>
<bottom-input @submit="submit"></bottom-input>
</view>
</template>
<script>
import commonList from '@/components/common/common-list.vue';
import bottomInput from '@/components/common/bottom-input.vue';
export default {
data() {
return {
// 当前帖子信息
info: {}
}
},
components: {
commonList,
bottomInput
},
computed: {
imagesList() {
return this.info.images.map(item=>item.url);
}
},
onLoad(e) {
console.log(e);
// 初始化操作
if (e.detail) {
this.__init(JSON.parse(e.detail));
}
},
methods: {
__init(data) {
// 修改标题
uni.setNavigationBarTitle({
title: data.title
});
// 请求API
this.info = data;
},
// 关注
follow() {
this.info.isFollow = true;
uni.showToast({
title: '关注成功'
});
},
// 顶踩操作
doSupport(e) {
let msg = e.type === 'support' ? '顶' : '踩';
// 之前操作过
if(this.info.support.type === e.type) {
return uni.showToast({
title: '您已经' + msg + '过了'
});
}
// 之前未操作过
if(this.info.support.type === '') {
this.info.support[e.type + '_count']++;
}
// 之前已顶过并且现在的操作为踩,则顶-1、踩+1
else if(this.info.support.type === 'support' && e.type === 'unsupport') {
this.info.support.support_count--;
this.info.support.unsupport_count++;
}
// 之前已踩过并且现在的操作为顶,则踩-1、顶+1
else if(this.info.support.type === 'unsupport' && e.type === 'support') {
this.info.support.unsupport_count--;
this.info.support.support_count++;
}
this.info.support.type = e.type;
uni.showToast({
title: msg + '成功'
});
},
// 点击评论
doComment() {
console.log('Commenting...');
},
// 点击分享
doShare() {
console.log('Sharing...');
},
// 预览图片
preview(index) {
uni.previewImage({
urls: this.imagesList,
current: index
})
},
// 提交评论
submit(data) {
console.log(data);
}
}
}
</script>
<style>
</style>
显示:
可以看到,底部输入框组件封装成功,模拟出了添加评论。
评论列表组件使用uni-app官方提供的模板,如下:
<!-- 评论 -->
<view class="p-2 font-md font-weight-bold">
最新评论 3
</view>
<view class="uni-comment-list px-2">
<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>Olivia</text>
</view>
<view class="uni-comment-content">大佬,写的不错</view>
<view class="uni-comment-date">
<view>2天前</view>
</view>
</view>
</view>
显示:
可以看到,实现了评论列表。
分享功能也是使用uni-popup
组件实现,类型是bottom
从底部弹出,如下:
<!-- 分享组件 -->
<uni-popup ref="popup" type="bottom">
<view class="popup-content text-center py-2 font-md border-bottom border-light-secondary">分享到</view>
<view class="popup-content flex align-center">
<block v-for="(item, index) in shareList" :key="index">
<view class="flex-1 flex flex-column align-center justify-center py-2" hover-class="bg-light">
<view class="iconfont text-white font-lg rounded-circle flex align-center justify-center" :class="item.icon+' '+item.color" style="width: 100rpx; height: 100rpx;"></view>
<text class="font-sm mt-1 text-muted">{{item.name}}</text>
</view>
</block>
</view>
<view class="popup-content text-center py-2 font-md border-top border-light-secondary" hover-class="bg-light">取消</view>
</uni-popup>
<script>
import commonList from '@/components/common/common-list.vue';
import bottomInput from '@/components/common/bottom-input.vue';
import uniPopup from '@/components/uni-ui/uni-popup/uni-popup.vue';
export default {
data() {
return {
// 当前帖子信息
info: {},
shareList: [
{
icon: 'icon-weixin',
color: 'bg-green',
name:'微信好友'
},
{
icon: 'icon-pengyouquan',
color: 'bg-brown',
name:'朋友圈'
},
{
icon: 'icon-weibo',
color: 'bg-red',
name:'微博'
},
{
icon: 'icon-qq',
color: 'bg-blue',
name:'QQ好友'
}
]
}
},
components: {
commonList,
bottomInput,
uniPopup
},
computed: {
imagesList() {
return this.info.images.map(item => item.url);
}
},
onLoad(e) {
console.log(e);
// 初始化操作
if (e.detail) {
this.__init(JSON.parse(e.detail));
}
},
onNavigationBarButtonTap() {
this.$refs.popup.open();
},
onBackPress() {
this.$refs.popup.close();
},
methods: {
__init(data) {
// 修改标题
uni.setNavigationBarTitle({
title: data.title
});
// 请求API
this.info = data;
},
// 关注
follow() {
this.info.isFollow = true;
uni.showToast({
title: '关注成功'
});
},
// 顶踩操作
doSupport(e) {
let msg = e.type === 'support' ? '顶' : '踩';
// 之前操作过
if (this.info.support.type === e.type) {
return uni.showToast({
title: '您已经' + msg + '过了'
});
}
// 之前未操作过
if (this.info.support.type === '') {
this.info.support[e.type + '_count']++;
}
// 之前已顶过并且现在的操作为踩,则顶-1、踩+1
else if (this.info.support.type === 'support' && e.type === 'unsupport') {
this.info.support.support_count--;
this.info.support.unsupport_count++;
}
// 之前已踩过并且现在的操作为顶,则踩-1、顶+1
else if (this.info.support.type === 'unsupport' && e.type === 'support') {
this.info.support.unsupport_count--;
this.info.support.support_count++;
}
this.info.support.type = e.type;
uni.showToast({
title: msg + '成功'
});
},
// 点击评论
doComment() {
console.log('Commenting...');
},
// 点击分享
doShare() {
console.log('Sharing...');
},
// 预览图片
preview(index) {
uni.previewImage({
urls: this.imagesList,
current: index
})
},
// 提交评论
submit(data) {
console.log(data);
}
}
}
</script>
为了本文项目练手所需,需要在https://www.iconfont.cn/中下载微信
、朋友圈
、微博
、QQ
等图标,同时更新icon.css和iconfont.ttf更新为最新状态。
显示:
可以看到,实现了图标。
再进一步封装为组件,在components/common目录下新建more-share组件,如下:
<template>
<uni-popup ref="popup" type="bottom">
<view class="popup-content text-center py-2 font-md border-bottom border-light-secondary">分享到</view>
<view class="popup-content flex align-center">
<block v-for="(item, index) in shareList" :key="index">
<view class="flex-1 flex flex-column align-center justify-center py-2" hover-class="bg-light">
<view class="iconfont text-white font-lg rounded-circle flex align-center justify-center" :class="item.icon+' '+item.color" style="width: 100rpx; height: 100rpx;"></view>
<text class="font-sm mt-1 text-muted">{{item.name}}</text>
</view>
</block>
</view>
<view class="popup-content text-center py-2 font-md border-top border-light-secondary" hover-class="bg-light">取消</view>
</uni-popup>
</template>
<script>
import uniPopup from '@/components/uni-ui/uni-popup/uni-popup.vue';
export default {
data() {
return {
shareList: [
{
icon: 'icon-weixin',
color: 'bg-green',
name:'微信好友'
},
{
icon: 'icon-pengyouquan',
color: 'bg-brown',
name:'朋友圈'
},
{
icon: 'icon-weibo',
color: 'bg-red',
name:'微博'
},
{
icon: 'icon-qq',
color: 'bg-blue',
name:'QQ好友'
}
]
}
},
components: {
uniPopup
},
methods: {
open() {
this.$refs.popup.open();
},
close() {
this.$refs.popup.close();
}
}
}
</script>
<style>
</style>
detail.vue如下:
<!-- 分享组件 -->
<more-share ref="share"></more-share>
onNavigationBarButtonTap() {
this.$refs.share.open();
},
onBackPress() {
this.$refs.share.close();
},
效果与之前相同。
分享接口可参考hello_uniapp参考项目下pages/API下的share页面,使用的是uni.getProvider()
接口动态获取服务商,如下:
<template>
<uni-popup ref="popup" type="bottom">
<view class="popup-content text-center py-2 font-md border-bottom border-light-secondary">分享到</view>
<view class="popup-content flex align-center">
<block v-for="(item, index) in providerList" :key="index">
<view class="flex-1 flex flex-column align-center justify-center py-2" hover-class="bg-light" @tap="share(item)">
<view class="iconfont text-white font-lg rounded-circle flex align-center justify-center" :class="item.icon+' '+item.color"
style="width: 100rpx; height: 100rpx;"></view>
<text class="font-sm mt-1 text-muted">{{item.name}}</text>
</view>
</block>
</view>
<view class="popup-content text-center py-2 font-md border-top border-light-secondary" hover-class="bg-light">取消</view>
</uni-popup>
</template>
<script>
import uniPopup from '@/components/uni-ui/uni-popup/uni-popup.vue';
export default {
data() {
return {
providerList: [],
title: 'share',
shareText: 'uni-app是DCloud官方推出的使用Vue.js开发跨平台应用的前端框架,一套代码可编译到iOS、Android、微信小程序等多个平台,学习和开发成本较低。在进行uni-app开发之前需要先搭建环境,下载并安装HBuilderX、微信开发者工具;新建项目时选择类型,创建之后会自动生成项目的默认目录,可以通过多种方式编译运行。一个典型的项目包括App.vue、main.js等文件和pages、static等目录;uni-app遵守Vue单文件组件规范,vue文件包括模板、脚本和样式3个顶级语言块。更多内容可点击https://blog.csdn.net/CUFEECR/article/details/111088889。',
href: "https://blog.csdn.net/CUFEECR",
image: 'https://img-blog.csdnimg.cn/20210202134847418.png',
shareType: 1
}
},
components: {
uniPopup
},
computed: {
isDisableButton() {
return function(item) {
if (this.shareType === 0 && item.id === 'qq') {
return true;
}
if (this.shareType === 5 && item.name !== '分享到微信好友') {
return true;
}
return false;
}
}
},
mounted() {
uni.getProvider({
service: 'share',
success: (e) => {
console.log('success', 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-green',
id: 'weixin',
sort: 0
})
data.push({
name: '朋友圈',
icon: 'icon-pengyouquan',
color: 'bg-brown',
id: 'weixin',
type: 'WXSenceTimeline',
sort: 1
})
break;
case 'sinaweibo':
data.push({
name: '微博',
icon: 'icon-weibo',
color: 'bg-red',
id: 'sinaweibo',
sort: 2
})
break;
case 'qq':
data.push({
name: 'QQ好友',
icon: 'icon-qq',
color: 'bg-blue',
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
})
}
});
},
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 = '';
},
methods: {
open() {
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>
显示:
可以看到,实现了分享到微信好友和朋友圈。
在进行uni-app开发时,因为官方提供了很多模板、组件和接口,可以实现常见的功能,我们可以在其基础上进行稍微的优化和改动,即可用于自己项目,例如评论列表模板、分享组件和API,这样可以大大加快开发效率。