学习之路--微信公众号开发(二)--前端开发遇到的问题
(逻辑和表达能力不强,或许只有我自己才能看懂吧?/捂脸)
大写的壹——技术知识点学习
一、http://jqweui.com/extends#infinite ——JQuery WEUI
在这里也不详细说了,功能很多,如果写的话能写好几章……下面列出一些主要功能:
表单,文件上传,加载提示,搜索栏,加载更多,下拉刷新,滚动加载,图片浏览器,日历日期时间控件,地址控件,通知控件,下拉框控件,弹出框
二、http://lbs.qq.com/javascript_v2/index.html ——腾讯地图导航接口文档
三、http://lbsyun.baidu.com/index.php?title=jspopular/guide/routeplan ——百度地图导航接口文档,实现距离计算。示例:http://lbsyun.baidu.com/jsdemo.htm#i5_5
四、文件上传ajaxfileupload.js
大写的贰——遇到的问题及解决方法
一、轮播图问题
1、轮播图的图片由后台传过来的数据加载;
2、轮播图在电脑上的微信web开发者工具没法调试,需要使用真机调试;
3、应该是先通过模板或别的途径加载好轮播图内部的节点,才进行初始化。
1 // 初始化轮播图 2 function newSwiper() { 3 var mySwiper = new Swiper('.swiper-container', { 4 direction: 'horizontal', 5 loop: true, 6 // 如果需要分页器 7 pagination: '.swiper-pagination' 8 }) 9 } 10 11 // 加载轮播图数据 12 function addSwiper() { 13 var url = "/home-ajax/swiper"; 14 $.post(url, function(data) { 15 console.log(data); 16 var h = template("swiper-tpl", data); 17 $('#swiper-body').html(h); 18 newSwiper(); 19 }, "json"); 20 }
二、滚动加载问题
1、滚动加载在电脑上的微信web开发者工具没法调试,需要使用真机调试;
2、项目采用了WEUI的滚动加载功能,没有注意原项目在common.js层已经另行写有了一个不采用WEUI的滚动加载的方法。
3、内容的加载不能使用.html(),而应该使用.append();
4、滚动加载相当于后台项目中的分页功能,需要分步去请求数据,需要有分页的索引;
5、最后一页的下一页的滚动加载不需要请求后台,直接变换为无更多内容。
6、滚动加载事件的触发在加载期间是持续触发的,要做判断并提前提出事件。
7、触发滚动事件的滚动高度写高点,数据加载的量(每页多少条数据)也写大点,尽量不要让用户看到类似正在加载的文字,这样体验友好一点。
1 var listParam = { 2 "menuId": "1001", 3 "pageIndex": 0, 4 "totalPages": 0, 5 "newsSort": "new" 6 }; 7 // 初始加载第一页 8 addList(listParam); 9 // 滚动加载 10 var loading = false; //状态标记为不加载 11 $(document.body).infinite(50).on("infinite", function() { 12 if (loading) return; // 如果正在加载,则退出事件 13 // 如果没有下一页了,加载图标消失和无更多内容显示 14 if (listParam.pageIndex >= listParam.totalPages) { 15 setTimeout(function() { 16 $(".loadmore .weui-loadmore").hide(); 17 $(".loadmore .no-more-data").show(); 18 $(document.body).destroyInfinite(); 19 return; 20 }, 1000); 21 } 22 loading = true; 23 setTimeout(function() { 24 addList(listParam); 25 loading = false; 26 }, 1000); 27 }); 28 // 加载列表数据 29 function addList(listParam) { 30 var url = "/home-ajax/newsList"; 31 $.post(url, listParam, function(data) { 32 var h = template("list-tpl", data); 33 $('#list-body').append(h); 34 listParam.totalPages = data.totalPages; 35 listParam.pageIndex++; 36 }, "json"); 37 }
三、图片加载问题
1、除去前端页面的logo等死图片之外,大部分图片的加载来自后台;
2、公司使用的template.js,写法是这样:<img src="/gridfs-download?f_id={{v.imgId}}">,完整的是这样:<img src="${contextPath}/gridfs-download?f_id={{v.imgId}}">
3、但是这样写不对,因为链接到的应该是后台项目的方法,后台的前端页面可以这样写,毕竟在同一个项目,而微信项目是另一个项目,其本身的${contextPath}是微信本身的路径。
4、还有一个地方就是详情加载的时候,详情的内容是可以有图片视频之类的,在后台的新增页里,详情的正文内容是一个编辑器(UEditor),图片链接有可能是这样的:
也有可能是这样的:
5、微信加载内容的代码是这样的:
1 <script type="text/html" id="detail-tpl"> 2 <div class="title"> 3 <p>{{results.title}}</p> 4 </div> 5 <div class="time"> 6 {{results.lastUpdate | dateFormat:'yyyy-MM-dd'}} 7 </div> 8 <div class="content"> 9 {{#results.content}} 10 </div> 11 </script> 12 13 // 去掉文本标签 14 // {{#jobinfo.info | removeTag}} 15 template.helper('removeTag', function(data) { 16 return data.replace(/<[^>]+>/g, ""); 17 });
6、综上所述,我们要解决问题的关键是改掉图片的链接:
1 // 首先在最顶部的位置(声明contextPath的位置)声明一个后台系统的绝对路径 2 <% 3 String serverUrl=Constants.MEN_HU; 4 request.setAttribute("serverUrl",serverUrl); 5 %> 6 <script> 7 var serverUrl = '${serverUrl}'; 8 </script> 9 // 前端页面img链接改写成: 10 <img src="${serverUrl}/gridfs-download?f_id={{v.imgId}}"> 11 12 13 // 详情的链接没法直接改写,我们可以在填充模板之后,再通过js遍历所有的图片,再改写 14 $.post(url, listParam, function(data) { 15 var h = template("detail-tpl", { "results": data }); 16 $('#detail-body').html(h); 17 updateImgSrc('detail-body'); 18 }, 'json'); 19 20 /** 21 * 修改详情内容中的图片链接路径,(contextPath) 22 * @param {*要填充模板的body的id} templateBodyId 23 * 24 */ 25 function updateImgSrc(templateBodyId) { 26 $("#" + templateBodyId).find("img").each(function(i) { 27 var src = $("#" + templateBodyId).find("img").eq(i).attr("src"); 28 if ("/gridfs-download?f_id=" == src.substring(0, 22)) { 29 src = serverUrl + src; 30 } 31 $("#" + templateBodyId).find("img").eq(i).attr("src", src); 32 }); 33 }
四、文件上传问题
1、整个项目就一个地方用到了文件上传,因为整个包括后台项目都是我来干,所以我很清楚微信项目并没有连接数据库,而且文件上传后支撑它的后台项目要能看到。
2、解决方法:首先在微信项目中引入数据库,文件上传的数据库和后台项目中文件上传的数据库(MongoDb)要一致。
3、引入mongo的maven包(改pom.xml),引入gridFSKit.java文件(从后台项目中拷过来,这个文件我是看不懂),新建一个GridfsController.java;
4、在新建的文件里面写upload方法,然后把url给前端,前端就可以调用了。
5、前端采用的是ajaxfileupload.js插件实现文件的上传。
1 var data = { 2 fileId: 'btnUpLoad', 3 successCall: function(data, status) { 4 if (data) { 5 $('input[name="entity.imgName"]').val(data.filename); 6 $('input[name="entity.imgId"]').val(data.f_id); 7 } 8 } 9 } 10 uploadFile(data); 11 12 // 上传文件(点击上传文件控件就上传) 13 function uploadFile(options) { 14 options = options || {}; 15 options.url = options.url || "/gridfs/upload"; 16 options.fileId = options.fileId || "btnUpLoad"; 17 $(document).on('change', '#' + options.fileId, function(e) { 18 _doUpload(options); 19 }); 20 } 21 22 function _doUpload(options) { 23 $.ajaxFileUpload({ 24 url: options.url, //用于文件上传的服务器端请求地址 25 secureuri: false, //是否需要安全协议,一般设置为false 26 fileElementId: options.fileId, //文件上传域的ID 27 dataType: 'json', //返回值类型 一般设置为json 28 success: function(data, status) { //服务器成功响应处理函数 29 if (!data.success) { 30 return; 31 } 32 $.toptip("上传成功", 'success'); 33 if (options.successCall && typeof options.successCall == 'function') { 34 options.successCall.call($(options.fileId), data, status);; //data.info --> fileId 35 } 36 }, 37 error: function(data, status, e) { //服务器响应失败处理函数 38 $.toptip(e + "", 'error'); 39 } 40 }); 41 }
五、微信呼叫功能
1、就是调用手机的打电话功能,看上去很高大上,但实现上微信这个软件已经帮我们实现了,我们需要做的只有一步:
2、给呼叫按钮用a标签表示,href这样写:<a href="tel:{{v.phone}}">呼叫</a>
3、只要点击这个呼叫,就会有一个弹窗,当然,不一样的手机效果可能不一样。弹窗之后的操作微信都实现了。效果图如下:
六、地图导航功能问题
1、微信开发要用地图首先想到的就是腾讯地图,于是我就去学习了腾讯地图的API,当我做出来后,发现我并不能实现距离的计算。
2、弯路:我在腾讯地图的JavaScript API 中没有找到计算距离的方法,然后去学习了微信小程序JavaScript SDK,最后发现SDK并不适用于公众号。
3、弯路:因为此微信项目是有一个原版公众号的,这次开发是相当于重做,于是我去看了原项目的实现方法,被它带进去了。
4、弯路:在网上百度了如何实现距离的计算,以及看了一些案例,发现都是用的百度地图,于是学习百度地图JavaScript API。
5、虽然最后写出来了,但是很怪异,有点个功能点,一个是在详情页显示距离(百度地图实现),一个是点击详情页的导航按钮进入地图导航(腾讯地图实现)。
6、最后回来发现腾讯地图也可以实现距离的计算,方法在WebService API中。可惜我已经完成功能了,没必要再否定百度地图再来一次。
1 // 导航按钮功能的实现(腾讯地图),只需要一个链接,这就是腾讯地图的特点。 2 // routeplan为路线规划方法,eword为地点名称,epointx为经度,epointy为纬度,referer为我的应用名称,key为申请的密钥,起点不填默认为我的位置(手机定位当前位置) 3 <a id="map-nav" class="map-nav" href="http://apis.map.qq.com/tools/routeplan/eword={{name}}&epointx={{longitude}}&epointy={{latitude}}?referer=myapp&key=XXX">导航</a> 4 5 // 下面是百度地图 6 // 引入js 7 <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=xxx"></script> 8 // 放置百度地图的容器,(页面只要距离,不要地图,所以样式设置为隐身) 9 <div class="baidu-map" id="mymap"></div> 10 11 /** 百度地图API功能 start**/ 12 var map = new BMap.Map("mymap"); 13 map.centerAndZoom(new BMap.Point(116.404, 39.915), 12); 14 var searchComplete = function(results) { 15 if (transit.getStatus() != BMAP_STATUS_SUCCESS) { 16 return; 17 } 18 var plan = results.getPlan(0); 19 $("#distance").text(plan.getDistance(true)); 20 } 21 var transit = new BMap.DrivingRoute(map, { 22 renderOptions: { map: map }, 23 onSearchComplete: searchComplete, 24 onPolylinesSet: function() { 25 26 } 27 }); 28 var geolocation = new BMap.Geolocation(); 29 30 /** 百度地图API功能 end**/ 31 32 // 因为距离也是数据填充上去的,百度地图是异步的,所以百度地图的请求要放在数据填充之后 33 $.post(url, listParam, function(data) { 34 data.distance = "正在加载…"; 35 longitude = data.longitude; 36 latitude = data.latitude; 37 var h = template("list-tpl", data); 38 $("#list-body").html(h); 39 geolocation.getCurrentPosition(function(r) { 40 if (this.getStatus() == BMAP_STATUS_SUCCESS) { 41 var mk = new BMap.Marker(r.point); 42 map.addOverlay(mk); 43 map.panTo(r.point); 44 var p1 = new BMap.Point(r.point.lng, r.point.lat); 45 var p2 = new BMap.Point(longitude, latitude); 46 transit.search(p1, p2); 47 } else { 48 alert('failed' + this.getStatus()); 49 } 50 }, { enableHighAccuracy: true }); 51 }, "json");