mui开发总结----基本上解决了开发过程中遇到的大多数问题

mui开发过程遇到的问题和解决方案

  • 最近接触了一个老项目是使用的mui(webapp),一段时间下来的有一些感受,这里大致说一下项目开发过程中的体会
    • 上手非常容易----html5+js+css没问题的话,就等于直接入门了
    • 坑很多----在开发的过程中,mui本身提供了很多的例子,很多组件都是可以拿过来使用的,但是在一些情况下,这些组件之间会有冲突,导致各种报错,但是知道解决方案之后,也就很顺畅了
    • 开发效率高----熟练之后,开发效率很高
    • 丰富的api----提供很多api,可以直接拿过来使用,非常方便
    • 跨平台----一套代码,android和ios两个环境运行
    • 界面UI----ui框架的界面效果一般般
问题和解决方案
1.页面传值

一个项目避免不了页面之间的交互,在mui中页面之间的传值是通过事件监听的方式来实现的(这里使用的是mui.fire,另外一种为mui.openWindow(extras:{id:this.id},)),例如A页面跳转到B页面,并且给B页面传一个ID值,代码实现如下
A.html:

<!-- 	点击按钮触发跳转事件 -->
<button id="edit" type="button" class="mui-btn mui-btn-blue mui-btn-link" v-on:tap="edit(item.ID)">编辑</button>

A.js:

var vm = new Vue({
	el: '#content',
	created() {
	},
	methods: {
		edit(id) {
			const editShipLanding = plus.webview.getWebviewById('B');
			// 在B页面监听 shipLanding
			mui.fire(editShipLanding , 'shipLanding', {
				id: id // 这个id值会传递到B页面
			});
			mui.openWindow({
				id: 'B',// 这里是B页面的页面id,一般是页面的名称
			});
		}
	}
})
mui.init({
	preloadPages: [{
			id: 'B',// 这里是B页面的页面id,一般是页面的名称
			url: 'B.html'// 页面于当前页面的相对位置,这里是在同一目录下
		}
	],
});

B.html

<h2>{{id}}</h2>

B.js

var vm = new Vue({
	el: '#content',
	data: {
		id:''
	},
	created() {
		
	},
	methods: {
		
	}
});
(function($, doc) {
	$.init();
	window.addEventListener('shipLandingForm', function(event) {
	 vm.id = event.detail.id; // event.detail.id就是A页面传过来的id值 -- event.detail['属性键值'],这就获取到了A页面的值
	});
})(mui, document);
2.http请求

做项目避免不了前后台的交互,mui封装了常用的函数,用于与发送http请求
2.1 get请求

mui.ajax('${this.url}',{
	data: {
		id: this.id
	},
	dataType: 'json',//服务器返回json格式数据
	type: 'get',//HTTP请求类型
	success: function (data) {
		console.log(data);// 获取请求成功的结果
	},
	error: function (error) {
		console.log(error);// 获取的错误信息
	}
});

2.2 post请求

mui.ajax('${this.url}',{
	data: this.userInfo,
	dataType: 'json',//服务器返回json格式数据
	type: 'post',//HTTP请求类型
	headers: {'Content-Type':'application/json'},
	success: function (data) {
		console.log(data);// 获取请求成功的结果
	},
	error: function (error) {
		console.log(error);// 获取的错误信息
	}
});

2.3 put请求

mui.ajax('${this.url}',{
	data: this.userInfo,
	dataType: 'json',//服务器返回json格式数据
	type: 'put',//HTTP请求类型
	headers: {'Content-Type':'application/json'},
	success: function (data) {
		console.log(data);// 获取请求成功的结果
	},
	error: function (error) {
		console.log(error);// 获取的错误信息
	}
});

2.4 delete请求

mui.ajax('${this.url}id=${this.id}',{
	dataType: 'json',//服务器返回json格式数据
	type: 'put',//HTTP请求类型
	headers: {'Content-Type':'application/json'},
	success: function (data) {
		console.log(data);// 获取请求成功的结果
	},
	error: function (error) {
		console.log(error);// 获取的错误信息
	}
});
3.文件下载

有需求要求需要支持移动端可以下载PDF文件,文件下载完成后,会使用手机端的wps打开文件,代码如下

	 var wt = plus.nativeUI.showWaiting();
      var dtask = plus.downloader.createDownload(`${this.url}?id=${event.ID}&inline=true`, {}, function(d, status) {
        if (status == 200) {
          var fileUrl = d.filename;
          plus.runtime.openFile(fileUrl, {}, function(e) {
            alert('打开失败');
          });
          wt.close();
        } else {
          alert('Download failed: ' + status);
          wt.close();
        }
      });
      dtask.start();
4下拉刷新和上拉加载

当数据很多的时候,我们需要去做分页,这个时候就会要用到上拉刷新和下来加载

var vm = new Vue({
	el: '#content',
	data: {
		params: { // 分页参数
			top: 10,
			skip: 0,
			orderby: 'CreateDate desc',// 默认排序条件
		},
		violationList: [],
		listUrl: getApiUrl('PunishSheet'),
		httpUrl: 'http://47.99.116.65:8193/FiveS.Web/Fives.Reports/PunishSheet/Index?punishtype=xq&id',
	},
	created() {
		this.getViolationList();
	},
	methods: {
		getViolationList() {
			gets(this.listUrl, this.params, (data) => {
				this.violationList = data.Results; // 初始化列表
			})
		}
	}
})
mui.init({
	pullRefresh: {
		swipeBack: true,
		container: '#refreshContainer', //待刷新区域标识,querySelector能定位的css选择器均可,比如:id、.class等
		down: { // 下拉刷新
			style: 'circle', //必选,下拉刷新样式,目前支持原生5+ ‘circle’ 样式
			color: '#2BD009', //可选,默认“#2BD009” 下拉刷新控件颜色
			height: '50px', //可选,默认50px.下拉刷新控件的高度,
			range: '100px', //可选 默认100px,控件可下拉拖拽的范围
			offset: '50%', //可选 默认0px,下拉刷新控件的起始位置
			callback: function() {
				vm.params.skip = 0;
				const params = vm.params;
				gets(vm.listUrl, params, (data) => {
					vm.violationList = data.Results;
					mui('#refreshContainer').pullRefresh().endPulldown();
					mui('#refreshContainer').pullRefresh().refresh(true);
				})
			}
		},
		up: { //上拉加载
			height: 50, //可选.默认50.触发上拉加载拖动距离
			contentrefresh: "正在加载...", //可选,正在加载状态时,上拉加载控件上显示的标题内容
			contentnomore: '没有更多数据了', //可选,请求完毕若没有更多数据时显示的提醒内容;
			callback: function() {
				vm.params.skip += 10;
				const params = vm.params;
				gets(vm.listUrl, params, (data) => {
					vm.violationList = vm.violationList.concat(data.Results);
					vm.params.skip >= data.Count ? this.endPullupToRefresh(true) : this.endPullupToRefresh(false);
				})
			}
		}
	}
});
// 封装的get
//按条件获取多条记录
function gets (url, params, success, fail) {
	return _gets (url, params, false, success, fail);
}

function _gets (url, params, countOnly, success, fail) {
	if (params) {
		if (params.filter) {
			url = url + '?$filter=' + params.filter;
		} else {
			url = url + '?$filter=(1 eq 1)';
		}
		if (params.skip) {
			url = url + '&$skip=' + params.skip;
		}
		if (params.top) {
			url = url + '&$top=' + params.top;
		}
		if (params.orderby) {
			url = url + '&$orderby=' + params.orderby;
		}
	}

	var headers = {
		'Content-Type': 'application/json'
	};
	if (app && app.getState() && app.getState().token) {
		headers['token'] = app.getState().token;
	}
	if (countOnly) {
		headers['CountOnly'] = 'CountOnly';
	}

	url = encodeURI(url);
	mui.ajax(url, {
		type: 'get',
		dataType: 'json',
		headers: headers,
		success: function(data) {
			success(data);
		},
		error: function(xhr, type, errorThrown) {
			//console.log(xhr, type, errorThrown);
			if (fail) {
				fail(xhr, type, errorThrown);
			}
		}
	});
}

mui.init();
5.开启左滑返回
mui.init({
	pullRefresh: {
		swipeBack: true //配置开启左滑返回 
		}
});
// 实现左滑返回
mui.plusReady(function() {
	const _self = plus.webview.currentWebview();
	_self.addEventListener('swipeleft', function() {
		mui.back()
	}, false);
});
6.图片上传

在表单中需要将手机中相册中的图片上传(下次使用直接拷贝,修改url以及属性名称即可)
html:

<form class="mui-input-group">
				<div class="form-group">
					<div v-if="upload.imgList.length!==0" v-for="(item, index) in upload.imgList" class="upload">
						<img :src="item.thumbpreView" alt="" data-preview-src="" :data-preview-group="index" />
						<span class="iconfont icon-download" style="background: seagreen;" v-on:tap="operation('download',item)"></span>
						<span class="iconfont icon-shanchu" style="background: indianred;" v-on:tap="operation('delete',item)"></span>
					</div>
					<div class="files" v-on:tap="upLoadImg()"></div>
				</div>
			</form>

js:

var vm = new Vue({
	el: '#content',
	data: {
		uploadUrl: getApiUrl('Base_FileInfor/upload'),
		imgUrl: getApiUrl('Base_FileInfor'),
		isDelete: false,
		id: '',
		files: [],
		upload: {
			imgList: [],
			mataData: []
		},
		imgHttp: 'http://47.99.116.65:8193/fives.web/',
		ids:[],
	},
	created() {},
	methods: {
		upLoadImg() {
			const _self = this;
			// 点击获取选项----排照\从手机相册中选择
			if (mui.os.plus) {
				const a = [{
						title: '拍照'
					},
					{
						title: '从手机相册选择'
					}
				];
				// 添加取消按钮
				plus.nativeUI.actionSheet({
						cancel: '取消',
						buttons: a
					},
					b => {
						/*actionSheet 按钮点击事件*/
						switch (b.index) {
							case 0:
								break;
							case 1:
								_self.getImage(); /*拍照*/
								break;
							case 2:
								_self.galleryImg(); /*打开相册*/
								break;
						}
					}
				);
			}
		},
		getImage() {// 拍照
			var c = plus.camera.getCamera();
			const _self = this;
			c.captureImage(
				function(e) {
					plus.io.resolveLocalFileSystemURL(
						e,
						function(entry) {
							const imgSrc = entry.toLocalURL() + '?version=' + new Date().getTime(); //拿到图片路径
							const ID = new Date().getTime() * Math.random();
							_self.files.push({
								path: imgSrc,
								name: new Date().getTime()
							});

							_self.upload.imgList.push({
								name: 'images' + new Date().getTime(),
								thumbpreView: imgSrc,
								ID: ID,
								isNew: true
							});
						},
						function(e) {
							console.log('读取拍照文件错误:' + e.message);
						}
					);
				},
				function(s) {
					console.log('error' + s);
				}, {
					filename: '_doc/camera/'
				}
			);
		},
		galleryImg() {//打开相册
			const _self = this;
			plus.gallery.pick(
				function(e) {
					for (var i in e.files) {
						const file = e.files[i];
						const ID = new Date().getTime() * Math.random();
						const name = file.substr(file.lastIndexOf('/') + 1);
						_self.files.push({
							name: 'images' + name,
							path: file
						});

						_self.upload.imgList.push({
							name: 'images' + name,
							thumbpreView: file,
							ID: ID,
							isNew: true
						});
					}
				},
				function(e) {}, {
					multiple: true
				}
			);
		},
		fileUpload() {// 点击上传将选择的图片上传
			const _self = this;
			const files = this.files;
			const content = mui.extend({}, {
				RelateID: String(_self.id),
				RelateType: 'EntryShipBerthing',
				TreeID: '-1',
				OrigenName: 'photo'
			});
			var wt = plus.nativeUI.showWaiting();
			if (_self.isDelete === true) {
				_self.fileUploadDelete();// 编辑的时候,涉及到删除,点击上传之后,若是操作的删除.将图片从数据库中删除
			}
			// 图片上传
			var task = plus.uploader.createUpload(
				_self.uploadUrl, {
					method: 'POST'
				},
				function(t, status) {
					//上传完成
					if (status == 200) {
						wt.close();
						mui.toast('上传完成');
						const shipIslanding = plus.webview.getWebviewById('shipIslanding');
						shipIslanding.reload();
						mui.back();
						_self.upload = {
							imgList: [],
							mataData: []
						};
					} else {
						console.log('上传失败:' + status);
						wt.close();
					}
				}
			);

			// 数据
			mui.each(content, function(index, element) {
				task.addData(index, element);
			});
			
			//添加上传文件
			mui.each(_self.files, function(index, element) {
				var f = _self.files[index];
				task.addFile(f.path, {
					key: f.path
				});
			});
			//加用户信息
			task.setRequestHeader('token', app.getState().token);
			//开始上传任务
			task.start();
		},
		operation(event, item) {
			const _self = this;
			switch (event) {
				case 'download':
					const download = plus.downloader.createDownload(item.url, {}, function(dl, status) {
						if (status == 200) {
							plus.gallery.save(
								dl.filename,
								function(event) {
									mui.toast('图片已保存到相册');
								},
								function(error) {
									mui.toast('保存失败');
								}
							);
						} else {
							mui.toast('保存失败');
						}
					});
					download.start();
					break;
				case 'delete':
					mui.confirm('是否要删除?', '警告', ['是', '否'], function(e) {
						if (e.index === 0) {
							_self.isDelete = true;
							// 删除一个图片,先从数组中删除,点击上传才将图片真正的删除
							_self.upload.imgList = _self.upload.imgList.filter(x => x.ID !== item.ID);
							if (_self.files.some(x => x.ID === item.ID)) {
								_self.files = _self.files.filter(x => x.ID !== item.ID);
							}
						}
						
					});
					break;
			}
		},
		fileUploadDelete() {
			// 删除图片
			const mata = this.upload.mataData.map(x => x.ID);
			const list = this.upload.imgList.map(x => x.ID);
			const difference = mata.filter(v => !list.includes(v)).map(x => x);
			const url = `${getApiUrl('Base_FileInfor/DeleteInBatches')}?IDs=${difference}`;
			remove(url, data => {
				
			});
		},
	}
});
(function($, doc) {
	$.init({
		preloadPages: [{
			id: 'shipIslanding',
			url: 'shipIslanding.html'
		}]
	});
	// 获取列表页面的某条数据的id
	window.addEventListener('shipIslandingUpFile', function(event) {
		vm.id = event.detail.id;
		vm.isDelete = false;
		gets(
			vm.imgUrl, {
				filter: `RelateID eq ${vm.id} and RelateType eq 'EntryShipBerthing'`
			},
			res => {
			// 若是没有上传的图片
				if (res.Results === null) {
					vm.upload.imgList = [];
					return;
				}
				// 将图片放到upload,在页面显示
				vm.upload.imgList = res.Results.map(x => {
					return {
						url: vm.imgHttp + GetPicStaticSrc(x.NewName),
						thumbpreView: vm.imgHttp + 'app_data/' + GetPicThumbnailAddress(x.NewName),
						ID: x.ID,
						name: x.OrigenName
					};
				});

				vm.upload.mataData = res.Results.map(x => {
					return {
						url: vm.imgHttp + GetPicStaticSrc(x.NewName),
						thumbpreView: vm.imgHttp + 'app_data/' + GetPicThumbnailAddress(x.NewName),
						ID: x.ID,
						name: x.OrigenName
					};
				});
			}
		);
	});
})(mui, document);
// /***获取图片资源的缩略图地址**/
function GetPicThumbnailAddress(srcOriginal) {
	if (srcOriginal.indexOf('?') !== -1) {
		return '';
	}
	let straddress = GetFileNameNoExt(srcOriginal);
	straddress += '.THUMBPREVIEW';
	straddress += GetFileExt(srcOriginal);
	return straddress;
}

// /***获取图片资源的静态资源地址**/
function GetPicStaticSrc(src) {
	return 'app_data/' + src;
}

// 取文件后缀名
function GetFileExt(filepath) {
	if (filepath != '') {
		var pos = '.' + filepath.replace(/.+\./, '');
		return pos;
	}
}

// 取文件名不带后缀
function GetFileNameNoExt(filepath) {
	if (filepath != '') {
		var names = filepath.split('\\');
		var pos = names[names.length - 1].lastIndexOf('.');
		return names[names.length - 1].substring(0, pos);
	}
}
mui.plusReady(function() {
	const _self = plus.webview.currentWebview();
	_self.addEventListener('swipeleft', function() {
		mui.back()
	}, false);
});

7.实现时间组件

表单中常常会用到时间组件,在开发过程中,在这里遇到一个小坑,mui的mui.back于时间组件冲突了,在我开发的过程中,发现只要我将时间组件在页面加载的过程中就初始化,mui顶部自带的返回按钮就会不起作用,这块确实坑了我一下,以下是解决方案:
html:

					<div class="mui-input-row">
						<label>开始时间<span class="violation-form-text"> *</span>:</label>
						<input type="text" class="mui-input-clear mui-input"
						 v-model="data.StartTime" v-on:tap="getStartTime()" id="shipIslandingStartTime"
						 data-options='{"type":"datetime"}' />
					</div>

js:

var vm = new Vue({
	el: '#content',
	data: {
		data: {
			StartTime: ''
		},
	},
	created() {
	},
	methods: {
		getStartTime () {
			const _this = this;
			let dtPicker = new mui.DtPicker();
			const dateElement = document.getElementsByClassName('mui-dtpicker')
			if (dateElement[0].className === 'mui-dtpicker mui-active') {
				return false;
			} else {
				dtPicker.show(function(selectItems) {
					return _this.data.StartTime = selectItems.text;
				})
			}
		},
	}
});
mui.init();
8.实现选择器

在web中我们一般使用下拉框来实现的功能,在app中会使用选择器来实现,这个项目值有一级的选择,所以这里也只记录最简单的一级选择器,这个功能挺简单的,仔细看下示例就没啥问题了,代码实现
html:

					<div class="mui-input-row">
						<label>申请部门<span class="violation-form-text"> *</span>:</label>
						<input type="text" 
						class="mui-input-clear mui-input" 
						v-model="data.ApplicationDept" 
						placeholder="请选择申请部门"
						readonly="readonly"
						v-on:tap="getDeptInfo()"
						/>
						<div class="ui-alert" v-model="deptTextValue"></div>
					</div>

js:

var vm = new Vue({
	el: '#content',
	data: {
		getDeptListUrl: getApiUrl('Base_TreeItems'),
		data: {
			ApplicationDept: '',
		},
		
		selectDept: '',
		deptList: []
	},
	created() {
		this.getStaffDeptList();
	},
	methods: {
		getStaffDeptList() {
			gets(`${this.getDeptListUrl}?$filter=startswith(InCode, 'O')`, null, (res) => {
				res.Results.forEach((item) => {
					this.deptList.push({
						value: item.CNName, // 这里的键value和text是确定的,text是显示的值,value可以写成对应的需要传到后台的值
						text: item.CNName
					});
				})
			}, (error) => {
				console.log(error);
			});
		},
	getDeptInfo() {
			const _this = this;
			const userPicker = new mui.PopPicker();
			userPicker.setData(this.deptList);
			userPicker.show(function(items) {
				_this.ApplicationDept= JSON.stringify(items[0]);
				_this.data.ApplicationDept = items[0].value;
			});
		},
});
mui.init();
9.唤醒默认浏览器打开html网页

html:

<button type="button" class="mui-btn mui-btn-blue mui-btn-link" v-on:tap="detail(item.ID)">详情</button>

js:

var vm = new Vue({
	el: '#content',
	data: {
		httpUrl: 'http:/xxxx.xxxx.com?id',
	},
	created() {
	},
	methods: {
		detail(id) {
		// 点击打开该网页
			plus.runtime.openURL(`${this.httpUrl}=${id}`);
		}
	}
})
mui.init();
  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值