目录
#上拉加载更多
添加提示信息
<view class='load-more'>{{loadtext}}</view>
监听触底事件
@scrolltolower="loadmore(index)"
向服务器请求更多数据
//上拉加载更多
loadmore(index) {
if (this.newslist[index].loadtext != "上拉启动半部电台,接收更多电波") {
return;
}
//修改状态
this.newslist[index].loadtext = "滴滴滴...半部电台正在接收中...";
//获取数据
setTimeout(() => {
//获取完成
let obj = {
userpic: "../../static/tabbar/hacker.png",
username: "光谷小五郎",
isSubscribed: false,
title: "出售半部电台!",
type: "img", //img 图文 video 视频
titlepic: "../../static/code.jpg",
thumbs: {
up_count: 11,
down_count: 12,
isThumb: 2 //0 未操作 1 顶 2踩
},
video: {},
comment_num: 10,
share_num: 10
};
this.newslist[index].list.push(obj);
this.newslist[index].loadtext = "上拉启动半部电台,接收更多电波";
}, 1000)
// this.newslist[index].loadtext = "上拉启动半部电台,接收更多电波";
// this.newslist[index].loadtext = "滴滴滴...半部电台正在接收中...";
// this.newslist[index].loadtext = "没有更多电波了";
}
#vue 引入animate动画库
官网直接下载,然后只需要将animate.css 引入到项目中,就可以直接使用了
一般对应的类名前都有前缀animate_
使用方法:
animate_animated animate_动画名
#自定义导航栏
需要引入的组件有
uni-nav-bar组件:
<template>
<view class="uni-navbar">
<view :class="{ 'uni-navbar--fixed': fixed, 'uni-navbar--shadow': shadow, 'uni-navbar--border': border }" :style="{ 'background-color': backgroundColor }" class="uni-navbar__content">
<uni-status-bar v-if="statusBar" />
<!-- 导航栏 -->
<view :style="{ color: color,backgroundColor: backgroundColor }" class="uni-navbar__header uni-navbar__content_view">
<!-- 左边按钮 -->
<view @tap="onClickLeft" class="uni-navbar__header-btns uni-navbar__header-btns-left uni-navbar__content_view">
<view class="uni-navbar__content_view" v-if="leftIcon.length">
<uni-icons :color="color" :type="leftIcon" size="24" />
</view>
<view :class="{ 'uni-navbar-btn-icon-left': !leftIcon.length }" class="uni-navbar-btn-text uni-navbar__content_view" v-if="leftText.length">
<text :style="{ color: color, fontSize: '14px' }">{{ leftText }}</text>
</view>
<slot name="left" />
</view>
<!-- 中间部分 -->
<view class="uni-navbar__header-container uni-navbar__content_view">
<view class="uni-navbar__header-container-inner uni-navbar__content_view" v-if="title.length">
<text class="uni-nav-bar-text" :style="{color: color }">{{ title }}</text>
</view>
<!-- 标题插槽 -->
<slot />
</view>
<!-- 右边按钮 -->
<view :class="title.length ? 'uni-navbar__header-btns-right' : ''" @tap="onClickRight" class="uni-navbar__header-btns uni-navbar__content_view">
<view class="uni-navbar__content_view" v-if="rightIcon.length">
<uni-icons :color="color" :type="rightIcon" size="24" />
</view>
<!-- 优先显示图标 -->
<view class="uni-navbar-btn-text uni-navbar__content_view" v-if="rightText.length && !rightIcon.length">
<text class="uni-nav-bar-right-text">{{ rightText }}</text>
</view>
<slot name="right" />
</view>
</view>
</view>
<view class="uni-navbar__placeholder" v-if="fixed">
<uni-status-bar v-if="statusBar" />
<view class="uni-navbar__placeholder-view" />
</view>
</view>
</template>
<script>
import uniStatusBar from "../uni-status-bar/uni-status-bar.vue";
import uniIcons from "../uni-icons/uni-icons.vue";
/**
* NavBar 自定义导航栏
* @description 导航栏组件,主要用于头部导航
* @tutorial https://ext.dcloud.net.cn/plugin?id=52
* @property {String} title 标题文字
* @property {String} leftText 左侧按钮文本
* @property {String} rightText 右侧按钮文本
* @property {String} leftIcon 左侧按钮图标(图标类型参考 [Icon 图标](http://ext.dcloud.net.cn/plugin?id=28) type 属性)
* @property {String} rightIcon 右侧按钮图标(图标类型参考 [Icon 图标](http://ext.dcloud.net.cn/plugin?id=28) type 属性)
* @property {String} color 图标和文字颜色
* @property {String} backgroundColor 导航栏背景颜色
* @property {Boolean} fixed = [true|false] 是否固定顶部
* @property {Boolean} statusBar = [true|false] 是否包含状态栏
* @property {Boolean} shadow = [true|false] 导航栏下是否有阴影
* @event {Function} clickLeft 左侧按钮点击时触发
* @event {Function} clickRight 右侧按钮点击时触发
*/
export default {
name: "UniNavBar",
components: {
uniStatusBar,
uniIcons
},
props: {
title: {
type: String,
default: ""
},
leftText: {
type: String,
default: ""
},
rightText: {
type: String,
default: ""
},
leftIcon: {
type: String,
default: ""
},
rightIcon: {
type: String,
default: ""
},
fixed: {
type: [Boolean, String],
default: false
},
color: {
type: String,
default: "#000000"
},
backgroundColor: {
type: String,
default: "#FFFFFF"
},
statusBar: {
type: [Boolean, String],
default: false
},
shadow: {
type: [Boolean, String],
default: false
},
border: {
type: [Boolean, String],
default: true
}
},
mounted() {
if (uni.report && this.title !== '') {
uni.report('title', this.title)
}
},
methods: {
onClickLeft() {
this.$emit("clickLeft");
},
onClickRight() {
this.$emit("clickRight");
}
}
};
</script>
<style scoped>
.uni-nav-bar-text {
/* #ifdef APP-PLUS */
font-size: 34rpx;
/* #endif */
/* #ifndef APP-PLUS */
font-size: 16;
/* #endif */
}
.uni-nav-bar-right-text {
font-size: 14px;
}
.uni-navbar__content {
position: relative;
background-color: #ffffff;
overflow: hidden;
}
.uni-navbar__content_view {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
align-items: center;
flex-direction: row;
/* background-color: #FFFFFF;
*/
}
.uni-navbar__header {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
height: 44px;
line-height: 44px;
font-size: 16px;
/* background-color: #ffffff;
*/
}
.uni-navbar__header-btns {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-wrap: nowrap;
width: 120rpx;
padding: 0 6px;
justify-content: center;
align-items: center;
}
.uni-navbar__header-btns-left {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
width: 150rpx;
justify-content: flex-start;
}
.uni-navbar__header-btns-right {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
width: 150rpx;
padding-right: 30rpx;
justify-content: flex-end;
}
.uni-navbar__header-container {
flex: 1;
}
.uni-navbar__header-container-inner {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex: 1;
align-items: center;
justify-content: center;
font-size: 14px;
}
.uni-navbar__placeholder-view {
height: 44px;
}
.uni-navbar--fixed {
position: fixed;
z-index: 998;
}
.uni-navbar--shadow {
/* #ifndef APP-NVUE */
box-shadow: 0 1px 6px #ccc;
/* #endif */
}
.uni-navbar--border {
border-bottom-width: 1rpx;
border-bottom-style: solid;
border-bottom-color: #e5e5e5;
}
</style>
使用方法:
<!-- 自定义导航栏 -->
<uni-nav-bar :statusBar='true' rightText="发布电波" left-icon="arrowleft" @clickLeft="back" @clickRight="submit">
<view class='flex-xy-center' style="width: 100%;" @tap='changelook'>
<view style='margin-right:20rpx;'>{{cat}}</view>
<view class='iconfont icon-tubiaozhizuo-'></view>
</view>
</uni-nav-bar>
#多图上传组件
<!-- 多图上传组件 -->
<template>
<view class="uni-list list-pd">
<view class="uni-list-cell cell-pd">
<view class="uni-uploader">
<view class="uni-uploader-head">
<view class="uni-uploader-title">点击可预览选好的图片</view>
<view class="uni-uploader-info">{{imageList.length}}/9</view>
</view>
<view class="uni-uploader-body">
<view class="uni-uploader__files">
<block v-for="(image,index) in imageList" :key="index">
<view class="uni-uploader__file">
<!-- 删除 -->
<view class='iconfont icon-shanchu' @tap="delPic(index)"></view>
<image class="uni-uploader__img" :src="image" :data-src="image" @tap="previewImage"></image>
</view>
</block>
<view class="uni-uploader__input-box">
<view class="uni-uploader__input" @tap="chooseImage"></view>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
var sourceType = [
['camera'],
['album'],
['camera', 'album']
]
var sizeType = [
['compressed'],
['original'],
['compressed', 'original']
]
export default{
data(){
return {
imageList: [],
sourceTypeIndex: 2,
sourceType: ['拍照', '相册', '拍照或相册'],
sizeTypeIndex: 2,
sizeType: ['压缩', '原图', '压缩或原图'],
countIndex: 8,
count: [1, 2, 3, 4, 5, 6, 7, 8, 9]
}
},
methods:{
// 选择图片
chooseImage: async function() {
// #ifdef APP-PLUS
// TODO 选择相机或相册时 需要弹出actionsheet,目前无法获得是相机还是相册,在失败回调中处理
if (this.sourceTypeIndex !== 2) {
let status = await this.checkPermission();
if (status !== 1) {
return;
}
}
// #endif
if (this.imageList.length === 9) {
return;
}
uni.chooseImage({
sourceType: sourceType[this.sourceTypeIndex],
sizeType: sizeType[this.sizeTypeIndex],
count: this.imageList.length + this.count[this.countIndex] > 9 ? 9 - this.imageList.length : this.count[this.countIndex],
success: (res) => {
this.imageList = this.imageList.concat(res.tempFilePaths);
//将imageList传送给父组件
this.$emit('upload',this.imageList);
},
fail: (err) => {
// #ifdef APP-PLUS
if (err['code'] && err.code !== 0 && this.sourceTypeIndex === 2) {
this.checkPermission(err.code);
}
// #endif
// #ifdef MP
uni.getSetting({
success: (res) => {
let authStatus = false;
switch (this.sourceTypeIndex) {
case 0:
authStatus = res.authSetting['scope.camera'];
break;
case 1:
authStatus = res.authSetting['scope.album'];
break;
case 2:
authStatus = res.authSetting['scope.album'] && res.authSetting['scope.camera'];
break;
default:
break;
}
if (!authStatus) {
uni.showModal({
title: '授权失败',
content: 'App需要从您的相机或相册获取图片,请在设置界面打开相关权限',
success: (res) => {
if (res.confirm) {
uni.openSetting()
}
}
})
}
}
})
// #endif
}
})
},
//预览图片
previewImage: function(e) {
var current = e.target.dataset.src
uni.previewImage({
current: current,
urls: this.imageList
})
},
// 删除图片
delPic(index) {
uni.showModal({
title: "提示",
content: "是否要删除该图片?",
success: (res) => {
if (res.confirm) {
this.imageList.splice(index, 1);
//将imageList传送给父组件
this.$emit('upload',this.imageList);
}
}
})
}
}
}
</script>
<style scoped>
.cell-pd {
padding: 22rpx 30rpx;
}
.uni-list {
color: #999;
}
.uni-uploader__file {
position: relative;
}
.icon-shanchu {
position: absolute;
top: 0px;
right: 0px;
background-color: #333333;
color: #fff;
z-index: 99;
padding: 1px 10rpx;
border-radius: 2px;
}
</style>
使用方法:
<!-- 上传多图 -->
<uploadImages @upload="onUpload"></uploadImages>
//导入
import uploadImages from '../../components/common/upload-images.vue';
//从子组件接受上传的图片列表,便于父组件作为表单提交给服务端
onUpload(arr){
this.imglist = arr;
}
#动态修改导航栏的标题
建议写在Onload中,可以实现根据跳转传参来动态修改本页面的标题
//修改窗口标题
uni.setNavigationBarTitle({
title:标题
})
#跳转并传参
例如:当需要传一个对象时候,需要先将对象 序列化
uni.navigateTo({
"url":"/pages/detail/detail?detailData="+JSON.stringify(this.item)
})
然后在 跳转页面的 OnLoad函数中接受参数,并反序列化
OnLoad(e){
let obj = JSON.parse(e.detailData);
}