uniapp 开发实操一 :列表与表单提交
目前随着5g网络的不断普及以及web app 跨平台的优势,web app已经逐渐成了 普通app 开发的首选框架。uni-app基于Vue.js实现的。所以它具备了vue.js前端的所有优势。而且uniapp 有很丰富的第三方插件,可以很方便的用一套代码开发公众号与小程序。先上图,效果如下:html5页面:小程序页面:1、列表页面代码:这里用引入了mescroll 上拉下拉第三方插件,非常好用。
目前随着5g网络的不断普及以及web app 跨平台的优势,web app已经逐渐成了 普通app 开发的首选框架。uni-app基于Vue.js实现的。所以它具备了vue.js前端的所有优势。而且uniapp 有很丰富的第三方插件,可以很方便的用一套代码开发公众号与小程序。先上图,效果如下:
html5页面:
小程序页面:
1、列表页面代码:这里用引入了mescroll 上拉下拉第三方插件,非常好用。
<template>
<view class="container">
<bar :nav="setNav"></bar>
<mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback" >
<view class="notice"></view>
<good-list :list="goods"></good-list>
</mescroll-body>
</view>
</template>
<script>
import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
import bar from '../components/bar';
export default {
mixins: [MescrollMixin], // 使用mixin
components:{
bar
},
data() {
return {
baseUrl:getApp().globalData.baseUrl,
goods: [],
setNav:{
'bg':'yellow', //背景色
'color':'red', //字体颜色
'isdisPlayNavTitle':true, //是否显示返回按钮,由于导航栏是共用的,把所有的东西封装好,
'isdisPlayNavLeftButton':true,
// 然后有些页面不需要的东西通过条件控制进行显示与隐藏
'navTitle':'商品列表' //导航标题
}// 数据列表
}
},
methods: {
/*上拉加载的回调: 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 */
upCallback(page) {
console.log("调用2:"+page.num);
console.log("this.baseUrl:"+this.baseUrl);
uni.request({
url: this.baseUrl+'/app/secondHand/list', //仅为示例,并非真实接口地址。
contentType: "application/json;charset=utf-8",
data : JSON.stringify({ 'page':page.num,'rows':8}),
dataType : "json",
method: "POST",
header: {
'custom-header': 'hello' //自定义请求头信息
},
success: (res) => {
console.log(res);
//this.goods=res.data.data;
this.mescroll.endSuccess(res.data.data.length);
//this.mescroll.endByPage(this.goods.length,100); //必传参数(当前页的数据个数, 总页数)
//设置列表数据
//if(page.num == 1) this.goods = []; //如果是第一页需手动制空列表
this.goods=this.goods.concat(res.data.data); //追加新数据
},
fail: () => {
this.mescroll.endErr();
console.log("失败");
}
});
}
}
}
</script>
<style>
/*说明*/
.notice{
font-size: 26upx;
padding: 40upx 0;
border-bottom: 1upx solid #eee;
text-align: center;
color:#555;
}
.container{
display: flex;
flex-direction: colum;
}
mescroll-body{
margin-top:50rpx;
}
</style>
2、列表项组件页面:vue.js 就是组件化更方便,相比微信小程序原生代码结构会更方便些。
<template>
<view class="good-list">
<view :id="'good'+good.id" class="good-li" v-for="good in list" :key="good.id">
<image class="good-img" :src="getImgUrl(good.goodPic)" mode="scaleToFill"/>
<view class="item_data">
<view class="item_1">
<text class="good-name">{{good.goodName}}</text>
<text class="good-price">{{good.goodPrice}} 元</text>
</view>
<text class="good-desc">{{good.goodDesc}}</text>
</view>
</view>
</view>
</template>
<script>
export default {
props:{
list: {
type: Array,
default(){
return []
}
}
},
methods: {
getImgUrl(icon){
console.log("getApp().globalData.host:"+getApp().globalData.host);
return getApp().globalData.host+icon;
}
}
}
</script>
<style lang="scss">
.good-list{
background-color: #000000;
width:750rpx;
.good-li{
display: flex;
flex-direction:row;
align-items: center;
padding:20rpx;
background-color: #fef;
border-bottom: 1upx solid #eee;
.good-img{
width: 160upx;
height: 160upx;
margin-right: 20rpx;
}
.item_data{
display: flex;
flex-direction:column;
width:100%;
.item_1{
display: flex;
flex-direction:row;
justify-content:space-between;
width:100%;
.good-name{
font-size: 30rpx;
height: 80upx;
margin-bottom: 20upx;
overflow: hidden;
}
.good-price{
font-size: 30rpx;
}
.good-sold{
font-size: 24upx;
margin-left: 16upx;
color: gray;
}
}
.good-desc{
font-size: 30rpx;
}
}
}
}
</style>
3、新增页面:集成了第三方上传组件htz-image-upload
<template>
<view class="container">
<bar :nav="setNav"></bar>
<view class="uni-padding-wrap uni-common-mt">
<form @submit="formSubmit" @reset="formReset">
<view class="row_style">
<text class="title">物品名称:</text>
<input class="uni-input" name="goodName" placeholder="请输入物品名称" />
</view>
<view class="row_style">
<text class="title">新旧程度:</text>
<picker @change="bindPickerChange" :value="newLevel" :range="array" range-key="name">
<view class="uni-input">{{array[newLevel].name}}</view>
</picker>
</view>
<view class="row_style">
<text class="title">物品价格:</text>
<input class="uni-input" type="number" name="goodPrice" placeholder="请输入价格" />
</view>
<view class="colum_style">
<text class="title">物品图片或视频:</text>
<htz-image-upload :max="19" v-model="ceshiData" mediaType="all" :chooseNum="9" :sourceType="['album','camera']"
:compress="false" :quality="80" :formData="{'businessType': 'ershou'}" :remove="true"
@uploadSuccess="ceshiUploadSuccess" @imgDelete="ceshiImgDelete" @uploadFail="ceshiUploadFail"
:action="mediaActionUrl"></htz-image-upload>
</view>
<view class="colum_style">
<text class="title">物品描述:</text>
<textarea name="goodDesc" placeholder-style="color:#666666" placeholder="请输入物品描述不少20个字"/>
</view>
<view class="uni-btn-v">
<button form-type="submit" plain="true">发布</button>
</view>
</form>
</view>
</view>
</template>
<script>
// import htzImageUpload from '/components/htz-image-upload/htz-image-upload.vue'
import bar from '@/components/bar';
var graceChecker = require("../../common/graceChecker.js");
export default {
components:{
bar
},
data() {
return {
baseUrl:getApp().globalData.baseUrl,
array: [{name:'9成新'},{name: '8成新'}, {name:'7成新'}, {name:'7成以下'}],
newLevel: 0,
ceshiData: [
],
incAttachments:"",
setNav:{
'bg':'yellow', //背景色
'color':'red', //字体颜色
'isdisPlayNavTitle':true, //是否显示返回按钮,由于导航栏是共用的,把所有的东西封装好,
'isdisPlayNavLeftButton':false,
// 然后有些页面不需要的东西通过条件控制进行显示与隐藏
'navTitle':'新增物品' //导航标题
},// 数据列表
mediaActionUrl:getApp().globalData.baseUrl+'/app/attachment/upload/Media'
}
},
methods: {
bindPickerChange: function(e) {
console.log('picker发送选择改变,携带值为:' + e.detail.value)
this.newLevel = e.detail.value;
},
formSubmit: function(e) {
console.log('form发生了submit事件,携带数据为:' + JSON.stringify(e.detail.value))
//定义表单规则
var rule = [
{name:"goodName", checkType : "string", checkRule:"1,10", errorMsg:"物品名称应为1-10个字符"},
{name:"goodDesc", checkType : "string", checkRule:"20,", errorMsg:"物品描述不少20个字符"},
];
//进行表单检查
var formData = e.detail.value;
var incAttachments=this.incAttachments.substring(0,this.incAttachments.length-1);
formData["incAttachments"]=incAttachments;
formData["newLevel"]=this.newLevel;
var checkRes = graceChecker.check(formData, rule);
if(checkRes){
if(this.ceshiData.length <= 0){
uni.showToast({title:"请添加物品图片或视频!", icon:"none"});
return;
}
if(formData['goodPrice'].length <=0){
uni.showToast({title:"请输入价格!", icon:"none"});
return;
}
//uni.showToast({title:"验证通过!", icon:"none"});
uni.request({
url: getApp().globalData.baseUrl+"/app/secondHand/add",
data: JSON.stringify(formData),
method: "post",
success:(res)=> {
uni.showToast({title:"提交成功!", icon:"none"});
console.log(JSON.stringify(res));
uni.navigateBack({
});
},
fail:(res)=>{
uni.showToast({title:"提交成功!", icon:"none"});
}
});
}else{
uni.showToast({ title: graceChecker.error, icon: "none" });
}
},
ceshiUploadSuccess(res) { //上传成功
console.log('res', this)
/****************
因为上传接口返回的结构不一致,所以以下代码需要根据实际的接口返回结构开发,在此只是展示如果给数组里添加的过程,仅供参考
***************/
var _res = JSON.parse(res.data);
console.log('_res', _res)
if (_res.success) {
this.ceshiData.push(getApp().globalData.host+"/" + _res.data.path);
this.incAttachments+=_res.data.id+",";
}
/*******************************/
},
ceshiUploadFail(err) { //上传失败
console.log('err', err)
},
ceshiImgDelete(e) {
console.log('ceshiImgDelete', e)
},
formReset: function(e) {
console.log('清空数据')
}
}
}
</script>
<style>
.uni-form-item .title {
width: 150rpx;
text-align: right;
}
.uni-input{
width:560rpx;
margin-left: 10rpx;
}
.row_style{
display: flex;
flex-direction: row;
margin-left: 15rpx;
margin-right: 15rpx;
margin-top: 30rpx;
}
.colum_style{
display: flex;
flex-direction: column;
margin-left: 15rpx;
margin-right: 15rpx;
margin-top: 30rpx;
}
</style>
更多推荐
所有评论(0)