「这是我参与2022首次更文挑战的第22天,活动详情查看:2022首次更文挑战」
大家好,我是 摸鱼小公举,真正的强者,不会怨天尤人,如果想不被别人看轻,你就只有付出比别人多十倍百倍的努力,才能站的比别人更高。上一篇文章是 监听滚动事件来控制页面变化 ;今天我们来学习一下 用uni-app的表单组件来实现微信小程序的表单使用。
文本输入框
文本输入框,不管是单行还是多行文本输入框都很像原生的标签那样,但是属性有很多,又不像原生的input和textarea。
单行文本输入框 input
原生input不仅是输入框,还有radio、checkbox、时间、日期、文件选择功能。在uni-app中仅仅是输入框,其他功能uni-app有单独的组件。
<view class="uni-form-item uni-column">
<view class="title"> 单行文本输入框</view>
<input v-model="userName" class="uni-input"
:name="userName" :placeholder="请输入文本框内容"/>
</view>
多行文本输入框textarea
注意:textarea 的 blur 事件会晚于页面上的 tap 事件,如果需要在 button 的点击事件获取 textarea,可以使用 form 的 @submit
<view class="uni-form-item uni-column">
<view class="title"> 多行文本输入框</view>
<textarea v-model="content" :name="item.name"
:placeholder="`请输入文本框内容" :auto-height="false"/>
</view>
单选框 radio
这里的check属性遍历到哪一项为true,那么久选中,我这里是用了数组的索引值相等的条件来判断,我这里默认了索引值为0选中。然后需要借助change事件来更新所选的值。由于uni-app的radio没有v-model的属性,所以后台需要的值也从change事件中获取;radio中的value值绑定可设置change事件中返回的是id还是name的值。
HTML代码
<view class="uni-form-item uni-column">
<view class="title">单选框</view>
<radio-group :name="radioName" @change="radioChange">
<label v-for="(subItem,index) in items" :key="index">
<radio :value="subItem。id" :checked="index==current" />
<text>{{ subItem.name }}</text>
</label>
</radio-group>
</view>
JS代码
// 数据结构: items: [
// { id: 1, name: '苹果' },
// { id: 2, name: '香蕉' },
// { id: 3, name: '芒果' },
// { id: 4, name: '草莓' }]
//methods里面的方法
radioChange: function(evt) {
console.log(evt.detail.value,"value");//1 2 3 4
for (let i = 0; i < this.items.length; i++) {
if (this.items[i].id === evt.detail.value.id) {
this.current = i;
break;
}
}
},
效果如下
多选框 checkbox
checkbox的属性和radio的属性差不多一样。就是这个checked属性的更新值不一样,是通过判断change事件返回的value值是否包含items中遍历项的value,包含则this.$set添加checked属性并设置true,反之为false。
HTML 代码
<view class="uni-form-item uni-column">
<view class="title">多选框</view>
<checkbox-group :name="checkboxName" @change="checkboxChange">
<label v-for="(subItem,index) in items" :key="subItem.id">
<checkbox :value="subItem.name" :checked="subItem.checked" />
<text>{{ subItem.name }}</text>
</label>
</checkbox-group>
</view>
JS代码 数据与上述一样
checkboxChange (e) {
var items = this.items,
values = e.detail.value;
for (var i = 0, lenI = items.length; i < lenI; ++i) {
const item = items[i]
if(values.includes(item.value)){
this.$set(item,'checked',true)
}else{
this.$set(item,'checked',false)
}
}
},
效果如下
下拉框 picker
这里的value不能跟多选框和单选框那样设置@change事件返回的值,picker组件的change事件返回的是数组的下标。而input显示出来的值是通过返回的数组下标值来匹配显示出来的。最重要的这里数组对象的数据结构,控制下拉筛选内容显示的不是value-key而是range-key。
HTML代码
<view class="uni-form-item uni-column">
<view class="title"> 下拉框</view>
<picker @change="onSelectChange" :range="items" range-key="name" >
<input class="uni-input" :name="pickerName" :placeholder="`请选择类型`"
:value="items[pickerData].name" :disabled="true"/>
</picker>
</view>
JS代码 数据与上述一样
onSelectChange: function(e) {
console.log('value', e.target.value) //数组的下标
this.pickerData = e.target.value
},
效果如下
上传功能
小程序里面的上传功能跟H5的不一样,小程序是上传的api调用,而h5是组件的调用。上传功能具体使用的代码如下。
首先来看HTML部分,这里CSS样式省略
这里我们可以看到有一个isError是控制抛出错误路径后显示默认图片,不只是上传图片这里,还有别的后台返回的图片链接都需要给一个错误图片路径后的默认图片,要不然显示出来的页面体验不好。
<view class="uni-form-item uni-column">
<view class="title">上传图片:</view>
<block v-if="upload_url" >
<image v-if="isError" :src="image_url+'imgs/default.png'" style="width: 200rpx; height:
200rpx;border-radius: 8rpx;" @tap="chooseImage(item)" @error="imageError" alt="">
</image>
<image :src="upload_url" style="width: 200rpx; height: 200rpx;border-radius: 8rpx;"
@tap="chooseImage(item)" @error="imageError" alt="">
</image>
</block>
<block v-else>
<view class="uni-hello-addfile" @tap="chooseImage(item)">+ 选择图片</view>
</block>
</view>
再来看JS逻辑代码部分
这里有控制默认图片显隐的方法,和上传图片的方法(这里api的代码有点长);首先调用uni.chooseImage从本地相册选择一张图片,成功后调用uni.uploadFile同时在此api方法里调用上传的接口,调用接口要注意的是要传请求头的参数,接口调用成功后会返回一个图片的链接,接口调用失败则返回错误信息;若uni.uploadFile调用失败则提示请重试,若uni.chooseImage调用失败则需要uni.getSetting获取用户的当前设置,若授权失败则需要提示弹框“从您的相册获取图片,请在设置界面打开相关权限”,点击弹框确认按钮调用uni.openSetting调起客户端小程序设置界面
imageError(){
this.isError=true
},
chooseImage() {
uni.chooseImage({
count: 1,sizeType: ["compressed"],sourceType: ["album"],
success: (res) => {
var imageSrc = res.tempFilePaths[0];
uni.uploadFile({
url: this.base_url.base_url+"/v1/upload/index",
filePath: imageSrc,
fileType: "image",
name: "file",
formData: {
path_type: "course",
},
header: {
"user-token": uni.getStorageSync("token"),
"x-shop-token": uni.getStorageSync("token"),
},
success: (res) => {
res = JSON.parse(res.data);
if (res.code === 1) {
uni.showToast({
title: "图片上传成功",
icon: "success",
duration: 1000,
});
this.upload_url = res.data.src;
this.isError=false
} else {
uni.showToast({
title: res.msg,
icon: "none",
});
}
},
fail: (err) => {
uni.showToast({
title: "图片上传失败,请重试",
icon: "none",
});
},
});
},
fail: (err) => {
// #ifdef MP
uni.getSetting({
success: (res) => {
let authStatus = res.authSetting["scope.album"];
if (!authStatus) {
uni.showModal({
title: "授权失败",
content:
"Hello uni-app需要从您的相册获取图片,请在设置界面打开相关权限",
success: (res) => {
if (res.confirm) {
uni.openSetting();
}
},
});
}
},
});
// #endif
},
});
},
效果如下
结语:
刚开始我用uni-app来写小程序,我大部分用来vue的语法来写,好家伙,结果浏览器是能预览出页面,到了微信小程序那边代码跑不动了。因为不能用vue语法来写小程序,必须要用微信小程序的语法来写。 好了文章到此就结束了,欢迎大家( 点赞+评论+关注 ) 有问题可以来互相交流一下。希望这篇文章对大家有帮助,也希望大家多多支持我,今天是我参与2022首次更文挑战的第22天,加油!坚持就是胜利。