0. 前言
  这两天刚好了解了一下微信小程序的蓝牙功能。主要用于配网功能。发现微信的小程序蓝牙API已经封装的很好了。编程起来很方便。什么蓝牙知识都不懂的情况下,不到两天就晚上数据的收发了,剩下的就是数据帧格式的定义,当然这部分就不是本次博客的重点。
1. 准备硬件
  这里我准备了CH341SER这个作为USB转串口。用sscom5.13.1 串口工具。由于我不太懂硬件开发。硬件部分都是由公司其他人开发的。我只是负责把环境搭建起来。然后负责我的微信小程序开发。

2. 开发小程序简单讲解
  onLoad 这个一方面是用来获取当前连接的WiFi名称,减少用户输入,另一方面也是用来判断当前是否开启GPS功能。对于Android用户,是需要打开GPS蓝牙功能才能搜索到周围的蓝牙设备。

   onLoad: function(options) {
var that = this;
wx.startWifi({
success(res) {
console.log(res.errMsg)
wx.getConnectedWifi({
success: function(res) {
console.log(res);
that.setData({
ssid: res.wifi.SSID
})
},
fail: function(res) {
if(res.errCode == 12006){
wx.showModal({
title: '请打开GPS定位',
content: 'Android手机不打开GPS定位,无法搜索到蓝牙设备.',
showCancel: false
})
}
console.log(res);
}
})
}
})
},

  搜索蓝牙设备相关代码

   searchBleEvent: function(ret){
var ssid = this.data.ssid;
var pass = this.data.pass;
console.log(ssid, pass);
if (util.isEmpty(ssid) || util.isEmpty(pass)) {
util.toastError('请输入WiFi名称及密码');
return;
}
this.initBLE();
},

  初始化蓝牙适配器

   initBLE: function() {
this.printLog("启动蓝牙适配器, 蓝牙初始化")
var that = this;
wx.openBluetoothAdapter({
success: function(res) {
console.log(res);
that.findBLE();
},
fail: function(res) {
util.toastError('请先打开蓝牙');
}
})
},

  定义搜索设备任务

   findBLE: function() {
this.printLog("打开蓝牙成功.")
var that = this
wx.startBluetoothDevicesDiscovery({
allowDuplicatesKey: false,
interval: 0,
success: function(res) {
wx.showLoading({
title: '正在搜索设备',
})
console.log(res);
delayTimer = setInterval(function(){
that.discoveryBLE() //3.0 //这里的discovery需要多次调用
}, 1000);
setTimeout(function () {
if (isFound) {
return;
} else {
wx.hideLoading();
console.log("搜索设备超时");
wx.stopBluetoothDevicesDiscovery({
success: function (res) {
console.log('连接蓝牙成功之后关闭蓝牙搜索');
}
})
clearInterval(delayTimer)
wx.showModal({
title: '搜索设备超时',
content: '请检查蓝牙设备是否正常工作,Android手机请打开GPS定位.',
showCancel: false
})
util.toastError("搜索设备超时,请打开GPS定位,再搜索")
return
}
}, 15000);
},
fail: function(res) {
that.printLog("蓝牙设备服务发现失败: " + res.errMsg);
}
})
},

  搜索设备回调

   discoveryBLE: function() {
var that = this
wx.getBluetoothDevices({
success: function(res) {
var list = res.devices;
console.log(list);
if(list.length <= 0){
return ;
}
var devices = [];
for (var i = 0; i < list.length; i++) {   
//that.data.inputValue:表示的是需要连接的蓝牙设备ID,
//简单点来说就是我想要连接这个蓝牙设备,
//所以我去遍历我搜索到的蓝牙设备中是否有这个ID
var name = list[i].name || list[i].localName;
if(util.isEmpty(name)){
continue;
}
if(name.indexOf('JL') >= 0 && list[i].RSSI != 0){
console.log(list[i]);
devices.push(list[i]);
}
}
console.log('总共有' + devices.length + "个设备需要设置")
if (devices.length <= 0) {
return;
}
that.connectBLE(devices);
},
fail: function() {
util.toastError('搜索蓝牙设备失败');
}
})
},

  设置可以进行连接的设备

   connectBLE: function(devices){
this.printLog('总共有' + devices.length + "个设备需要设置")
var that = this;
wx.hideLoading();
isFound = true;
clearInterval(delayTimer);
wx.stopBluetoothDevicesDiscovery({
success: function (res) {
that.printLog('连接蓝牙成功之后关闭蓝牙搜索');
}
})
//两个的时候需要选择
var list = [];
for (var i = 0; i < devices.length; i++) {
var name = devices[i].name || devices[i].localName;
list.push(name + "[" + devices[i].deviceId + "]")
}
this.setData({
deviceArray: list
})
//默认选择
this.setData({
currDeviceID: list[0]
})
},

  选择设备,然后点击对应的配网按钮,创建BLE连接

   createBLE: function(deviceId){
this.printLog("连接: [" + deviceId+"]");
var that = this;
this.closeBLE(deviceId, function(res){
console.log("预先关闭,再打开");
setTimeout(function(){
wx.createBLEConnection({
deviceId: deviceId,
success: function (res) {
that.printLog("设备连接成功");
that.getBLEServiceId(deviceId);
},
fail: function (res) {
that.printLog("设备连接失败" + res.errMsg);
}
})
}, 2000)
});
},

  获取蓝牙设备提供的服务UUID(本项目由于只会提供一个服务,就默认选择,实际项目,会自定义这个UUID的前缀或者后缀规则,定义多个不同的服务)

   //获取服务UUID
getBLEServiceId: function(deviceId){
this.printLog("获取设备[" + deviceId + "]服务列表")
var that = this;
wx.getBLEDeviceServices({
deviceId: deviceId,
success: function(res) {
console.log(res);
var services = res.services;
if (services.length <= 0){
that.printLog("未找到主服务列表")
return;
}
that.printLog('找到设备服务列表个数: ' + services.length);
if (services.length == 1){
var service = services[0];
that.printLog("服务UUID:["+service.uuid+"] Primary:" + service.isPrimary);
that.getBLECharactedId(deviceId, service.uuid);
}else{ //多个主服务
//TODO
}
},
fail: function(res){
that.printLog("获取设备服务列表失败" + res.errMsg);
}
})
},

  获取服务下的特征值(由于这个例子,是包含两个特征值,一个用于读,一个用于写,实际项目,跟上面的服务一样,要定义好特征量UUID的规则)

   getBLECharactedId: function(deviceId, serviceId){
this.printLog("获取设备特征值")
var that = this;
wx.getBLEDeviceCharacteristics({
deviceId: deviceId,
serviceId: serviceId,
success: function(res) {
console.log(res);
//这里会获取到两个特征值,一个用来写,一个用来读
var chars = res.characteristics;
if(chars.length <= 0){
that.printLog("未找到设备特征值")
return ;
}
that.printLog("找到设备特征值个数:" + chars.length);
if(chars.length == 2){
for(var i=0; i<chars.length; i++){
var char = chars[i];
that.printLog("特征值[" + char.uuid + "]")
var prop = char.properties;
if(prop.notify == true){
that.printLog("该特征值属性: Notify");
that.recvBLECharacterNotice(deviceId, serviceId, char.uuid);
}else if(prop.write == true){
that.printLog("该特征值属性: Write");
that.sendBLECharacterNotice(deviceId, serviceId, char.uuid);
}else{
that.printLog("该特征值属性: 其他");
}
}
}else{
//TODO
}
},
fail: function(res){
that.printLog("获取设备特征值失败")
}
})
},

  recv 接收设备发送过来数据

   recvBLECharacterNotice: function(deviceId, serviceId, charId){
//接收设置是否成功
this.printLog("注册Notice 回调函数");
var that = this;
wx.notifyBLECharacteristicValueChange({
deviceId: deviceId,
serviceId: serviceId,
characteristicId: charId,
state: true, //启用Notify功能
success: function(res) {
wx.onBLECharacteristicValueChange(function(res){
console.log(res);
that.printLog("收到Notify数据: " + that.ab2hex(res.value));
//关闭蓝牙
wx.showModal({
title: '配网成功',
content: that.ab2hex(res.value),
showCancel: false
})
});
},
fail: function(res){
console.log(res);
that.printLog("特征值Notice 接收数据失败: " + res.errMsg);
}
})
},

  send 小程序发送数据到设备

   sendBLECharacterNotice: function (deviceId, serviceId, charId){
//发送ssid/pass
this.printLog("延时1秒后,发送SSID/PASS");
var that = this;
var cell = {
"ssid": this.data.ssid,
"pass": this.data.pass
}
var buffer = this.string2buffer(JSON.stringify(cell));
setTimeout(function(){
wx.writeBLECharacteristicValue({
deviceId: deviceId,
serviceId: serviceId,
characteristicId: charId,
value: buffer,
success: function(res) {
that.printLog("发送SSID/PASS 成功");
},
fail: function(res){
console.log(res);
that.printLog("发送失败." + res.errMsg);
},
complete: function(){ }
}) }, 1000);
},

  手机端可以同时连接多个蓝牙设备,但是同一个蓝牙设备不能被多次连接,所以需要在每次连接前关闭BLE连接

   closeBLE: function(deviceId, callback){
var that = this;
wx.closeBLEConnection({
deviceId: deviceId,
success: function(res) {
that.printLog("断开设备[" + deviceId + "]成功.");
console.log(res)
},
fail: function(res){
that.printLog("断开设备成功.");
},
complete: callback
})
},

  说明:接收数据和发送数据时,注意BLE限制了发送数据包的大小,现在20byte。具体参考微信小程序官方文档: https://developers.weixin.qq.com/miniprogram/dev/api/device/bluetooth-ble/wx.writeBLECharacteristicValue.html

3. 蓝牙相关的所有JS代码

 // pages/bluetoothconfig/bluetoothconfig.js
const util = require('../../utils/util.js') var delayTimer; //用来控制是否持续服务发现
var isFound = false; Page({
/**
* 页面的初始数据
*/
data: {
ssid: '',
pass: '',
logs: [],
deviceArray: [],
currDeviceID: '请选择...'
},
onLoad: function(options) {
var that = this;
wx.startWifi({
success(res) {
console.log(res.errMsg)
wx.getConnectedWifi({
success: function(res) {
console.log(res);
that.setData({
ssid: res.wifi.SSID
})
},
fail: function(res) {
if(res.errCode == 12006){
wx.showModal({
title: '请打开GPS定位',
content: 'Android手机不打开GPS定位,无法搜索到蓝牙设备.',
showCancel: false
})
}
console.log(res);
}
})
}
})
},
bindPickerChange: function(ret){
var array = this.data.deviceArray;
console.log(array[ret.detail.value]);
this.setData({
currDeviceID: array[ret.detail.value]
})
},
searchBleEvent: function(ret){
var ssid = this.data.ssid;
var pass = this.data.pass;
console.log(ssid, pass);
if (util.isEmpty(ssid) || util.isEmpty(pass)) {
util.toastError('请输入WiFi名称及密码');
return;
}
this.initBLE();
},
bleConfigEvent: function (ret) {
var deviceID = this.data.currDeviceID;
console.log("选中:" + deviceID);
if (util.isEmpty(deviceID) || deviceID == "请选择..."){
util.toastError("请先搜索设备");
return ;
}
var device = deviceID.split('[');
if(device.length <= 1){
util.toastError("请先搜索设备");
return ;
}
var id = device[device.length - 1].replace("]", "");
console.log(id);
util.toastError("连接" + id);
this.createBLE(id);
}, initBLE: function() {
this.printLog("启动蓝牙适配器, 蓝牙初始化")
var that = this;
wx.openBluetoothAdapter({
success: function(res) {
console.log(res);
that.findBLE();
},
fail: function(res) {
util.toastError('请先打开蓝牙');
}
})
},
findBLE: function() {
this.printLog("打开蓝牙成功.")
var that = this
wx.startBluetoothDevicesDiscovery({
allowDuplicatesKey: false,
interval: 0,
success: function(res) {
wx.showLoading({
title: '正在搜索设备',
})
console.log(res);
delayTimer = setInterval(function(){
that.discoveryBLE() //3.0 //这里的discovery需要多次调用
}, 1000);
setTimeout(function () {
if (isFound) {
return;
} else {
wx.hideLoading();
console.log("搜索设备超时");
wx.stopBluetoothDevicesDiscovery({
success: function (res) {
console.log('连接蓝牙成功之后关闭蓝牙搜索');
}
})
clearInterval(delayTimer)
wx.showModal({
title: '搜索设备超时',
content: '请检查蓝牙设备是否正常工作,Android手机请打开GPS定位.',
showCancel: false
})
util.toastError("搜索设备超时,请打开GPS定位,再搜索")
return
}
}, 15000);
},
fail: function(res) {
that.printLog("蓝牙设备服务发现失败: " + res.errMsg);
}
})
},
discoveryBLE: function() {
var that = this
wx.getBluetoothDevices({
success: function(res) {
var list = res.devices;
console.log(list);
if(list.length <= 0){
return ;
}
var devices = [];
for (var i = 0; i < list.length; i++) {   
//that.data.inputValue:表示的是需要连接的蓝牙设备ID,
//简单点来说就是我想要连接这个蓝牙设备,
//所以我去遍历我搜索到的蓝牙设备中是否有这个ID
var name = list[i].name || list[i].localName;
if(util.isEmpty(name)){
continue;
}
if(name.indexOf('JL') >= 0 && list[i].RSSI != 0){
console.log(list[i]);
devices.push(list[i]);
}
}
console.log('总共有' + devices.length + "个设备需要设置")
if (devices.length <= 0) {
return;
}
that.connectBLE(devices);
},
fail: function() {
util.toastError('搜索蓝牙设备失败');
}
})
},
connectBLE: function(devices){
this.printLog('总共有' + devices.length + "个设备需要设置")
var that = this;
wx.hideLoading();
isFound = true;
clearInterval(delayTimer);
wx.stopBluetoothDevicesDiscovery({
success: function (res) {
that.printLog('连接蓝牙成功之后关闭蓝牙搜索');
}
})
//两个的时候需要选择
var list = [];
for (var i = 0; i < devices.length; i++) {
var name = devices[i].name || devices[i].localName;
list.push(name + "[" + devices[i].deviceId + "]")
}
this.setData({
deviceArray: list
})
//默认选择
this.setData({
currDeviceID: list[0]
})
}, createBLE: function(deviceId){
this.printLog("连接: [" + deviceId+"]");
var that = this;
this.closeBLE(deviceId, function(res){
console.log("预先关闭,再打开");
setTimeout(function(){
wx.createBLEConnection({
deviceId: deviceId,
success: function (res) {
that.printLog("设备连接成功");
that.getBLEServiceId(deviceId);
},
fail: function (res) {
that.printLog("设备连接失败" + res.errMsg);
}
})
}, 2000)
});
},
//获取服务UUID
getBLEServiceId: function(deviceId){
this.printLog("获取设备[" + deviceId + "]服务列表")
var that = this;
wx.getBLEDeviceServices({
deviceId: deviceId,
success: function(res) {
console.log(res);
var services = res.services;
if (services.length <= 0){
that.printLog("未找到主服务列表")
return;
}
that.printLog('找到设备服务列表个数: ' + services.length);
if (services.length == 1){
var service = services[0];
that.printLog("服务UUID:["+service.uuid+"] Primary:" + service.isPrimary);
that.getBLECharactedId(deviceId, service.uuid);
}else{ //多个主服务
//TODO
}
},
fail: function(res){
that.printLog("获取设备服务列表失败" + res.errMsg);
}
})
},
getBLECharactedId: function(deviceId, serviceId){
this.printLog("获取设备特征值")
var that = this;
wx.getBLEDeviceCharacteristics({
deviceId: deviceId,
serviceId: serviceId,
success: function(res) {
console.log(res);
//这里会获取到两个特征值,一个用来写,一个用来读
var chars = res.characteristics;
if(chars.length <= 0){
that.printLog("未找到设备特征值")
return ;
}
that.printLog("找到设备特征值个数:" + chars.length);
if(chars.length == 2){
for(var i=0; i<chars.length; i++){
var char = chars[i];
that.printLog("特征值[" + char.uuid + "]")
var prop = char.properties;
if(prop.notify == true){
that.printLog("该特征值属性: Notify");
that.recvBLECharacterNotice(deviceId, serviceId, char.uuid);
}else if(prop.write == true){
that.printLog("该特征值属性: Write");
that.sendBLECharacterNotice(deviceId, serviceId, char.uuid);
}else{
that.printLog("该特征值属性: 其他");
}
}
}else{
//TODO
}
},
fail: function(res){
that.printLog("获取设备特征值失败")
}
})
},
recvBLECharacterNotice: function(deviceId, serviceId, charId){
//接收设置是否成功
this.printLog("注册Notice 回调函数");
var that = this;
wx.notifyBLECharacteristicValueChange({
deviceId: deviceId,
serviceId: serviceId,
characteristicId: charId,
state: true, //启用Notify功能
success: function(res) {
wx.onBLECharacteristicValueChange(function(res){
console.log(res);
that.printLog("收到Notify数据: " + that.ab2hex(res.value));
//关闭蓝牙
wx.showModal({
title: '配网成功',
content: that.ab2hex(res.value),
showCancel: false
})
});
},
fail: function(res){
console.log(res);
that.printLog("特征值Notice 接收数据失败: " + res.errMsg);
}
})
},
sendBLECharacterNotice: function (deviceId, serviceId, charId){
//发送ssid/pass
this.printLog("延时1秒后,发送SSID/PASS");
var that = this;
var cell = {
"ssid": this.data.ssid,
"pass": this.data.pass
}
var buffer = this.string2buffer(JSON.stringify(cell));
setTimeout(function(){
wx.writeBLECharacteristicValue({
deviceId: deviceId,
serviceId: serviceId,
characteristicId: charId,
value: buffer,
success: function(res) {
that.printLog("发送SSID/PASS 成功");
},
fail: function(res){
console.log(res);
that.printLog("发送失败." + res.errMsg);
},
complete: function(){ }
}) }, 1000);
}, closeBLE: function(deviceId, callback){
var that = this;
wx.closeBLEConnection({
deviceId: deviceId,
success: function(res) {
that.printLog("断开设备[" + deviceId + "]成功.");
console.log(res)
},
fail: function(res){
that.printLog("断开设备成功.");
},
complete: callback
})
}, printLog: function(msg){
var logs = this.data.logs;
logs.push(msg);
this.setData({ logs: logs })
},
/**
* 将字符串转换成ArrayBufer
*/
string2buffer(str) {
if (!str) return;
var val = "";
for (var i = 0; i < str.length; i++) {
val += str.charCodeAt(i).toString(16);
}
console.log(val);
str = val;
val = "";
let length = str.length;
let index = 0;
let array = []
while (index < length) {
array.push(str.substring(index, index + 2));
index = index + 2;
}
val = array.join(",");
// 将16进制转化为ArrayBuffer
return new Uint8Array(val.match(/[\da-f]{2}/gi).map(function (h) {
return parseInt(h, 16)
})).buffer
},
/**
* 将ArrayBuffer转换成字符串
*/
ab2hex(buffer) {
var hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function (bit) {
return ('00' + bit.toString(16)).slice(-2)
}
)
return hexArr.join('');
},
inputSSID: function(res) {
var ssid = res.detail.value;
this.setData({
ssid: ssid
})
},
inputPASS: function(res) {
var pass = res.detail.value;
this.setData({
pass: pass
})
} })

//补充util.js

 const formatTime = date => {
const year = date.getFullYear()
const month = date.getMonth() + 1
const day = date.getDate()
const hour = date.getHours()
const minute = date.getMinutes()
const second = date.getSeconds() return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':')
} const formatNumber = n => {
n = n.toString()
return n[1] ? n : '0' + n
} const isEmpty = function(str){
if(str == null || str == undefined || str == ""){
return true;
}
return false;
} const randomWord = function(range){
var str = "",
arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
// 随机产生
for (var i = 0; i < range; i++) {
var pos = Math.round(Math.random() * (arr.length - 1));
str += arr[pos];
}
return str;
} const toastServerError = function(){
wx.showToast({
title: '服务器异常,请稍后重试!',
icon: 'none',
duration: 1200,
mask: true
})
}
const toastError = function(info){
wx.showToast({
title: info,
icon: 'none',
duration: 1200,
mask: true
})
} module.exports = {
formatTime: formatTime,
isEmpty: isEmpty,
toastServerError: toastServerError,
toastError: toastError,
randomWord: randomWord
}

//补充分包代码

   /* 统一发送数据,带分包 */
sendBLEData: function (deviceId, serviceId, charId, array){
var that = this;
if(array.length <= 0){
that.printLog("发送SSID/PASS 完成");
return;
}
var list = array.splice(0, 20);
var buffer = new Uint8Array(list).buffer; wx.writeBLECharacteristicValue({
deviceId: deviceId,
serviceId: serviceId,
characteristicId: charId,
value: buffer,
success: function (res) {
that.printLog("发送SSID/PASS 分包发送");
that.sendBLEData(deviceId, serviceId, charId, array);
},
fail: function (res) {
console.log(res);
that.printLog("发送失败." + res.errMsg);
},
complete: function () { }
})
},

4. 运行时截图

  

工具下载地址:

  https://files.cnblogs.com/files/wunaozai/sscom5.13.1.zip

  https://files.cnblogs.com/files/wunaozai/CH341SER_64bit.zip

源代码下载 :

  https://files.cnblogs.com/files/wunaozai/bluetoothconfig.rar

参考资料:

  https://www.cnblogs.com/guhonghao/p/9947144.html

本文地址:

  https://www.cnblogs.com/wunaozai/p/11512874.html

微信小程序开发-蓝牙功能开发的更多相关文章

  1. 微信小程序调用蓝牙功能控制车位锁

    第一次学用微信小程序,项目需要,被逼着研究了一下,功能是调用微信小程序的蓝牙功能,连接上智能车位锁,控制升降,大概步骤及调用的小程序接口API如下: 1.打开蓝牙模块 wx.openBluetooth ...

  2. 微信小程序之蓝牙开发(详细读数据、写数据、附源码)

    本文将详细介绍微信小程序的蓝牙开发流程(附源码)准备:微信只支持低功耗蓝牙也就是蓝牙4.0,普通的蓝牙模块是用不了的,一定要注意. 蓝牙可以连TTL接到电脑上,再用XCOM调试 一开始定义的变量 va ...

  3. 微信小程序购物商城系统开发系列-工具篇

    微信小程序开放公测以来,一夜之间在各种技术社区中就火起来啦.对于它 估计大家都不陌生了,对于它未来的价值就不再赘述,简单一句话:可以把小程序简单理解为一个新的操作系统.新的生态,未来大部分应用场景都将 ...

  4. 微信小程序购物商城系统开发系列

    微信小程序购物商城系统开发系列 微信小程序开放公测以来,一夜之间在各种技术社区中就火起来啦.对于它 估计大家都不陌生了,对于它未来的价值就不再赘述,简单一句话:可以把小程序简单理解为一个新的操作系统. ...

  5. 从微信小程序到鸿蒙js开发【12】——storage缓存&自动登录

    鸿蒙入门指南,小白速来!从萌新到高手,怎样快速掌握鸿蒙开发?[课程入口] 正文: 在应用开发时,我们常需要将一些数据缓存到本地,以提升用户体验.比如在一个电商的app中,如果希望用户登录成功后,下次打 ...

  6. 从微信小程序到鸿蒙js开发【13】——list加载更多&回到顶部

    鸿蒙入门指南,小白速来!从萌新到高手,怎样快速掌握鸿蒙开发?[课程入口] 目录: 1.list加载更多 2.list回到顶部 3.<从微信小程序到鸿蒙js开发>系列文章合集 1.list加 ...

  7. 微信小程序版博客——开发汇总总结(附源码)

    花了点时间陆陆续续,拼拼凑凑将我的小程序版博客搭建完了,这里做个简单的分享和总结. 整体效果 对于博客来说功能页面不是很多,且有些限制于后端服务(基于ghost博客提供的服务),相关样式可以参考截图或 ...

  8. 微信小程序购物商城系统开发系列-目录结构

    上一篇我们简单介绍了一下微信小程序的IDE(微信小程序购物商城系统开发系列-工具篇),相信大家都已经蠢蠢欲试建立一个自己的小程序,去完成一个独立的商城网站. 先别着急我们一步步来,先尝试下写一个自己的 ...

  9. 从微信小程序到鸿蒙js开发【11】——页面路由

    目录: 1.router.push()&wx.navigateTo() 2.router.replace()&wx.redirectTo() 3.router.back()&w ...

随机推荐

  1. 【C#】C#获取本地的内网(局域网)和外网(公网)IP地址的方法

    1.获取本机的IP地址集合: /// <summary> /// 获取本机所有ip地址 /// </summary> /// <param name="netT ...

  2. Python - 部分PEP8规范

    写代码就像写字一样,为什么有的人写的字十分漂亮,而有的人写的字过后连自己都不认识,最主要还是从一开始是否对自己严格要求.从现在开始就当自己是个初学者,把代码写漂亮点.以下截取了部分PEP8代码规范,里 ...

  3. 聊一聊 bootstrap 的轮播图插件

    今天做工作的时候,轻车熟路的做完,又用到了bootstrap的轮播图,觉得有必要安利一下这个插件,如果你需要的轮播图.功能不需要太炫酷,那么bootstrap的插件是你的首要选择. 使用方式 引入js ...

  4. Spring核心(IoC) 入门解读

    什么是IoC容器和Bean? 说到容器,就是用来装东西,那么这里边装的是什么那?是bean对象.那么你会问什么是bean?这就要从很久很久以前说起,当我们创建对象的时候,我们会new一个对象出来,但是 ...

  5. 2019-9-23-win10-uwp-睡眠唤醒

    原文:2019-9-23-win10-uwp-睡眠唤醒 title author date CreateTime categories win10 uwp 睡眠唤醒 lindexi 2019-9-23 ...

  6. FCC---Make Motion More Natural Using a Bezier Curve--- juggling movement

    This challenge animates an element to replicate the movement of a ball being juggled. Prior challeng ...

  7. 从HTML开始

    <html>:做网页,是一种超文本标记语言. 超文本:既有添加文本的能力,还可以添加图片,视频等多媒体元素. 标记:由标签组成.不同的标签有不同的效果.        开始标签,结束标签. ...

  8. 2019年上半年收集到的人工智能Python编程干货文章

    2019年上半年收集到的人工智能Python编程干货文章 一文了解Python深拷贝与浅拷贝问题 Python广度优先查找和深度优先查找(内附python教程分享) Python基础之函数2 (参数的 ...

  9. QNetworkRequest加Authorization头,适应Rest风格的API

    Rest是无状态的.Rest的请求之间不应该有依赖,在调用一个请求前,不需要一定要去提前调用另外一个请求.Rest里面不应该有 session,特别是Rest请求不应该保存信息在sesssion里,以 ...

  10. cluster集群基本概念

    cluster集群种类: 1,LB(Load Balance)负载均衡集群: 弱点:当横向扩展到一定机器后,发现在怎么横向加机器也没有效果的时候,瓶颈就卡在分发的服务器上了,也就是LB机器上了,如何解 ...