wx.opensetting废弃之后的二次授权(可以通过button也可以通过modal的方式,很多人说不可以用showModal但本人亲测可用,版本为2.8.3)

   wx.showModal({title: '提示',content: '这是一个模态弹窗',success(res) {if (res.confirm) {console.log('用户点击确定')wx.openSetting({success(res) { console.log(res) },fail(res) { console.log(res) },})}}})
点击确定即可进入权限设置页面      如果直接使用wx.openSetting会报错:VM1015:1 openSetting:fail can only be invoked by user TAP gesture.

自定义弹窗防止底层触摸

/****弹窗****/
<view catchtouchmove='true'>...
</view>

监听左上角返回键 

 onUnload: function () {wx.reLaunch({url: '../logs/logs'})

拨打电话

wx.makePhoneCall({phoneNumber: '123456789' // 仅为示例,并非真实的电话号码})

客服(小程序后台可以绑定客服人员)

<button open-type="contact" bindcontact="handleContact">客服</button>

置顶

wx.pageScrollTo({scrollTop: 0})

动画

let that = this
var animation = wx.createAnimation({// 动画持续时间duration: 500,// 定义动画效果,当前是匀速timingFunction: 'linear'})// 将该变量赋值给当前动画that.animation = animation// 先在y轴偏移,然后用step()完成一个动画animation.translateY(1000).step()// 用setData改变当前动画that.setData({// 通过export()方法导出数据animationData: animation.export(),chooseSize: true})

地址三级联动

wxml
<view style='height:84rpx;background:#fff;border-bottom:1px solid #D9D9D9;line-height:84rpx;'><view class="section__title" style='display:inline-block;line-height:85rpx;color:rgba(0,0,0,1);font-size:33rpx;float:left;'>选择地址</view><picker mode="region" bindchange="bindRegionChange" value="{{detailed}}" custom-item="{{customItem}}"name="detailed" style='display:inline-block;font-size:33rpx;color:#C7C7CC;width:71%;margin-left:36rpx;height:75rpx;letter-spacing:2rpx;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;}' ><view class="picker {{clas}}" >{{detailed}}</view></picker></view>
jsPage({data: {customItem: [],detailed: '请选择',},//省市联动bindRegionChange: function (e) {var that = this//为了让选择框有个默认值,    that.setData({clas: ''})   //下拉框所选择的值console.log('picker发送选择改变,携带值为', e.detail.value)this.setData({//拼的字符串传后台detailed: e.detail.value[0] + " " + e.detail.value[1] + " " + e.detail.value[2],//下拉框选中的值region: e.detail.value})this.setData({"AddSite.area": e.detail.value[0] + " " + e.detail.value[1] + " " + e.detail.value[2]})console.log(this.data.AddSite)},
})

小程序强制更新

在app.js的onLaunch方法中使用:const updateManager = wx.getUpdateManager()updateManager.onCheckForUpdate(function (res) {// 请求完新版本信息的回调console.log(res.hasUpdate)
})updateManager.onUpdateReady(function () {wx.showModal({title: '更新提示',content: '新版本已经准备好,是否重启应用?',success: function (res) {if (res.confirm) {// 新的版本已经下载好,调用 applyUpdate 应用新版本并重启updateManager.applyUpdate()}}})
})updateManager.onUpdateFailed(function () {// 新的版本下载失败wx.showModal({title: '更新提示',content: '新版本下载失败',showCancel:false})
})

轮播图

<swiper indicator-dots="true" autoplay="true" interval="5000" duration="1000" style='width: 100%'><swiper-item wx:for="{{imgUrls}}" wx:for-item="imgItem"><image src='{{imgItem}}' class="slide-image" width="355" height="150" /></swiper-item>
</swiper>

下拉刷新

app.json"window": {"enablePullDownRefresh": true
}
onPullDownRefresh: function () {wx.stopPullDownRefresh()
}

自定义属性

<view class='zright' bindtap='choseCoupon' data-info='{{item}}'  data-id='{{index}}'>choseCoupon: function (e) {console.log(e.currentTarget.dataset.id)console.log(e.currentTarget.dataset.info)
}

bindtap和catchtap 以及 .currentTarget和.target

bindtap事件属于冒泡事件
当事件没有冒泡行为时,e.target是tap点击事件触发的对象(也就是点击的是谁,e.currentTarget是事件绑定在哪个元素上(也就是这个事件在哪个组件上)。
e.targe可以理解是最里面的view   e.currentTarget是view的父元素 即被冒泡的父元素
catchtap阻止事件冒泡
当事件没有冒泡行为时,e.target与e.currentTarget都指向事件触发的对象。
target:事件源组件对象(事件触发的对象)  currentTarget:当前组件对象(事件触发被冒泡的对象)
冒泡事件有:touchstart   touchmove   touchend  longtap   tap这五个事件,其余的事件为非冒泡事件。 
总结:
currentTarget可能会等于target,但是target不一定会等于currentTarget,看事件类型 即非冒泡相等 冒泡不相等 currentTarget是父元素 target是事件触发的对象
冒泡:事件从里层到外层

小程序和vue的语法区别 

数据绑定
小程序(不加括号,为被认为是字符串)
<image src="{{imgSrc}}"></image>
vue
<img :src="imgSrc"/>循环渲染
小程序
<text wx:for="{{items}}">{{item}}</text>
vue
<li v-for="item in items">{{ item.message }}
</li>显示隐藏
小程序中,使用wx-if和hidden控制元素的显示和隐藏
vue中,使用v-if 和v-show控制元素的显示和隐藏事件处理
小程序中,全用bindtap(bind+event),或者catchtap(catch+event)绑定事件
vue:使用v-on:event绑定事件,或者使用@event绑定事件绑定事件传参
vue可以直接传参 例如 @click="say('明天不上班')"
小程序不可以直接传参数 通过e.currentTarget.dataset.*的方式获取双向绑定
小程序的表单没有v-model
使用this.setData({key:value})代替v-model

页面生命周期

 onLoad  onReady  onShow onHide   onUnload 卸载 onPullDownRefresh 下拉  onReachBottom 上拉

组件

子组件
生命周期
created 组件实例化,但节点树还未导入,因此这时不能用setData
attached 节点树完成,可以用setData渲染节点,但无法操作节点
ready 组件布局完成,这时可以获取节点信息,也可以操作节点
moved 组件实例被移动到树的另一个位置
detached 组件实例从节点树中移除在子组件的json文件中,将该文件声明为组件
{"component": true
}
在需要引入的父组件的json文件中,在usingComponents填写引入组件的组件名以及路径"usingComponents": {"tab-bar": "../../components/tabBar/tabBar"}父组件引入
<tab-bar currentpage="index"></tab-bar>父子通信
在子组件properties中,接收传递的值properties: {currentpage: { type: String, // 类型包括:String, Number, Boolean, Object, Array, null(表示任意类型)value: 'index'  }}子父通信子组件var myEventDetail = "我是子组件通信父组件的"this.triggerEvent('myevent', myEventDetail) //myevent自定义名称事件,父组件中使用
父组件
<bar bind:myevent="toggleToast" ref="bar"></bar>
// 获取子组件信息
toggleToast(e){console.log(e.detail)
}通过id或者class调用子组件的方法
this.selectComponent('#id').syaHello()
//vue是使用ref名调用 this.$ref.bar.子组件的方法

通信

缓存方式
a页面:wx.setStorageSync("data","b页面的数据")
b页面:console.log(wx.getStorageSync("data")) //"b页面的数据"getCurrentPages() 方式
getCurrentPages() 获取当前页面栈。数组中第一个元素为首页,最后一个元素为当前页面。
使用:let pages = getCurrentPages();let curPage = pages[pages.length - 1];//现在页面let beforePage = pages[pages.length - 2];//上一个页面console.log(curPage)beforePage.setData({ text: "我是上个页面修改的" })
注意事项
不要在 App.onLaunch 的时候调用 getCurrentPages,此时 page 还没有生成。
页面A必须使用 wx.navigateTo() 跳转到下一页面B,不能使用wx.redirectTo等其它的跳转方式,这样会关闭上一个页面,导致页面B无法获取上一页的Page实例
getCurrentPages无法实现tab页面之间的通信 原因也很简单 getCurrentPages是页面栈 tab之间是switchTab路由通信的 不存在页面栈url传递通信events.js
/*** 使用方式:* 1、接收方js代码中*  1.1 引入该类,如:let flashEvent = require('你的路径/utils/FlashEvent.js');*  1.2 注册FlashEvent,如:在onLoad中*    flashEvent.register(flashEvent.EVENT_KEYS.FIRST_EVENT, this, function (data) {*       this.setData({*         eventCallBack: data*       })*    })*  1.3 注销FlashEvent,如:在onUnload中调用 flashEvent.unregister(flashEvent.EVENT_KEYS.FIRST_EVENT, this);* 2、发送方js代码中*  2.1 引入该类,如:let flashEvent = require('你的路径/utils/FlashEvent.js');*  2.2 发送事件,如:flashEvent.post(flashEvent.EVENT_KEYS.FIRST_EVENT, '发送的数据');*/
// 事件定义 方便维护管理 - 新事件添加到此处
const EVENT_KEYS = {FIRST_EVENT: "FIRST_EVENT"
}// 存储组合后的事件
var eventData = {};
/*** register 注册事件:再Page* key 事件名* context 上下文-当前page的this* callback 事件回调*/
function register(key, context, callback) {var eventInfo = [context, callback];var callbacks = eventData[key];if (Array.isArray(callbacks)) {callbacks.push(eventInfo);} else {eventData[key] = [eventInfo];}
}
/*** unregister 注销事件* key 事件名* context 上下文-当前page的this*/
function unregister(key, context) {var callbacks = eventData[key];if (Array.isArray(callbacks)) {eventData[key] = callbacks.filter((eventInfo) => {return eventInfo[0] != context;})}
}
/*** post 发送事件* key 事件名* data 传递的数据*/
function post(key, data) {var callbacks = eventData[key];if (Array.isArray(callbacks)) {callbacks.map((eventInfo) => {var context = eventInfo[0];var callback = eventInfo[1];callback.call(context, data);})}
}
// 导出代码
module.exports = {EVENT_KEYS: EVENT_KEYS,register: register,unregister: unregister,post: post
}//使用
a页面
let flashEvent = require('./../../utils/events.js');
flashEvent.register(flashEvent.EVENT_KEYS.FIRST_EVENT, this, function (data) {console.log(data)  //监听数据 打印出:发送的数据})b页面let flashEvent = require('./../../utils/events.js');flashEvent.post(flashEvent.EVENT_KEYS.FIRST_EVENT, '发送的数据');// 注销FlashEvent,如:在onUnload中调用 //flashEvent.unregist(flashEvent.EVENT_KEYS.FIRST_EVENT, this);//store.js
/*** @author xiaoheng* @time 2019/8/1* @github https://github.com/xiaoheng21* @tip 还在找工作,有机会望告知,坐标北京*/
/*** 状态管理类* @constructor 构造函数* @_data  内部数据,用来保存页面数据* @addData 添加页面数据的方法* @removeData 移除不需要的页面数据,减小内存压力*/
class Store {constructor() {this._data = {};}/*** 向数据池里添加数据* @param { Object<this> } context 保存当前页面的执行上下文,也就是当前页面的 this* @param { String } name 当前页面数据的名字,用于在别的页面读取数据,默认值为当前页面的路径*/addData(context, name) {// 如果传了 name 就用传过来的,如果未传就用页面路径let routeName = name ? name : context.route;//设置代理,用于简化操作let proxyContext = new Proxy(context, {// 获取数据,如果数据在外层,返回外层数据get: function (context, property) {if (property in context) {return context[property];} else {// 如果外层找不到数据, 就在 "this.data" 里找,若有,返回数据if (property in context.data) {return context.data[property];} else {//若没有,报错console.error(`${name}页面没有此属性`);}}},// 改变数据, 封装 "this.setData", 简化操作set: function (context, property, value) {context.setData({[property]: value});return true;},// 判断数据是否存在has: function (context, property) {return property in context.data;}});// 将代理对象添加进数据池this._data[routeName] = proxyContext;}/*** 从数据池里移除页面数据* @param { String } name 需要移除的页面的名字*/removeData(name) {if (name in this._data) {delete this._data[name];} else {console.error(`希望删除的属性不存在`);}}
}// 创建单例对象,全局共享一个数据池
const store = new Store();// 创建代理, 私有化 _data, 简化用户操作, 提高安全性
let proxyStore = new Proxy(store, {// 若访问的属性为 add remove 函数, 直接返回函数get: function (store, property) {if (property in store) {return store[property];} else {// 若访问的数据为页面数据, 则返回页面代理对象if (property in store._data) {return store._data[property];} else {// 若没有页面信息, 报错console.error("访问的页面数据未载入数据池");}}}
});export default proxyStore;使用:
import store from "./../utils/store.js"添加页面数据
store.addData( context, name )
参数说明:
context
执行上下文,也就是当前页面的 this
name
命名当前页面,也就是在别的页面取值的时候 store.name.属性,默认值为当前页面的路径移除页面数据
store.removeData( name )
参数说明
name
希望删除的页面数据的名字获取数据
let value = store.页面name.属性
这样既可获取数据,后台是用代理封装了数据池,从而方便用户使用修改数据
store.页面name.属性 = value
这样赋值即可,后台使用的依然是封装的 setData检测属性是否存在
property in store.页面name

微信授权失败处理(有关授权的代码一般放在onShow生命周期里面)

方案一
wx.getSetting({success: function (res) {var statu = res.authSetting;if (!statu['scope.userLocation']) {
//没有权限直接跳转权限设置页wx.navigateTo({url: './../setSetting/setSetting',})
//提示用户没有权限直接跳转权限设置页// wx.showModal({//   title: '是否授权当前位置',//   content: '需要获取您的地理位置,请确认授权,否则地图功能将无法使用',//   success: function (tip) {//     console.log(tip)//     if (tip.confirm == true) {//       wx.navigateTo({//         url: './../setSetting/setSetting',//       })//     }//   }// })}
setSetting.wxml
<button type='primary' open-type="openSetting">  授权登录 </button>方案二
可以把授权按钮封装成弹窗组件形式(太长不贴代码了)

小程序登录 (就是通过login得到临时登录code去服务端后台请求得到openid和session_key和用户信息)

wxml
<button open-type="getUserInfo" bindgetuserinfo="bindGetUserInfo">点击授权</button>
js
bindGetUserInfo(res) {let info = res;console.log(info);if (info.detail.userInfo) {console.log("点击了同意授权");wx.login({success: function (res) {if (res.code) {wx.request({url: 'http://www.test.com/test',//服务端接口data: {code: res.code,nickName: info.detail.userInfo.nickName,avatarUrl: info.detail.userInfo.avatarUrl},header: {'content-type': 'application/json' // 默认值},success: function (res) {var userinfo = {};userinfo['id']=res.data.id;userinfo['nickName'] = info.detail.userInfo.nickName;wx.setStorageSync('userinfo', userinfo);                    }})} else {console.log("授权失败");}},})} else {console.log("点击了拒绝授权");}}

小程序使用菜单

  wx.showActionSheet({itemList: ['从手机相册选择', '拍照'],success: function (res) {console.log(res.tapIndex)},fail: function (res) {console.log(res.errMsg)}})

微信使用相册选择图片

         wx.chooseImage({count: 1, // 默认9sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有success: function (res) {// 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片var tempFilePaths = res.tempFilePathsconsole.log(tempFilePaths)that.setData({src: tempFilePaths,})}})
//实例
//js/** 选择图片Banner */chooseBanner: function () {var that = this;if (this.data.banner.length < 3) {wx.chooseImage({count: 2, //最多选择1张图片- that.data.banner.length,sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有success: function (res) {// 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片console.log(res.tempFilePaths);if (res.tempFilePaths.count == 0) {return;}//上传图片var imgArrNow = that.data.banner;imgArrNow = imgArrNow.concat(res.tempFilePaths);that.setData({banner: imgArrNow})that.chooseViewShowBanner();}})} else {wx.showToast({title: '限制选择6个文件',icon: 'loading',duration: 1000})}},/** 删除图片Banner */deleteImvBanner: function (e) {var banner = this.data.banner;var itemIndex = e.currentTarget.dataset.id;banner.splice(itemIndex, 1);this.setData({banner: banner})//判断是否隐藏选择图片this.chooseViewShowBanner();},/** 是否隐藏图片选择Banner*/chooseViewShowBanner: function () {if (this.data.banner.length >= 3) {this.setData({chooseViewShowBanner: false})} else {this.setData({chooseViewShowBanner: true})}},/** 查看大图Banner */showImageBanner: function (e) {var banner = this.data.banner;var itemIndex = e.currentTarget.dataset.id;console.log("itemIndex:" + JSON.stringify(e))wx.previewImage({current: banner[itemIndex], // 当前显示图片的http链接urls: banner // 需要预览的图片http链接列表})}
//wxml
<view class="addImv"><!--这个是已经选好的图片--><view wx:for="{{banner}}" wx:key="key" class="upFile" bindtap="showImageBanner" style="border-radius: 5px" data-id="{{index}}"><image class="itemImv" src="{{item}}"></image><view class="closeImv" catchtap="deleteImvBanner" data-id="{{index}}">+</view><!-- <image src="../../resources/images/delect.png" mode="scaleToFill" ></image> --></view><!--这个是选择图片--><view class="chooseView" bindtap="chooseBanner" wx:if="{{chooseViewShowBanner}}" style="border-radius: 5px" ><!-- <image class="chooseImv" src="../../resources/images/add.png"></image>-->+ </view></view>
//wxss.container {background-color: #F2f2f2;
}.swiper_box {width: 100%;
}swiper-item image {width: 100%;display: inline-block;overflow: hidden;
}view.text {display: flex;align-items: center;position: relative;padding: 10px 10px 10px 12px;font-size: 15px;color: #656565;
}view.text:before {position: absolute;display: block;content: ' ';left: -5px;width: 2px;height: 100%;background-color: #09bb07;
}.line_flag {width: 3px;height: 100%;height: 15px;display: inline-block;background-color: #f9f027;
}view.text text {margin-left: 10px;line-height: 18px;font-weight: bold;
}.venues_box {padding: 0 10rpx;
}.venues_item {display: inline-block;width: 49%;margin: 0 0.5%;
}.venues_item image{width: 100%;height: 90px;
}.choice_box {padding: 0 10rpx;
}
.choice_box .choice_list .choice_item{margin-bottom: 15px;
}
.choice_box .choice_list image {width: 100%;height: 200px;
}.choice_box .choice_list .title {font-size: 12px;font-weight: bold;text-align: center;color: #333;
}.addImv {/* background-color: white; */border: 1px dashed gray;display: flex;flex-wrap: wrap;align-items: center;margin-top: 5rpx;/* width: 50rpx;height: 50rpx; */
}.upImv {background-color: white;width: 100%;margin-top: 5rpx;
}.upImv_text {font-size: 30rpx;margin-left: 20rpx;padding-top: 20rpx;
}/*添加图片*/.addImv{padding: 20rpx}
.addImv .chooseView {width: 180rpx;height: 180rpx;/* margin: 20rpx 20rpx; */background-color: #f2f6f9;border: 1px dashed lightgray;text-align: center;line-height: 180rpx;/* padding: 0rpx 7rpx; */border-radius: 5px;margin-left: 40rpx;
}.addImv .chooseImv {width: 50rpx;height: 50rpx;
}/*已选择的图片*/.addImv .upFile {width: 180rpx;height: 180rpx;position: relative;/* padding: 0rpx 7rpx; */margin-left: 40rpx;border: 1px solid #c0ccda;
}.addImv .upFile .itemImv {width: 180rpx;height: 180rpx;/* padding: 0rpx 7rpx; */
}.addImv .upFile .closeImv {position: absolute;right: 0rpx;top: 0rpx;width: 25rpx;height: 25rpx;transform:rotate(45deg);color: red;}

微信地图api 

app.json
"permission": {
"scope.userLocation": {
"desc": "你的位置信息将用于小程序位置接口的效果展示"}}wxml<!--index.wxml-->
<view class='view'><map longitude="{{longitude}}" latitude="{{latitude}}" markers="{{markers}}" covers="{{covers}}" show-location><cover-view>经度:{{longitude}}</cover-view><cover-view>纬度:{{latitude}}</cover-view><cover-view>速度:{{speed}}</cover-view><cover-view>精度:{{accuracy}}</cover-view></map>
</view>jsconst app = getApp()
Page({data: {longitude: 116.4965075,latitude: 40.006103,speed: 0,accuracy: 0,markers: [{id: 0,latitude: 22.26606,longitude: 113.54302,// alpha:0,callout: {content: " text \n 12000元/㎡",padding: 5,display: 'ALWAYS',textAlign: 'center',// borderRadius: 5,// borderColor:'#ff0000',// borderWidth: 2,}},{id:1,latitude: 22.26666,longitude: 113.54342,callout: {content: " text123 \n 12000元/㎡",padding: 5,display: 'ALWAYS',textAlign: 'center',}}]},//事件处理函数bindViewTap: function () {},onShow: function () {var that = thiswx.showLoading({title: "定位中",mask: true})wx.getLocation({type: 'gcj02',altitude: true,//高精度定位//定位成功,更新定位结果success: function (res) {var latitude = res.latitudevar longitude = res.longitudevar speed = res.speedvar accuracy = res.accuracythat.setData({longitude: longitude,latitude: latitude,speed: speed,accuracy: accuracy})console.log(res)},//定位失败回调fail: function () {wx.showToast({title: "定位失败",icon: "none"})wx.getSetting({success: function (res) {var statu = res.authSetting;if (!statu['scope.userLocation']) {//也可以检测到没有权限直接跳转授权也//  wx.navigateTo({//      url: './../setSetting/setSetting',})//wx.showModal({title: '是否授权当前位置',content: '需要获取您的地理位置,请确认授权,否则地图功能将无法使用',success: function (tip) {console.log(tip)if (tip.confirm == true) {wx.navigateTo({url: './../setSetting/setSetting',})}}})}},fail: function (res) {console.log(res)wx.showToast({title: '调用授权窗口失败',icon: 'success',duration: 1000})}})},complete: function () {//隐藏定位中信息进度wx.hideLoading()console.log("定位失败")}})},
})wxss
.view {width: 100%;height: 100vh;
}map {width: 100%;height: 100%;
}
//授权失败引导跳转
setSetting.wxml
<button type='primary' open-type="openSetting">  授权登录 </button>

打开地图和选择位置 

 wx.openLocation({latitude: latitude,longitude: longitude,scale: 18,success: function (res) {console.log(res)},fail: function (res) {console.log(res)},complete:function(res){console.log(res)}})wx.chooseLocation({success: function(res) {console.log(res)},fail: function (res) {console.log(res)},complete: function (res) {console.log(res)}})

支付(支付其实不难 大多是服务端实现)

小程序调用登录接口获取code,传递给商户服务器用来获取用户的openID
通过openID和订单信息 请求服务端接口得到wx.requestPayment需要的五个参数信息调起支付wx.requestPayment({"timeStamp": "","nonceStr": "","package": "","signType": "MD5","paySign": "","success":function(res){},"fail":function(res){}
})

请求接口封装

until.js
// 网络请求
const request = function(url, method, data, msg, succ, fail, com) {// 小程序顶部显示Loadingwx.showNavigationBarLoading();if (msg != "") {wx.showLoading({title: msg})}wx.request({url: url,data: data,header: {'content-type': 'application/x-www-form-urlencoded'},method: method,success: res => {if (succ) succ(res);},fail: err => {if (fail) fail(err);},complete: com => {wx.hideNavigationBarLoading();if (msg != "") {wx.hideLoading();}console.log(url + ' 返回的data:', com.data);}})
}
module.exports = request;//
var util = require("../../utils/util.js")let that = thisutil.request('test.php', 'get', { id: 1 } , '正在加载数据', res=> {that.setData({list_data:res.data})},err=> {wx.showToast({title: '加载数据失败',icon:"none"})})

wx.authorize(用户拒绝短期间内不会再弹起授权请求,通过openSetting的方式)

// 可以通过 wx.getSetting 先查询一下用户是否授权了 "scope.record" 这个 scope
wx.getSetting({success(res) {if (!res.authSetting['scope.record']) {wx.authorize({scope: 'scope.record',success () {// 用户已经同意小程序使用录音功能,后续调用 wx.startRecord 接口不会弹窗询问wx.startRecord()}})}}
})wx.authorize是授权用的
wx.getSetting是判断是否已经授权用的
wx.openSetting是打开授权列表用的

wx.getSetting 回调结果例如 res['scope.userLocation'] 没授权为null  授权了是true

boolean scope.userInfo
是否授权用户信息,对应接口 wx.getUserInfoboolean scope.userLocation
是否授权地理位置,对应接口 wx.getLocation, wx.chooseLocationboolean scope.address
是否授权通讯地址,对应接口 wx.chooseAddressboolean scope.invoiceTitle
是否授权发票抬头,对应接口 wx.chooseInvoiceTitleboolean scope.invoice
是否授权获取发票,对应接口 wx.chooseInvoiceboolean scope.werun
是否授权微信运动步数,对应接口 wx.getWeRunDataboolean scope.record
是否授权录音功能,对应接口 wx.startRecordboolean scope.writePhotosAlbum
是否授权保存到相册 wx.saveImageToPhotosAlbum, wx.saveVideoToPhotosAlbumboolean scope.camera
是否授权摄像头,对应<camera /> 组件

保存图片


wx.downloadFile({url: 'https://example.com/123',     //仅为示例,并非真实的资源success: function (res) {// 只要服务器有响应数据,就会把响应内容写入文件并进入 success 回调,业务需要自行判断是否下载到了想要的内容if (res.statusCode === 200) {wx.saveImageToPhotosAlbum({filePath: res.tempFilePath,success(res) {wx.showToast({title: '保存图片成功!',})},fail(res) {wx.showToast({title: '保存图片失败!',})}})}}
})

wx.createSelectorQuery()

demo01
const query = wx.createSelectorQuery()
query.select('#the-id').boundingClientRect()
query.selectViewport().scrollOffset()
query.exec(function(res){res[0].top       // #the-id节点的上边界坐标res[1].scrollTop // 显示区域的竖直滚动位置
})demo02
wx.createSelectorQuery().select('#the-id').fields({dataset: true,size: true,scrollOffset: true,properties: ['scrollX', 'scrollY']}, function(res){res.dataset    // 节点的datasetres.width      // 节点的宽度res.height     // 节点的高度res.scrollLeft // 节点的水平滚动位置res.scrollTop  // 节点的竖直滚动位置res.scrollX    // 节点 scroll-x 属性的当前值res.scrollY    // 节点 scroll-x 属性的当前值}).exec()}

微信小程序记录与项目实践相关推荐

  1. 微信小程序“信用卡还款”项目实践

    小程序概述 11月3日晚,微信团队对外宣布,微信小程序开放公测.开发者可登陆微信公众平台申请,开发完成后可以提交审核,公测期间暂不能发布. 我们前一段时间也进行了小程序开发,现在来对之前的开发体验做一 ...

  2. 微信小程序Taro + React开发实践

    微信小程序Taro + React开发实践 微信小程序原生开发有一套自己的规范和写法,开发体验十分类似Vue,但如果你想减少学习成本,那么Taro框架是一个在此基础上又封装了一层的轮子,从社区热度到开 ...

  3. 视频教程-【三月】微信小程序云开发项目实战课程 - T3租机械-微信开发

    [三月]微信小程序云开发项目实战课程 - T3租机械 宁夏酷申科技有限公司技术总监,计算机专业毕业后一直从事技术开发和架构工作 袁永刚 ¥366.00 立即订阅 扫码下载「CSDN程序员学院APP」, ...

  4. 微信小程序记录用户行为浏览记录和停留时间以及小程序全局分享

    微信小程序记录用户行为浏览记录和停留时间以及小程序全局分享 项目需求 1.后台统计一个用户在我们小程序的每个页面的停留时间 2,前台用户可以在个人中心看到自己的分享记录以及多少人查看 需求分析 需求一 ...

  5. 详解微信小程序开发(项目从零开始)

    关注公众号 风色年代(itfantasycc) 280G前端&小程序资料随便拿! 详解微信小程序开发(项目从零开始) 一.序 微信小程序,估计大家都不陌生,现在应用场景特别多.今天就系统的介绍 ...

  6. 微信读书登陆界面java_(JAVA后端)微信小程序-毕设级项目搭建-微信阅读小程序(内含源码,微信小程序+java逻辑后台+vue管理系统)~不求完美,实现就好...

    转载地址:(JAVA后端)微信小程序-毕设级项目搭建-微信阅读小程序(内含源码,微信小程序+java逻辑后台+vue管理系统)~不求完美,实现就好 转载请注明出处 一.环境搭建 相关环境软件:JDK1 ...

  7. 微信小程序云开发项目-个人待办事项-02今日模块开发

    上一篇: 微信小程序云开发项目-个人待办事项-01介绍 https://blog.csdn.net/IndexMan/article/details/124485626 模块开发步骤 本篇介绍今日模块 ...

  8. 微信小程序云音乐项目

    微信小程序云音乐项目 微信小程序云音乐项目 1. 项目介绍 技术栈 项目使用库 项目目标 2. 页面效果和功能展示 3. 项目源码与 API 接口 4. 项目说明 5. 致谢 微信小程序云音乐项目 1 ...

  9. 微信小程序电商项目开发实战漫谈

    原创文章,若转载请于明显处标明出处和相关链接:https://www.toutiao.com/i6567868839856439822/,否则追究其法律责任! 2018年小程序内容电商风口已成,如果我 ...

最新文章

  1. 关于60枚一分两分五分硬币凑成一块钱的解决方法
  2. B - Dungeon Master POJ - 2251
  3. Javascript 获取页面高度(多种浏览器)【转】
  4. C++实现快速排序(附完整源码)
  5. 逻辑回归算法_算法逻辑回归
  6. bi power 两个日期挑较早的日期_功率 BI 中的时间智能:利用时间
  7. ORA-00376:file x cannot be read at this time
  8. 网络_连接路由器的每台电脑使用固定IP的方法(TP-LINK)
  9. AndroidOpenCV摄像头预览全屏问题
  10. [转]VS 2005快捷键
  11. java apdu读取社保卡_读取社保卡信息
  12. matlab 电机 热仿真,MATLAB在电机仿真中的应用
  13. 应用软件提示服务器正在运行,服务器正在运行中怎么解决?IE浏览器服务器正在运行中的解决方法...
  14. 月薪过万是普遍现象吗?很抱歉,这事大部分人的错觉
  15. Axure RP10——值得信赖的强大的原型制作工具,无需编写代码即可创造无限可能
  16. 极兔快递电子面单打印API接口-极兔快递
  17. 身高预测c语言代码switch,C++ ,预测身高程序
  18. 5步完成编写Mysql的shell脚本
  19. 如何用私钥登陆linux服务器和cyberduck登陆配置
  20. Android 详解第三方介质交互之NFC,并且实现读你的交通卡,酒店房卡,学生证!

热门文章

  1. 【嵌入式学习-STM32F103-EXTI外部中断】
  2. shell插入多行文本
  3. 511遇见易语言子程序参考的作用
  4. 非专业python学多久_非的解释|非的意思|汉典“非”字的基本解释
  5. 我是如何零基础开始能写爬虫的?
  6. 壁纸|苹果Live壁纸以及静态壁纸,给大家分享点
  7. 51单片机c语言实践教程,51单片机C语言实验与实践教程.pdf
  8. Reason: Cannot pass null or empty values to constructor in spring security
  9. 完全认识计算机网络之TCP/IP
  10. 蓝桥杯单片机决赛(国赛)第十一届题目加代码