最近时常感叹道:时间老是那么的快,转瞬即逝。对于像我这种刚入门的小生来说,技术天天都在更新,框架也层出不穷,有时候还没弄懂这个知识大牛们又推出了更好的技术。固然学习好的技术也是十分重要的。可是在学习以后怎样才可以获得本身想要的呢,一个好的建议即是静下心来写点本身的东西,哪怕你完成不了也应该尽力去写,老大曾讲过要去实践要去独立思考,你才能掌握不少你看似懂了却又很难处理的知识点。学习小程序的我已通过去了半个月了,前不久滴滴事件颇为轰动,因而便萌发了这篇文章,打开滴滴的小程序。界面作了很大的变化,对于比较怀旧的我来讲,仍是挺喜欢之前的界面,因而决定打算本身手写一个怀旧版滴滴小程序,接下来我会列举我所遇到的坑和如何解决的方法,但愿可以帮到一样在奋斗的你...css
工欲善其事必先利其器,对于一个前端来讲有一个好的工具可以让咱们事半功倍。要想作好一个小程序咱们首先也应该先选择咱们的兵器。html
数据接口前端
说了一大堆,等于没说,仍是回到正题,先来一波效果图。
这里有更多的图片等你vue
接下来我会对滴滴微信小程序主要功能,以及对应的数据接口和采用的组件/API技术,描述的详细。让咱们离小程序更近一点,传递知识,分享收获git
功能描述:顶部导航的制做,点击相应的nav页面呈现不一样的内容,而且点击时能判断是向前仍是向后自动滑出下一个nav,实现动画过分效果。输入起始位置模拟等待的时间。
实现原理:程序员
<template name="sprinner"> <block wx:if="{{isLoading}}"> <view class="spinner"> <view class="bounce1"></view> <view class="bounce2"></view> <view class="bounce3"></view> </view> </block> </template>
在须要用到加载效果的地方就能够直接使用,es6
<import src="/templates/sprinner.wxml" /> <template is="sprinner" data='{{isLoading}}'> </template> //经过去设置isLoading的布尔值来判断是否须要显示
<scroll-view scroll-x="true" class="nav" scroll-left="{{navScrollLeft}}" scroll-with-animation="{{true}}"> <block wx:for="{{navData}}" wx:for-index="id" wx:for-item="navItem" wx:key="index"> <view class="nav-item {{currentTab == id ?'active':''}}" data-name="{{navItem.name}}" data-current="{{id}}" bindtap="switchNav">{{navItem.name}}</view> </block> </scroll-view>
怎样去改变这个navScrollLeft的值呢?一开始想的是去设置一下nav的导航的left,而后超出则隐藏。坑啊,根本就实现不了。没法判断左滑出仍是又滑出,后来又想到设置一个阈值。累真的难写。好像放弃啊,仍是坚持下吧,因而想到分开来取写他们的jsgithub
switchNav(e){ var cur = e.currentTarget.dataset.current; var singleNavWidth = this.data.windowWindth/4; //获取屏幕宽度存放放四个nav, this.setData({ navScrollLeft: (cur - 1) * singleNavWidth, //点击去减小每个nav的值 currentTab: cur, }) switchTab(e){ var cur = event.detail.current; var singleNavWidth =55; //设置每个nav的宽度 this.setData({ currentTab: cur, navScrollLeft: (cur - 1) * singleNavWidth //一样动态的去改变这个值 }); },
第一次打理这种顶部导航效果的小程序,而却还带一点特效的。之后的你若是碰到了就能够回来借鉴借鉴,避免跟我同样,在这里浪费大量的时间和精力了。咱们但是要完成有效时间建立更大价值的程序猿呀...编程
为了作这个效果,反反复复的看了n遍文档,真的是比较坑爹。微信小程序api对于地图这方面讲的确实不怎么详细,多是我这种对地图处理天生迷茫的人。这里将详细的把我遇到的问题一一列举出来,但愿也可以帮助到从此的你去处理地图这种东西少踩点坑吧。
这里使用到了关键词搜索,逆地址解析,地址解析,切换城市列表,建议之后作这个能够了解下腾讯地图api,仍是比较方便的canvas
var QQMapWX = require('../../libs/qqmap-wx-jssdk.js');//导入须要使用的包,建立一个libs文件夹 var qqmapsdk; qqmapsdk = new QQMapWX({ key:'DHNBZ-2ZLKK-T7IJJ-AXSQW-WX5L6-A6xxxx'//申请本身的开发者密钥 }); qqmapsdk.reverseGeocoder({ //逆地址解析api,能够根据你的经纬度去解析位置地址 location: { latitude: latitude, longitude: longitude, }, success: function (res) { conslog.log(res) }
第一个坑:如何去获取经纬度呢,移动markes?,天呐这要写多少,对于大牛们来讲可能分分分钟,对于刚入门的小生来讲难度仍是挺大大。沉思良久,忽然发现 this.mapCtx.getCenterLocation,移动地图事件获取地图中心的经纬度。那么咱们能够去固定一个 controls在地图中心,去移动地图来解析他的坐标位置,将数据绑定在下面显示出来,因而就实现了。emmm代码以下
bindregionchange: function(e){ //移动地图事件 var that = this this.mapCtx.getCenterLocation({ //getCenterLocation能够获取地图中点的经纬度 success: function (res) { app.globalData.strLatitude=res.latitude //存放到全局去,供后面计算价格使用 app.globalData.strLongitude= res.longitude qqmapsdk.reverseGeocoder({ location: { latitude: res.latitude, //经过移动地图能够获得相应中心点的经纬度 longitude: res.longitude, }, success: function (res) { that.setData({ address: res.result.address, //获得的经纬度逆地址解析获得咱们的位置信息 bluraddress: res.result.formatted_addresses.recommend }) }, });
第二个坑: 目的地调用api同样能够实现搜索提示功能,但我须要历史记录也存在,而且点击某一项我须要跳转到首页显示出来,没有历史的页面体验感极差。是否?这里我是这样实现的
qqmapsdk.getSuggestion({ //调用api实现关键词搜索提示 keyword: value, //传递input的值,这里要传value不是'value',刚开始犯困。提示一下 region: '南昌', success: function(res){ let data = res.data that.setData({ address: data, value })
<view wx:if="{{!value==''}}" class="destination" wx:for="{{address}}" data-destination="{{item.title}}" data-end="{{item.address}}" bindtap="toIndex" wx:key="{{item.id}}"> <view wx:if="{{value==''}}" class="destination" wx:for="{{ entity}}" data-destination="{{item.title}}" data-end="{{item.address}}" bindtap="toIndex" wx:key="{{item.id}}">
经过wx:if去判断输入框。下面for不一样的数组,填了第一小坑坑。接下来就会去思考,当咱们点击搜索的怎么把它加入到咱们的历史中呢?点击获取那个值的id而后push到历史数组中去,是否是很nice,实现了滴滴起始位置的选择,固然咱们这这是冰山一角,强大的背后还须要去探索。
古人云:细节决定成败,一个良好的微信小程序每每就是一些细节打动人心,竟然是模仿,虽作不到百分百,至少仍是很但愿如出一辙。
分析分析,首页点击呼叫快车页面不跳转,但要显示不一样的内容。是否是也能够跟上面同样用wx:if来处理呢?没错用一个repeat去承载要显示的内容,这样就能够不在刷星这个小技巧get到了吗。
<repeat wx:if="{{callCart}}"> <repeat wx:else>
计算价钱同样用到了腾讯地图api获取两点之间的距离,刚才把起始点都存放在globalData里,这样的好处是,能够随时获得里面的数据
let {endLatitude,endLongitude} = app.globalData //使用ES6的语法去结构数据 qqmapsdk.calculateDistance({ mode: 'driving', to:[ { latitude: endLatitude, longitude:endLongitude }], success: (res)=> { var num1 = 8+1.9*(res.result.elements[0].distance/1000) var play1 = num1.toFixed(1) //取一位小数点 app.globalData.play= play1 //一样存放在全局里,后面订单结束支付要用上 this.setData({ play1:play1, }) },
对于点击显示的转态这里就不详细描述,本文只针对一些不容易处理的问题。后面司机服务页面路线规划也是经过调用api,计算两点的经纬度去标点,连线。这里也就省略下,详细的能够参考个人代码。
怎样去作这个页面呢,或于你之后也须要计时器(不是倒计时)或者进度条,能够参考这里。
圆形进度条有不少实现的方法,但我以为canvas仍是挺方便的。两个canvas搞定
<canvas class="progress_bg" canvas-id="canvasProgressbg"> </canvas> //画底色 <canvas class="progress_canvas" canvas-id="canvasProgress"> </canvas> //画进度条,传递一个step参数,用定时器去绘制
第三坑:绘制canvas没有问题,文档也给的十分的详细,可是里面那个计时器怎么制做呢?我只须要分秒,而却又不是倒计时,而且还要跟外面保持一致。前端这么心酸的吗?啊,硬着头皮去写吧。搜索了下资源发现网上这方面的资料真的少。没有办法,bug仍是要解决的。你是否也遇到过这样的问题,或于之后呢!记得回来找我...
parseTime: function(time){ // 这里参考了每一个小程序项目中自带的utils下的util.js,大牛写的就是简洁明了 var time = time.toString(); return time[1]?time:'0'+time; //自动归零补零 }, countInterval: function () { var curr = 0; this.setData({ time: this.parseTime(timer.getMinutes())+":"+this.parseTime(timer.getSeconds()), //格式化下时间,取分秒 }); timer.setMinutes(curr/60); //秒针60了自动加1 timer.setSeconds(curr%60); //60后归零 curr++; }
对于同步,那确定很简单呀,放在一个定时器里就够了。点这里查看源码
有打车就应该有取消对吧,一看取消行程页面就有点端倪。这些样式须要本身去写吗?要学会说no,这里就以这个为例子,讲下我在小程序开始中如何使用weui快速去搭建一个页面效果。
这里给一些我以为还行的资料:在小程序中能够直接使用的例子 weui小程序官方文档,
要注明的一点,引用weui要在相应的文件夹里或全局的wxss引用它的css,可能多个页面都须要用到,这里在全局引用
@import 'styles/weui.wxss';
在app.wxss中引用这段代码就能够开始你的weui之旅了,比较啰嗦的贴了这么长的一段代码。暗示你要用weui去快速开发你的小程序了!
<view class="weui-cells weui-cells_after-title"> //使用weui能够直接复制套上去用就行了 <checkbox-group bindchange="bindReasonChange"> <label class="weui-cell weui-check__label" wx:for="{{reasons}}" wx:key="value"> <checkbox class="weui-check" value="{{item.value}}"checked="{{item.checked}}"/> <view class="weui-cell__bd name" >{{item.name}}</view> <view wx:if="{{item.checked}}" class="checked "> //点击是显示红色的√ <image src="../../assets/images/checked.png"></image> </view> <view wx:if="{{!item.checked}}" class="checked "> //不点击是显示空圆 <image src="../../assets/images/nochecked.png"></image> </view> </label> </checkbox-group> <view class="weui-cell weui-cell_link {{show==true?hidden:''}}"> <view class="weui-cell__bd moreReasons" style="display: {{show==true?'none':''}};"bindtap='moreReasons'> <text>点击查看更多缘由</text> </view> </view> </view>
采坑经历:点击转态如何解决呢?一开始我是这样想的,用一个icon经过改变它的checked事件去呈现不一样的转态。这样是能够实现的,可是只能点击一个,不能多选。痛苦啊!!
一上午展转反侧,较劲脑汁。反复的去看文档,终于豁然开朗起来,能够用多重循环去判断checked。哎,js仍是超级重要啊。话很少说
bindReasonChange(e){ let reasons = this.data.reasons; let strVal = e.detail.value; for(var i = 0, lenI = reasons.length; i < lenI; ++i){ reasons[i].checked = false; for(var j = 0, lenJ = strVal.length; j < lenJ; ++j){ if(reasons[i].value==strVal[j]){ reasons[i].checked =true; break; } } }
之后咱们的页面或多或少可能须要点击选择功能,其实原理都差很少,这点你获得了吗,之后再作这方面的功能时就能用上了。总感受还有什么没写完同样:好吧!!
在作点击加载更多的,我是这样打理的。wx:for一个数组而后去截取他的下边显示。点击加载更多时所有for这个数组。而后在用定时器设置wx.showLoading()显示加载更多效果,就有了那种既视感
享受了一下滴滴带来的快捷与方便,感叹技术的改变生活啊。一样评分也是app获得用户最终反馈的直接来源,所以咱们也不容错过这么重要的一点,可是打理的细节也是十分的坑啊。
如何去写一个评分呢,点击小星星去改变它的转态,还要根据第几颗星来判断前面的也要点亮。真的挺头痛的,网上不乏小程序评分功能实现,但大多数都写的不是复杂就是很深奥,对于一个小生来说,简直就是天书呀。就跟老大说的同样,不少东西都是靠细节去成长的,想一想以为很容易实现,不就一个status改变一下图片吗?可是打理起来真的见功夫。费尽心思去寻找一种简单粗暴的又能够达到这种效果的方式。
<view class="evaluation-stars" bindtap="myStarChoose"> <block wx:for="{{starMap}}"wx:key="{{index}}"> <text wx:if="{{star>=index+1}}" class="stars-solid" data-star="{{index+1}}">★</text> <text wx:if="{{star<index+1}}" class="stars-empty" data-star="{{index+1}}">☆</text> </block> </view> <text class="zan-c-gray-dark">{{starMap[star-1]}}</text>
不用图片,用字体去解决这个问题就方便多了,只要改变颜色就达到了评分效果。并且代码量很是的少,不知道这样会不会被打死。
myStarChoose(e) { let star = parseInt(e.target.dataset.star) || 0; this.setData({ star //名字同样能够省略 }); },
把这个放在最后来说,确定是特别重要的知识点,对于开发的你来讲这个比上面功能的描述更有帮助,或于你已经知道而且处理的更好,这里只为了帮助那些跟我同样入门不久的小生尽可能少走点歪路吧。
一、 数据请求的封装是搭建一个良好程序的前提。在小程序中咱们无时无刻不须要去请求数据。处处充斥作异步请求,让咱们处理起来很头疼。这一点更须要发时间去打理的,随著es6慢慢的普及咱们也应该把这些好的东西用到咱们的代码中promise,把异步编程同步。推荐廖雪峰老师的文章,把个人封装的贴出来,你们之后能够直接拷过去使用了
let util = { request(opt){ // 生成对象 结构 let options = Object.assign({},,opt); //es6的赋值 let {url,data,} = options //es6的结构从options结构出咱们须要的url,data return new Promise((resolve,reject)=>{ wx.request({ url, data, success(res){ resolve(res.data) }, fail(err){ reject(err) } }) }) } } export default util //向外输出模板,在外面能够直接使用util.request({})去网上请求咱们的数据的数据了。
二、还有一些就是包的管理,好比把咱们页面中可能同样的东西抽出来建立一个template文件夹,把一些同样的wxss也能够抽出来新建一个styles,在须要使用到的地方就@import就能够了,好比滴滴的按钮吧,其实都同样,还有页面底部的横条均可以封装起来,用的时候直接导入就好了。
功能可能没有一一列举出来,因为时间有限,只讲述了一些咱们平常能使用到的功能。想了解更多功能能够点击这里查看我github,本小程序我也会不断更新,喜欢的话能够加入我。一样也但愿你可以留下您宝贵的意见和建议。
做为一个程序猿挺不容易的,作一个前端程序猿更加不容易。技术突飞猛进。天天要去摄取更多的技术来源,心有千言,难于罄书。但咱们都是热于分享的人,可以把本身遇到的问题以及如何解决的方式写出来,老是但愿这样能够帮助到更多一样遇到这类问题的你,我,他。或于这就是社区的力量,这就是优秀程序员的品质吧。小程序的学习依旧要铆足劲的去学习,后面还有wepy,Mpvue等新技术在等着咱们,我已经踏上了那片领地的征程,往后也会发布遇到的问题、bug和个人做品。但愿对你有所帮助,咱们的口号是热于分享,热于创做。Let's start a new journey!!!