uni-app 17朋友圈开发
Posted 2019ab
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了uni-app 17朋友圈开发相关的知识,希望对你有一定的参考价值。
不废话,直接看效果图
下面是实现代码
moments.nvue
<template>
<view>
<free-transparent-bar :scrollTop="scrollTop"></free-transparent-bar>
<view class="position-relative" style="height: 620rpx;">
<image src="https://douyinzcmcss.oss-cn-shenzhen.aliyuncs.com/shengchengqi/datapic/1.jpg" mode="aspectFill" style="height: 590rpx;" class="bg-secondary w-100"></image>
<image src="/static/images/demo/demo6.jpg" style="width: 120rpx;height:120rpx;right: 30rpx;" mode="" class="bg-secondary rounded position-absolute bottom-0"></image>
<text class="text-white font-md position-absolute" style="bottom: 45rpx;right: 160rpx">Summer</text>
</view>
<!-- 朋友圈列表样式 -->
<free-moment-list v-for="(item,index) in list" :key='index' :item="item" :index="index" @action="doAction"></free-moment-list>
<!-- 评论框 -->
<free-popup ref="action" bottom transformOrigin="center bottom">
<view style="height: 105rpx;" class="bg-light border-top flex align-center">
<textarea fixed class="bg-white rounded p-2 font-md" style="height: 75rpx;width: 520rpx;" value="" placeholder="" v-model="content" :focus="true"/>
<free-icon-button @click="changeFaceModeal"><text class="iconfont font-lg"></text></free-icon-button>
<free-main-button name="发送" :disabled="content.length===0" @click="send"></free-main-button>
</view>
<!-- 表情包 -->
<scroll-view v-if="faceModal" scroll-y="true" style="height: 350rpx;" class="bg-light flex flex-wrap">
<view class="flex align-center justify-center" hover-class="bg-white" style="width:107rpx;height:107rpx;" v-for="(item,index) in faceList" :key="index" @click="addFace(item)">
<text>{{item}}</text>
</view>
</scroll-view>
</free-popup>
</view>
</template>
<script>
import freeTransparentBar from '@/components/free-ui/free-transparent-bar.vue';
import freeMomentList from '@/components/free-ui/free-moment-list.vue';
import freePopup from '@/components/free-ui/free-popup.vue';
import freeIconButton from '@/components/free-ui/free-icon-button.vue';
import freeMainButton from '@/components/free-ui/free-main-button.vue';
export default {
components:{
freeTransparentBar,
freeMomentList,
freePopup,
freeIconButton,
freeMainButton
},
data() {
return {
content:'',
scrollTop:0,
faceModal:false,
faceList:["😀","😁","😂","😃","😄","😅","😆","😉","😊","😋","😎","😍","😘","😗","😙","😚","😇","😐","😑","😶","😏","😣","😥","😮","😯","😪","😫","😴","😌","😛","😜","😝","😒","😓","😔","😕","😲","😷","😖","😞","😟","😤","😢","😭","😦","😧","😨","😬","😰","😱","😳","😵","😡","😠"],
commentIndex:-1,
list:[{
id:2,
avatar:'/static/images/demo/demo6.jpg',
username:'昵称',
context:'靓仔,靓仔',
image:[],
video:false,
create_time:1567481668,
supports:[{
id:1,
username:'昵称',
avatar:'/static/image/demo/demo6.jpg'
}],
comments:[{
id:1,
username:'昵称',
content:'评论内容'
}]
},
{
id:2,
avatar:'/static/images/demo/demo6.jpg',
username:'昵称',
context:'靓仔,靓仔',
image:['https://douyinzcmcss.oss-cn-shenzhen.aliyuncs.com/shengchengqi/datapic/1.jpg'],
video:false,
create_time:1567481668,
supports:[],
comments:[]
},
{
id:2,
avatar:'/static/images/demo/demo6.jpg',
username:'昵称',
context:'靓仔,靓仔',
image:['https://douyinzcmcss.oss-cn-shenzhen.aliyuncs.com/shengchengqi/datapic/1.jpg','https://douyinzcmcss.oss-cn-shenzhen.aliyuncs.com/shengchengqi/datapic/1.jpg'],
video:false,
create_time:1567481668,
supports:[],
comments:[]
},
{
id:2,
avatar:'/static/images/demo/demo6.jpg',
username:'昵称',
context:'靓仔,靓仔',
image:[],
video:{src:'/static/video/demo.mp4',poster:'https://douyinzcmcss.oss-cn-shenzhen.aliyuncs.com/shengchengqi/datapic/1.jpg'},
create_time:1567481668,
supports:[],
comments:[]
}],
}
},
onPageScroll(e) {
this.scrollTop = e.scrollTop;
},
methods: {
// 点击操作菜单
doAction(e){
uni.showActionSheet({
itemList: ['点赞','评论'],
success: res => {
if(res.tapIndex === 0){
// 点赞
this.doSupport(e)
}else{
this.content='';
this.faceModal=false;
this.commentIndex = e.index;
this.$refs.action.show();
// this.doComment(e)
}
}
});
},
// 点赞
doSupport(e){
e.item.supports.push({
id:1,
username:'昵称',
avatar:'/static/image/demo/demo6.jpg'
});
},
// 添加表情
addFace(item){
this.content += item;
},
// 开启关闭表情包面板
changeFaceModeal(){
uni.hideKeyboard();
setTimeout(()=>{
this.faceModal = !this.faceModal;
},100);
},
// 发送
send(){
this.list[this.commentIndex].comments.push({
id:1,
username:'昵称',
content:this.content
})
this.$refs.action.hide();
}
},
}
</script>
<style>
</style>
涉及的引入文件
// free-transparent-bar.vue
<template>
<view>
<view class="fixed-top" :style="navBarStyle">
<!-- 状态栏 -->
<view :style="'height:'+statusBarHeight+'px;'"></view>
<!-- 导航 -->
<view class="w-100 flex align-center justify-between" style="height: 90rpx;">
<!-- 左边 -->
<view class="flex align-center">
<!-- 返回按钮 -->
<view class="flex align-center justify-center"
hover-class="bg-hover-light" @click="back"
style="height: 90rpx;width: 90rpx;">
<text class="iconfont font-md" :style="buttonStyle"></text>
</view>
<!-- 标题 -->
<text v-if="title" class="font-md ml-3" >{{title}}</text>
</view>
<!-- 右边 -->
<view class="flex align-center">
<view class="flex align-center justify-center"
hover-class="bg-hover-light"
style="height: 90rpx;width: 90rpx;">
<text class="iconfont font-md" :style="buttonStyle"></text>
</view>
</view>
<!--\\ue6e3 \\ue682 -->
</view>
</view>
</view>
</template>
<script>
export default {
components: {
},
props: {
title: {
type: String,
default: ''
},
scrollTop:{
type:[String,Number],
default:0
}
},
data() {
return {
statusBarHeight: 0,
navBarHeight: 0,
}
},
mounted() {
// 获取任务栏高度
// #ifdef APP-PLUS-NVUE
this.statusBarHeight = plus.navigator.getStatusbarHeight()
// #endif
this.navBarHeight = this.statusBarHeight + uni.upx2px(90)
},
computed: {
// 变化0-1
changeNumber(){
let start = uni.upx2px(500);
let end = uni.upx2px(620);
let H = end - start;
let num = 0;
if(this.scrollTop > start){
num = (this.scrollTop - start)/H;
}
return num > 1 ? 1 : num;
},
navBarStyle(){
return `background-color:rgba(255,255,255,${this.changeNumber});`
},
buttonStyle(){
if(this.changeNumber>0){
return `color:rgba(0,0,0,${this.changeNumber})`;
}
return 'color:#FFFFFF;'
}
},
methods:{
// 返回
back(){
uni.navigateBack({
delta:1
})
}
}
}
</script>
<style>
</style>
// free-moment-list.vue
<template>
<view class="p-3 flex align-start border-bottom border-light-secondary">
<free-avatar :src='item.avatar' size="80"></free-avatar>
<view class="pl-2 flex-1 flex flex-column">
<!-- 昵称 -->
<text class="font-md text-hover-primary">{{item.username}}</text>
<!-- 内容 -->
<text class="font-md text-dark mb-1">{{item.context}}</text>
<!-- 图片 -->
<view v-if="item.image.length" class="py-2 flex flex-wrap">
<block v-for="(image,imageIndex) in item.image" :key='imageIndex'>
<!-- 单图 -->
<free-image v-if="item.image.length==1" :src="item.image[imageIndex]" imageClass='rounded' @click="preview(image)"></free-image>
<free-image v-else :src="item.image[imageIndex]" imageClass='rounded' mode="aspectFill" style="width: 180rpx;height: 180rpx;" class="bg-secondary mr-2 mb-2" @click="preview(image)"></free-image>
</block>
</view>
<!-- 视频 -->
<view class="py-2" v-if="item.video">
<video :src="item.video.src" :poster="item.video.poster" controls style="height: 300rpx;width: 500rpx;" loop></video>
</view>
<!-- 时间|操作 -->
<view class="flex align-center justify-between">
<text class="font-sm text-light-muted">{{item.create_time|formatTime}}</text>
<view class="rounded p-1 bg-light" @click="$emit('action',{item,index})">
<text class="text-hover-primary iconfont font"></text>
</view>
</view>
<!-- 点赞列表,评论列表 -->
<view class="bg-light mt-2" v-if="item.supports.length || item.comments.length">
<!-- 点赞 -->
<view v-if="item.supports.length" class="border-bottom flex align-start p-2">
<text class="flex-shrink iconfont font text-hover-primary"></text>
<view class="flex flex-wrap flex-1 ml-1">
<text v-for="(s,si) in item.supports" :key='si' class="font text-hover-primary ml-1">{{s.username}}</text>
</view>
</view>
<!-- 评论 -->
<view v-if="item.comments.length" class="border-bottom flex align-start p-2">
<text class="flex-shrink iconfont font-md text-hover-primary"></text>
<view class="flex flex-column flex-wrap flex-1 ml-2">
<view class="flex" v-for="(c,ci) in item.comments" :key="ci">
<text class="text-hover-primary font">{{c.username}}:</text>
<text class="font text-dark flex-1">{{c.content}}</text>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import freeAvatar from '@/components/free-ui/free-avatar.vue';
import freeImage from '@/components/free-ui/free-image.vue';
import $T from '@/common/free-lib/time.js';
export default {
components:{
freeAvatar,
freeImage
},
filters:{
formatTime(value){
return $T.gettime(value);
}
},
props:{
item:Object,
index:Number
},
methods:{
// 查看大图
preview(src){
uni.previewImage({
current:src,
urls:this.item.image
})
}
}
}
</script>
<style>
</style>
// free-popup.vue
<template>
<div style="z-index:9999;overflow:hidden;" v-if="status">
<!-- 蒙版 -->
<view v-if="mask" class="position-fixed top-0 left-0 right-0 bottom-0" :style="getMaskColor" @click="hide"></view>
<!-- 弹出框内容 -->
<div ref="popup" class="position-fixed free-animated" :class="getBodyClass" :style="getBodyStyle">
<slot></slot>
</div>
</div>
</template>
<script>
// #ifdef APP-PLUS-NVUE
const animation = weex.requireModule('animation');
// #endif
export default {
props: {
// 是否开启蒙版颜色
maskColor: {
type: Boolean,
default: false
},
// 是否开启蒙版
mask:{
type:Boolean,
default:true
},
// 是否居中
center:{
type:Boolean,
default:false
},
// 是否处于底部
bottom:{
type:Boolean,
default:false
},
// 弹出层内容高度
bodyHeight:{
type:Number,
default:0
},
// 弹出层内容宽度
bodyWidth:{
type:Number,
default:0
},
bodyBgColor:{
type:String,
default:'bg-white'
},
transformOrigin:{
type:String,
default:'left top'
},
// tabbar高度
tabbarHeight:{
type:Number,
default:0
}
},
data() {
return {
status: false,
x:-1,
y:1,
maxX:0,
maxY:0
}
},
mounted() {
try {
const res = uni.getSystemInfoSync();
this.maxX = res.windowWidth - uni.upx2px(this.bodyWidth)
this.maxY = res.windowHeight - uni.upx2px(this.bodyHeight) - uni.upx2px(this.tabbarHeight)
} catch (e) {
// error
}
},
computed: {
getMaskColor() {
let i = this.maskColor ? 0.5 : 0
return `background-color: rgba(0,0,0,${i});`
},
getBodyClass(){
if(this.center){
return 'left-0 right-0 bottom-0 top-0 flex align-center justify-center';
}
let bottom = this.bottom ? 'left-0 right-0 bottom-0' : 'rounded border'
return `${this.bodyBgColor} ${bottom}`;
},
getBodyStyle(){
let left = this.x > -1 ? `left:${this.x}px;` : ''
let top = this.y > -1 ? `top:${this.y}px;` : ''
return left + top
}
},
methods:{
show(x=-1,y=-1){
if(this.status){
return;
}
this.x = (x > this.maxX) ? this.maxX : x;
this.y = (y > this.maxY) ? this.maxY : y;
this.status = true
// #ifdef APP-PLUS-NVUE
this.$nextTick(()=>{
animation.transition(this.$refs.popup,{
styles:{
transform:'scale(1,1)',
transformOrigin:this.transformOrigin,
opacity:1
},
duration:100, //ms
timingFunction:'ease',
},()=>{
console.log('动画执行结束');
})
})
// #endif
},
hide(){
this.$emit('hide');
// #ifdef APP-PLUS-NVUE
this.$nextTick(()=>{
animation.transition(this.$refs.popup,{
styles:{
transform:'scale(0,0)',
transformOrigin:this.transformOrigin,
opacity:0
},
duration:100, //ms
timingFunction:'ease',
},()=>{
this.status = false;
})
})
// #endif
}
}
}
</script>
<style scoped>
.free-animated{
/* #ifdef APP-PLUS-NVUE */
/* transform: scale(0,0);
opacity: 0; */
/* #endif */
}
.z-index{
/* #ifndef APP-NVUE */
z-index: 9999;
/* #endif */
}
</style>
// free-icon-button.vue
<template>
<view class="flex align-center justify-center"
hover-class="bg-hover-light" @click="$emit('click')"
style="height: 90rpx;width: 90rpx;">
<slot></slot>
</view>
</template>
<script>
export default {
props: {
icon: {
type: String,
default: ''
},
},
mounted() {
// #ifdef APP-PLUS-NVUE
// 加载公共图标库
const domModule = weex.requireModule('dom')
domModule.addRule('fontFace', {
'fontFamily': "iconfont",
'src': "url('/static/font_1365296_2ijcbdrmsg.ttf')"
});
// #endif
}
}
</script>
<style>
</style>
// free-main-button.vue
<template>
<view class="rounded mr-2 px-2 py-1"
@click="clickEvent"
:class="disabled ? 'bg-light border' : 'main-bg-color'">
<text class="font"
:class="disabled ? 'text-light-muted':'text-white'">{{name}}</text>
</view>
</template>
<script>
export default {
props: {
name: {
type: String,
default: ""
},
disabled:{
type:Boolean,
default:false
}
},
methods: {
clickEvent() {
if(!this.disabled){
this.$emit('click')
}
}
},
}
</script>
<style>
</style>
感谢大家观看,我们下期见。
以上是关于uni-app 17朋友圈开发的主要内容,如果未能解决你的问题,请参考以下文章