小程序使用记录
结构:
关系:wxml=>文档,wxss=>样式,js=>逻辑交互(负责数据处理并给视图层),json=>配置(,如顶部栏颜色,一般只要配置app.json就好了,个别页面不一样也可以单独配置。)
数据绑定例子:
index.wxml: <view>{{ msg }}</view> <button bindtap="clickMe">点击我</button> index.js: Page({ clickMe: function() { this.setData({ msg: "Hello World" }) //设置数据{{msg}}为Hello World } })
小程序的启动:
1、打开小程序,下载小程序包
2、app.json中的pages字段获得所有的界面。
3、app.js的回调函数onLaunch执行。
app.json所有的配置展示: =>pages:定义了小程序的所有界面。window:设置窗口的顶部栏标题颜色、背景颜色、字体等等。tarBar是底部栏的配置。
{ "pages": [ "pages/index/index", "pages/logs/index" ], "window": { "navigationBarTitleText": "Demo" }, "tabBar": { "list": [{ "pagePath": "pages/index/index", "text": "首页" }, { "pagePath": "pages/logs/logs", "text": "日志" }] }, "networkTimeout": { "request": 10000, "downloadFile": 10000 }, "debug": true }
—————— 组件(小程序的标签、封装好的功能模块) ——————
如地图:
<map longitude="广州经度" latitude="广州纬度"></map>
组件七大类:视图容器、基础内容、表单、导航、多媒体、地图、画布。(见https://developers.weixin.qq.com/miniprogram/dev/component/)。
—————— API(用户信息、微信支付等)(见https://developers.weixin.qq.com/miniprogram/dev/api/) ——————
例子:获取地理位置:
wx.getLocation({ type: 'wgs84', success: (res) => { var latitude = res.latitude // 经度 var longitude = res.longitude // 纬度 } })
例子:扫一扫
wx.scanCode({ success: (res) => { console.log(res) } })
—————— 框架 ——————
App({ }) 只能在app.js中:
//app.js App({ onLaunch: function () { // 展示本地存储能力 var logs = wx.getStorageSync('logs') || [] logs.unshift(Date.now()) wx.setStorageSync('logs', logs);// 设置全局数据 globalData: { userInfo: null, serverUrl:"https://windyet.com/" } })
——在app.js中取全局数据:
this.globalData.serverUrl
——在其他界面取全局数据:
getApp().globalData.serverUrl
页面文件:js->page可以设置【data /onLoad / onShow / onPullDownRefresh / onShareAppMessage /
onPageScroll】以及很多自定义函数
——data是初始化的数据,会传给视图层
数据改变的示例代码:
<!--index.wxml--> <view>{{text}}</view> <button bindtap="changeText"> Change normal data </button> <view>{{num}}</view> <button bindtap="changeNum"> Change normal num </button> <view>{{array[0].text}}</view> <button bindtap="changeItemInArray"> Change Array data </button> <view>{{object.text}}</view> <button bindtap="changeItemInObject"> Change Object data </button> <view>{{newField.text}}</view> <button bindtap="addNewField"> Add new data </button>
//index.js Page({ data: { text: 'init data', num: 0, array: [{text: 'init data'}], object: { text: 'init data' } }, changeText: function() { // this.data.text = 'changed data' // bad, it can not work(不要采用JQ的写法) this.setData({ text: 'changed data' }) }, changeNum: function() { this.data.num = 1 this.setData({ num: this.data.num }) }, changeItemInArray: function() { // you can use this way to modify a danamic data path this.setData({ 'array[0].text':'changed data' }) }, changeItemInObject: function(){ this.setData({ 'object.text': 'changed data' }); }, addNewField: function() { this.setData({ 'newField.text': 'new data' }) } })
//跳转新界面(有返回按钮,原界面未出栈): ==> wx.navigateTo
<navigator url="/pages/logs/logs?title=navigate" hover-class="navigator-hover">跳转到新页面</navigator>
//打开新界面(无返回按钮,原界面出栈) ==>> wx.redirectTo
<navigator url="/pages/logs/logs?title=navigate" hover-class="navigator-hover" open-type="redirect">在当前页打开</navigator>
//重启动:调用 API wx.reLaunch 或使用组件 <navigator open-type="reLaunch"/>
getApp()可以获取全局的应用实例。非全局文件(除app.js)的变量只对该文件有效,相互不影响。
——————视图层(条件渲染等等,请查看文档。)——————
数据绑定(更多请查看文档):
<view> {{ message }} </view> <view id="item-{{id}}"> </view>
列表渲染:
<view wx:for="{{array}}"> {{index}}: {{item.message}} </view>
//wx:for是循环,wx:for-index是key,wx:for-item是value。以下为99乘法表 <view wx:for="{{[1, 2, 3, 4, 5, 6, 7, 8, 9]}}" wx:for-item="i"> <view wx:for="{{[1, 2, 3, 4, 5, 6, 7, 8, 9]}}" wx:for-item="j"> <view wx:if="{{i <= j}}"> {{i}} * {{j}} = {{i * j}} </view> </view> </view>
————更多渲染请看文档哦。
事件(可以携带id, dataset, touches等):
简单例子:点击则控制台输出事件
//view层 <view id="tapTest" data-hi="WeChat" bindtap="tapName"> Click me! </view> //js层 Page({ tapName: function(event) { console.log(event) } })
分类:冒泡和非冒泡事件。 去呗==>>冒泡:触发时会向父级传递 / 非冒泡:触发时不会向父级传递。
小程序规定:屏幕宽度为750rpx
选择器:.class / #id / element /element, element / :before / :after。定义在app.wxss中的为全局样式,定义在页面中的为局部样式。
实例:获取微信用户信息:
//app.js App({ onLaunch: function () { // 展示本地存储能力 var logs = wx.getStorageSync('logs') || [] logs.unshift(Date.now()) wx.setStorageSync('logs', logs); var self = this; // 登录 wx.login({ success:function(res){ // 发送 res.code 到后台换取 openId, sessionKey, unionId if (res.code) { // console.log(res.code); } else { console.log('登录失败!' + res.errMsg) } } }) // 获取用户信息 wx.getSetting({ //<<==检测是否授权 success: function (res) { //<<==如果已经授权 if (res.authSetting['scope.userInfo']) { //<<==如果有userInfo // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框 //<<==获取微信微信消息 wx.getUserInfo({ success: res => { // 可以将 res 发送给后台解码出 unionId self.globalData.userInfo = res.userInfo; console.log(self.globalData); // console.log(res.userInfo); // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回 // 所以此处加入 callback 以防止这种情况 if (this.userInfoReadyCallback) { this.userInfoReadyCallback(res) } } }) } } }) }, // 全局数据 globalData: { userInfo: null, serverUrl: "https://windyet.com/" } })
————需要说明,为什么这里需要 var self = this,因为回调的时候,不能直接使用this
index.js代码:
//index.js //获取应用实例,在这里获取是因为下面会用到多次。 const app = getApp(); Page({ data: { motto: 'Hello World', userInfo: {}, hasUserInfo: false, canIUse: wx.canIUse('button.open-type.getUserInfo') },
//事件处理函数 bindViewTap: function() { wx.navigateTo({ url: '/pages/logs/logs' }) }, // 页面加载完成,检测是否有userInfo onLoad: function () { if (app.globalData.userInfo) { this.setData({ userInfo: app.globalData.userInfo, hasUserInfo: true }) } else if (this.data.canIUse){ // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回 // 所以此处加入 callback 以防止这种情况 app.userInfoReadyCallback = res => { this.setData({ userInfo: res.userInfo, hasUserInfo: true }) } } else { // 在没有 open-type=getUserInfo 版本的兼容处理 wx.getUserInfo({ success: res => { app.globalData.userInfo = res.userInfo this.setData({ userInfo: res.userInfo, hasUserInfo: true }) } }) } }, // 获取用户信息 getUserInfo: function(e) { console.log(e) app.globalData.userInfo = e.detail.userInfo this.setData({ userInfo: e.detail.userInfo, hasUserInfo: true }) }, // 分享界面 onShareAppMessage: function () { // return custom share data when user share. return { title: '这是一个测试', path: '/pages/logs/logs?id=123' } }, })
发送请求给后台:
wx.request({ url: 'https://windeyt.com/xx/xx/xx', data: { x: '', y: '' }, header: { 'content-type': 'application/json' // 默认值 }, success: function (res) { console.log(res.data); } })
关于小程序backgroundColor不生效的问题:
官方文档,放在index.json中,其他都生效,就是backgroundColor不生效。
{ "navigationBarBackgroundColor": "#ffffff", "navigationBarTextStyle": "black", "navigationBarTitleText": "微信接口功能演示", "backgroundColor": "#eeeeee", "backgroundTextStyle": "light" }
————解决办法:直接写在index.wxss中:
page{ background-color: #f7f7f7; }
————是的,直接写page的background-color即可。
wx.login和wx.getUserInfo的区别:
wx.login可以在静默的情况下,直接获得code,发送给后台获得session_key、openid和unionid(如果有)。而wx.getUserInfo是需要用户同意,获取他的信息(不含openid)。
因为不是网页开发,没有session。所以需要保存用户的登录信息。使用wx.login能够获取openid,并保存在本地,作为后续的验证。记录登录状态。
————使用wx.login获取openid和session_key:
wx.login({ success: function (res) { if (res.code) { //发起网络请求 wx.request({ url: self.globalData.serverUrl + 'api/wx/getopenid', data: { code: res.code }, header: { 'content-type': 'application/json' // 默认值 }, success: function (res) { var data = JSON.parse(res.data); var openid = data.openid self.globalData.userInfo.openid = openid; console.log(self.globalData.userInfo); } }); } else { console.log('登录失败!' + res.errMsg); } } })
后台代码:
if (request()->isGet()){ $code = $_GET['code']; $url = 'https://api.weixin.qq.com/sns/jscode2session?appid='. 'xxx'. '&secret='.'xxx'. '&js_code='.$code. '&grant_type=authorization_code'; $res = http_request($url); return json_encode($res); }
——自定义弹框:
1、index.wxml:
<!-- 弹框测试 --> <view hidden="{{nullHouse}}"> <view class="myToast" bindtap="toastHide"></view> <view style="text-align:center"> <image class="home_icon lock" mode="widthFix" src='/images/lock.png'></image> //图片高度自适应 </view> </view> <view bindtap="clickArea">弹框测试</view>
2、index.wxss
/* 测试样式 */ .myToast{ width:100%; height:100%; background-color: #000; position: fixed; top: 0px; left: 0px; z-index: 100; opacity: 0.5; } .lock{ position:fixed; left:275rpx; top:35vh; z-index:999; width:200rpx; }
3、index.js:
Page({ data: { nullHouse: true, //true:隐藏,false:显示 }, clickArea: function () { var that = this; this.setData({ nullHouse: false, //弹窗显示 }); }, toastHide:function(){ this.setData({ nullHouse: true, //弹窗显示 }); } })
改变radio的大小:
radio{ transform:scale(0.8)}
关于子界面参数再次传给父界面:
1、不能使用wx.navigateTo或者
wx.redirectTo,因为返回都会又回到子界面
有两种方法:
方法一:设置storage或者globalData,然后回去的时候去取。
方法二:直接在子界面设置变量,下面演示方法二。(记得,是直接绑定了哦,返回上级界面不需要再取了。)
// 选择小区+设置上级界面的小区数据+返回上一级界面 selectVillage: function (e) { var villageId = e.currentTarget.dataset.id; var villageName = e.currentTarget.dataset.name; var pages = getCurrentPages(); var currPage = pages[pages.length - 1]; //当前页面 var prevPage = pages[pages.length - 2]; //上一个页面 //直接调用上一个页面的setData()方法,把数据存到上一个页面中去 prevPage.setData({ //记住,这里设置的直接就是上级界面的变量{{villageInfo.villageName}}和{{villageInfo.village_id}} villageInfo: { villageId: villageId, villageName:villageName } }); wx.navigateBack({ delta: 1 }) },
——————占位符