Github来源: | 求星星 ✨ | 给个❤️关注,❤️点赞,❤️鼓励一下作者

希望能够帮助更多的小伙伴。加我😚即可交流问题(不是大佬,互相学习,创造良好的学习环境)。以下哪些你不懂呢?

image.png

1.关于es5和es6得继承问题

  • es5的继承是 先创建子类的实例对象,然后将父类的方法添加到this上,Parent.apply(this)
  • es6的继承是 先创建父类的实例对象this,所以先调用父类的super()方法,然后再用子类的构造函数修改this
  • es5的继承是 通过原型或构造函数机制来实现
  • es6通过class关键字定义类,其中有构造方法,类之间通过extends关键字来实现继承
  • 字类必须再constructor方法中调用super方法,否则新建实例报错
  • super关键字表示 父类的实例,即是父类的this对象
  • 在子类构造函数中调用super后,才可使用this关键字,否则报错

2.innerHTML和outHTML的区别

1
2
3
4
5
<div id="dadaqianduan">我喜欢你</div>
document.getElementById("dadaqianduan").innerHTML; // 我喜欢你

document.getElementById("dadaqianduan").outerHTML;
// <div id="dadaqianduan">我喜欢你</div>
  • innerHTML设置或获取于对象起始和结束标签内的HTML
  • outerHTML设置或获取对象以及起内容的HTML形式

3.块级绑定

image.png

3.1var声明与变量提升

  • es6的块级绑定
  • 变量创建的位置取决于你如何声明它
  • var声明与变量提升
  • 使用var关键字声明的变量,不管其实际声明位置在哪个地方,都会被视为声明于所在函数的顶部,如果声明不在任意函数体内,则视为是在全局作用域的顶部(变量提升)

示例:

1
2
3
4
5
6
7
8
9
10
function fun(value) {
if(value) {
var da = "掘金魔王哪吒";
return da;
} esle {
// da 在此处可访问,值为undefined
return null
}
// da 在此处可访问,值为undefined
}

你如果以为value的值为true时,变量da才会被创建,那就错了,实际上da无论如何都会被创建,如下代码所示:

1
2
3
4
5
6
7
8
9
function fun(value) {
var da;
if(value) {
da = '魔王哪吒';
return da;
} else {
return null;
}
}
  • da变量的声明被提升到了顶部,而初始化工作则保留在原处
  • 上述代码表示else分支内da变量也是可访问的,只不过是它的值会是undefined,因为它并没有初始化呀

es6引入了块级作用域,让变量的声明周期更加可以控制

3.2块级声明

  • 块级作用域(又称为词法作用域)
  • 块级声明,就是让所声明的变量在指定块的作用域外无法被访问

创建:

块级作用域:

  1. 在一个函数的内部
  2. 在一个代码块内部

let声明

在项目中常用let来代替var进行变量声明(let声明会将变量的作用域限制在当前代码块中)

  • 如果你不需要让变量在整个代码块内部使用,就使用let声明
  • 如果你使用let声明并不会被提升到当前代码块的顶部,如果你还要动手将let声明放置到顶部,让变量在整个代码块内部使用,你还是使用var声明吧~
1
2
3
4
5
6
7
8
9
10
function fun(value) {
if(value) {
let da = "掘金魔王哪吒";
return da;
}else{
// da 在此处不可用
return null;
}
// da 在此处不可用
}

如果value为false时,该变量时永远都不会被声明并初始化的哦~

如下:不可以重复声明的哟~

  • 如果一个标识符在代码块中已经被定义了,那么在此代码块内部使用同一标识符进行let声明,就会导致错误的哟~
1
2
3
4
var da = '魔王哪吒';

// 语法错误
let da = '魔王哪吒好帅';

image.png

有图有真相

记住:let不能在同一作用域内重复声明一个已有标识符,注意时同一作用域内,如果时在嵌套的作用域内使用let声明一个同名的新变量,就不会抛出错误,我只说同一作用域内会报错,不在同一作用域内就不会报错了哟~

1
2
3
4
5
6
var da = 12;

// 不会抛出错误
if (true) {
let da = 123;
}

image.png

常量的声明

  • 使用const声明的变量会被认为时常量constant,表示它们的值被设置完成后就不能再被改变了

所以啊,所有的const声明的变量都需要(在声明时)进行初始化:

1
2
3
4
5
// 有效的常量
const da = 12;

// 语法错误:未进行初始化
const dada;

image.png

  • 记住:常量声明与let声明是一样的,都是块级声明(上述)见上

示例:

1
2
3
4
if(value) {
const da = '掘金魔王哪吒'
}
// da 在此处无法访问

无论是在严格模式还是非严格模式下:对之前用const声明的常量进行赋值会抛出错误

1
2
3
const da = '掘金:魔王哪吒,好帅'

da = '是很帅的,魔王哪吒' // 抛出错误

const声明常量,如果使用const声明对象如下描述:

const声明 会阻止对于 变量绑定 与 变量自身值的修改,这意味着 const 声明并不会阻止对变量成员的修改。

阻止:变量绑定,变量自身值的修改

不阻止:变量成员的修改

示例:

1
2
3
4
5
6
7
8
9
10
11
12
// dada 在初始化时绑定了带有一个属性的对象
const dada = {
string: 'dadaqianduan.cn亿万少女的梦'
};

// 正常
dada.string = '掘金魔王哪吒:亿万少女的梦';

// 抛出错误
dada = {
string: '魔王哪吒,你在做梦呢'
};

image.png

  • const阻止的是对于变量绑定的修改
  • const不会阻止对成员值的修改

暂时性死区

什么是暂时性死区呢?就是之前说过,使用let或者是const声明的变量,在没有达到声明处之前是无法访问的,如果访问会导致引用错误。就算是在安全情况下,也是一样。

如下:

1
2
3
4
if(value) {
console.log(typeof da); // 引用错误
let da = '达哥好帅';
}

image.png

当js引擎检视代码块并发现变量声明时,它会在面对 var 的情况下将声明提升到 函数或全局作用域的顶部,而面对 let 或 const 时会将声明放在暂时性死区内。

任何在暂 时性死区内访问变量的企图都会导致“运行时”错误(runtime error)。只有执行到变量的声明 语句时,该变量才会从暂时性死区内被移除并可以安全使用。

示例:

那么在变量被定义的代码块之外对该变量使用typeof,尽管其结果可能并非预期:

1
2
3
4
5
console.log(typeof da); // 'undefined'

if(true) {
let da = 'dadaqianduan';
}

image.png

3.3循环中的块级绑定

循环内的函数

1
2
3
4
5
6
// 因为 var 声明导致了变量提升。
for (var i = 0; i < 10; i++) {
...
}
// i 在此处仍然可被访问
console.log(i); // 10
1
2
3
4
5
for (let i = 0; i < 10; i++) { 
...
}
// i 在此处不可访问,抛出错误
console.log(i);
  • 立即调用函数表达式:
1
2
3
4
5
for(var i=1;i<=5;i++) {
setTimeout(() => {
console.log(i)
}, i*1000)
}

会打印出6个6,原因:for循环中用var来申明变量i,此时var存在变量提升问题,并且6次循环中全都共用一个变量,所以当setTimeout中的延迟函数开始执行时,循环已经结束,此时i=6,所以会打印出6个6。

变量i在循环的每次迭代中都被共享了,表示循环内创建的那些函数都拥有对于同一变量的引用。

利用闭包可以解决这个问题:

1
2
3
4
5
6
7
for(var i=1;i<=5;i++) {
(function(j){
setTimeout(() => {
console.log(j)
}, j* 1000)
})(i)
}
  • 在循环内使用立即调用函数表达式(IIFEs),以便在每次迭代中 强制创建变量的一个新副本

  • 使用 setTimeout 的第三个参数

1
2
3
4
5
for(var i=1;i<=5;i++) {
setTimeout((j) => {
console.log(j)
}, i* 1000, i)
}
  • 使用 let 定义 i
1
2
3
4
5
for(let i=1;i<=5;i++) {
setTimeout(() => {
console.log(i)
}, i*1000)
}

循环内的let声明

  • 在每次迭代中,都会创建一个新的同名变量并对其进行初始化。
  • 在循环中let声明每次都创建了一个新的i变量,因此在循环内部创建的函数获得了各自的i副本
  • 每个i副本的值都在每次循环迭代声明变量的时候被确定

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var arr = [],
object = {
a: 1,
b: 2,
c: 3
};
for(let key in object) {
arr.push(function(){
console.log(key);
});
}

arr.forEach(function(func){
func(); // a,b,c
});

image.png

  • 每次循环,一个新的key变量绑定就被创建,每个函数都能够拥有它自身的key变量副本,结果每个函数都输出了一个不同的值

循环内的常量声明

示例:

1
2
// 在一次迭代后抛出错误
for(const i = 0; i < 10; i++){..}

for-in 或 for-of

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var arr = [],
object = {
a: 1,
b: 2,
c: 3
};
// 不会报错
for(const key in object) {
arr.push(function(){
console.log(key);
});
}

arr.forEach(function(func){
func(); // a,b,c
});

image.png

注意:使用const声明,不能改变值,上述是 循环为每次迭代创建了一个新的变量绑定,而不是试图去修改已绑定的变量的值。

3.4全局块级绑定

使用var,在全局作用域中,它会创建一个新的全局变量,并成为全局对象的一个属性,可能当你使用var时,需要注意的时,var可能会无意覆盖一个已有的全局属性。使用var声明,定义为全局变量后会立即成为window的一个属性。

如果你在全局作用域上使用let或者时const,会在全局作用域上创建新的绑定,但不会被添加到全局对象上,不能使用let或const来覆盖一个全局变量,你只能用来起到屏蔽效果。

描述:

  • 由于块级绑定存在暂时性死区( TDZ ), 试图在声明位置之前访问它就会导致错误。
  • let 和 const能够在 for-in 和 for-of 循环中,每一次迭代时创建一个新的绑定,表示 在循环体内创建的函数可以使用 当前迭代所绑定的循环变量值。
  • 不向使用var 那样,统一使用循环结束时的变量值。
  • 在for循环中 使用 let 声明 成立,使用const声明会导致错误哦。

4.innerText和innerContent的区别

  1. textContent 会获取style="display:none中的文本,而innerText不会
  2. textContent会获取style标签里面的文本,而innerText不会
  3. textContent不会理会html格式,直接输出不换行的文本
  4. innerText会根据标签里面的元素独立一行
  5. innerText会根据标签里面的元素独立一行
  6. innerTextIE的兼容性较好
  7. textContent虽然作为标准方法但是只支持IE8+以上的浏览器

5.el.childrenel.childNodes的区别

  1. el.children,返回指定节点的所有element子节点,即返回节点元素
  2. el.childNodes,返回指定节点的所有子节点,包括节点元素和文本元素

6.JavaScript语法

image.png

  1. 方法:将JavaScript代码放到文档<head>标签中的<script标签之间
  2. 方法:在文档的<head>部分放一个<script>标签,并把它的src属性指向该文件
  3. 方法:把<script>标签放到HTML文档的最后,</body>标签之前(这样能使浏览器更快加载页面)
  4. JavaScript变量名允许包含字母,数字,美元符号和下划线(但第一个字符不允许是数字)
  5. 通常驼峰格式是函数名,方法名和对象属性名命名的首选格式。
  6. JavaScript中几种数据类型:字符串,数值,布尔值,数组,对象。
  7. 由浏览器提供的预定义对象被称为宿主对象。
  8. typeof操作符可以告诉我们它的操作数是一个字符串,数值,函数,布尔值还是对象。
  • 字符串:字符串由零个或多个字符构成。字符包括(但不限于)字母,数字,标点符号和空格。
  • 如果字符串包含双引号,就把整个字符串放在单引号里;如果字符串包含单引号,就把整个字符串放在双引号里。
  • 用对象来代替传统数组的做法意味可以通过元素的名字而不是下标数字来引用它们。

变量作用域:分全局,局部。

  1. 全局变量,可以在脚本中的任何位置被引用。一旦你在某个脚本里声明了一个全局变量,就可以从这个脚本中的任何位置,包括函数内部,引用它。全局变量的作用域是整个脚本。
  2. 局部变量,只存在于声明它的那个函数的内部,在那个函数的外部是无法引用它的。局部变量的作用域仅限于某个特定的函数。

7.DOM

  1. getElementById
  2. getElementsByTagName
  3. getElementsByClassName
  4. getAttribute
  5. setAttribute

JavaScript语言里的对象

  1. 用户定义对象,由程序员自己创建的对象
  2. 内建对象,内建在JavaScript语言里的对象
  3. 宿主对象,由浏览器提供的对象
  • window对象,浏览器窗口本身,整个对象的属性和方法通常称为BOM,浏览器对象模型。
  • 节点:元素节点,文本节点,属性节点

获取元素节点的方法:通过元素ID,通过标签名,通过类名字

  1. getElementById,这个方法将返回一个与那个给定id属性值的元素节点对应的对象document.getElementById(id)
  2. getElementsByTagName,这个方法返回一个对象数组,每个对象分别对应着文档里有着给定标签的一个元素。element.getElementsByTagName(tag)
  3. getElementsByClassName,这个方法能够通过Class属性中的类名来访问元素

获取和数值属性:

  1. getAttribute方法就是用来获取属性-object.getAttribute(attribute)
  2. setAttribute方法可以用来更改属性节点的值-object.setAttribute(attribute,value)

示例:

1
2
3
4
var node = document.getElementsByTagName("p");
for(let i=0, i<node.length; i++){
console.log(node[i].getAttribute("title"));
}
1
2
var node = document.getElementsByTagName("p");
node.setAttribute("title","dadaqianduan.cn");

8.a标签

  • target属性决定
  • _blank在新窗口中打开被链接文档
  • _self默认,在相同的框架中打开被链接文档

9.函数

image.png

带有参数默认值的函数:

1
2
3
4
5
// es5
function Fun(da, da2) {
da = da || 'dadaqianduan';
da2 = da2 || '1024bibi.com';
}

升级改造,typeof来检测参数的类型:

1
2
3
function fun(da) {
da = (typeof da !== 'undefined") ? da : 'dadaqianduan';
}
1
2
3
// es6
funtion da(da='掘金魔王哪吒', callback = function(){}) {
}

参数默认值如何影响arguments对象

  • arguments对象会在使用参数默认值时会有所不同
  • 在非严格模式下,arguments对象总是会被更新以反映出具名参数的变化
  • es5严格模式下,不再反映出具名参数的变化

如下所示:

1
2
3
4
5
6
function fn(a) {
console.log(a === arguments[0]);
a = '达达前端';
console.log(a === arguments[0]);
}
fn('dadaqianduan');

image.png

1
2
3
4
5
6
7
function fn(a) {
"use strict";
console.log(a === arguments[0]);
a = '达达前端';
console.log(a === arguments[0]);
}
fn('dadaqianduan');

image.png

参数默认值表达式

示例:

1
2
3
4
5
6
7
8
function getValue() {
return 1;
}
function add(a, b = getValue()) {
return a + b;
}
console.log(add(1,1)); // 2
console.log(add(2); // 3
1
2
3
4
5
6
7
8
9
10
let value = 5;
function getValue() {
return value++;
}
function add(a,b=getValue()) {
return a+b;
}
console.log(add(1,1)); // 2
console.log(add(1)); // 6
console.log(add(1)); // 7
1
2
3
4
5
function add(a,b=a) {
return a + b;
}
console.log(add(1,1));
console.log(add(1));
1
2
3
4
5
6
7
8
function getValue(value) {
return value + 5;
}
function add(a, b = getValue(a)) {
return a + b;
}
console.log(add(1,1)); // 2
console.log(add(1)); // 7
1
2
3
4
5
function add(a = b, b) {
return a + b;
}
console.log(add(1,1)); // 2
console.log(add(undefined,1)); // 抛出错误

参数默认值的暂时性死区

  • 函数每个参数都会创建一个新的标识符绑定,它在初始化之前不允许被访问,否则会抛出错误。

es5中的不具名参数

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function da(object) {
let result = Object.create(null);
for(let i = 1, len = arguments.length; i<len; i++) {
result[arguments[i]] = object[arguments[i]];
}
return result;
}
let book = {
a: '1',
b: '2',
c: '3'
};
let da1 = da(book, 'a', 'b');
console.log(da1.a); // 1
console.log(da2.b); // 2

剩余参数

剩余参数由三个点(…)与一个紧跟着的具名参数指定。

1
2
3
4
5
6
7
function fn(object, ...keys) {
let result = Object.reate(null);
for(let i = 0, len = keys.length; i<len; i++) {
result[key[i]] = object[keys[i]];
}
return result;
}
  • 剩余参数:函数只能有一个剩余参数,并且它必须被放在最后。
  • 剩余参数:不能在对象字面量的setter属性中使用
1
2
3
4
5
6
let object = {
// 语法错误:不能在setter中使用剩余参数
set name(...value) {
// 一些操作
}
};
  • arguments对象在函数被调用时反映了传入的参数
  • arguments对象总能正确反映被传入函数的参数
1
2
3
4
5
6
7
8
9
10
11
function fn(...args) {
console.log(args.length);
console.log(arguments.length);
console.log(args[0], arguments[0]);
console.log(args[1], arguments[1]);
}
fn("a","b");
// 2
// 2
// a a
// b b

函数构造器的增强能力(es6默认参数以及剩余参数)

1
2
3
4
5
6
var add = new Function("a", "b", "return a + b");
console.log(add(1,1)); // 2

var da = new Function("a", "b=a", "return a+b");
console.log(da(1,1)); // 2
console.log(da(1)); // 2

扩展运算符

示例:

1
2
3
4
// es5
let arr = [1,2,3,4,5];

console.log(Math.max.apply(Math, arr)); // 5
1
2
3
4
5
6
// es6
let arr = [1,2,3,4,5];
console.log(Math.max(...values)); // 5

let arr2 = [-2,-3,-4];
console.log(Math.max(...arr2, 0)); // 0

es6函数名称属性

示例:

1
2
3
4
5
function da() {}
console.log(da.name); // da

var dada = function() {}
console.log(dada.name); // dada

image.png

名称属性的特殊情况

image.png

明确函数的双重用途:当使用new时,函数内部的this是一个新对象,并作为函数的返回值。

当函数未使用 new 进行调用时, call 方法会被执行,运行的是代码中显示的函数体。

当函数使用 new 进行调用时, Construct 方法则会被执行,负责创建一个被称为新目标的新的对象,并且使用该新目标作为 this 去执行函数体。

es6引入new.target元属性

1
2
3
4
5
6
7
8
9
function Fun(value) {
if(this instanceof Fun) {
this.value = value;
} else {
throw new Error("dadaqianduan");
}
}
var da = new Fun("dada");
var dadaqianduan = Fun("123"); // 报错
1
2
3
4
5
6
7
8
9
function Fun(value) {
if(this instanceof Fun) {
this.value = value;
} else {
throw new Error("dadaqianduan");
}
}
var da = new Fun("dada");
var dadaqianduan = Fun.call(da, "dadaqianduan"); // ok
1
2
3
4
5
6
7
8
9
10
function Fun(value) {
// 是否被定义
if(typeof new.target !== "undefined") {
this.value = value;
}else{
throw new Error("dadaqianduan.cn");
}
}
var da = new Fun("jeskson");
var da2 = Fun.call(da, 'jeskson'); // 报错
1
2
3
4
5
6
7
8
9
10
11
12
function Fun(value) {
if(new.target === Fun) {
this.value = value;
}else{
throw new Error("dadaqianduan.cn");
}
}
function Da(value) {
Fun.call(this, name);
}
var person = new Fun("dadaqianduan.cn");
var person1 = new Da("dadaqianduan.cn"); // 报错

10.uni-app与蓝牙设备的传输

  1. 初始化蓝牙模块
  2. 搜索蓝牙设备
  3. 连接蓝牙设备
  4. 选择设备服务
  5. 获取服务的特征值
  6. 订阅特征值
  7. 发送数据
  8. 发送成功
  • 初 始 化 蓝 牙 uni.openBluetoothAdapter(OBJECT)

  • 开 始 搜 索 蓝 牙 设 备 uni.startBluetoothDevicesDiscovery(OBJECT)

  • 发 现 外 围 设 备 uni.onBluetoothDeviceFound(CALLBACK)

  • 停 止 搜 寻 附 近 的 蓝 牙 外 围 设 备 uni.stopBluetoothDevicesDiscovery(OBJECT)

  • 连 接 低 功 耗 蓝 牙 设 备 uni.createBLEConnection(OBJECT)

  • 获 取 蓝 牙 设 备 所 有 服 务 uni.getBLEDeviceServices(OBJECT)

  • 获 取 蓝 牙 特 征 uni.getBLEDeviceCharacteristics(OBJECT)

  • 启用蓝牙设备特征值变化时的 notify 功能

uni.notifyBLECharacteristicValueChange(OBJECT)

  • 监听低功耗蓝牙设备的特征值变化

uni.onBLECharacteristicValueChange(CALLBACK)

初始化蓝牙(检测一下手机蓝牙是否打开)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
uni.openBluetoothAdapter({
success:(res) => {
// 已打开
uni.getBluetoothAdapterState({ // 蓝牙的匹配状态
success: (res1) => {
console.log(res1, "本机设备的蓝牙已打开")
// 开始搜索蓝牙设备
this.startBluetoothDeviceDiscovery()
},
fail:(error)=>{
uni.showToast({icon:'none',title:'查看手机蓝牙是否打开'
}
});
},
fail: (err) => {
// 未打开
uni.showToast({icon:'none',title:'查看手机蓝牙是否打开'});
}
})

开始搜索蓝牙设备

1
2
3
4
5
6
7
8
9
10
11
12
startBluetoothDeviceDiscovery() {
uni.startBluetoothDevicesDiscovery({
success:(res) => {
console.log('startBluetoothDevicesDiscovery success', res)
// 发现设备
this.onBluetoothDeviceFound()
},
fail:(err) => {
console.log(err, '错误信息');
}
})
}

发现设备,获取设备id

1
2
3
4
5
6
7
8
onBluetoothDeviceFound() {
uni.onBluetoothDeviceFound((res) => {
// 搜索到的设备存储起来
if(this.list.indexOf(res.devices[0].deviceId) === -1){
this.list.push(res.devices[0].deviceId)
}
})
}

点击选择自己需要连接的设备,连接蓝牙设备

1
2
3
4
5
6
7
8
9
10
11
12
13
14
createBLEConnection(deviceId) {
this.deviceId = deviceId
// 连接蓝牙
uni.createBLEConnection({
deviceId: this.deviceId,
success:(res) =>{
this.stopBluetoothDeviceDiscovery()
console.log("蓝牙连接成功")
},
fail:(res) =>{
console.log('蓝牙连接失败',res)
}
})
}

连接成功后,要停止搜索设备

1
2
3
4
5
6
7
8
9
10
11
stopBluetoothDevicesDiscovery(){
uni.stopBluetoothDevicesDiscovery({
success: e=> {
this.loading = false
console.log('停止搜索蓝牙设备:' + e.errMsg);
},
fail: e=> {
console.log('停止搜索蓝牙设备失败,错误码:' + e.errCode);
}
});
}

获取蓝牙设备所有服务,setTimeout等待一秒种再去获取,直接获取我们可能出现获取不到的情况

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//获取蓝牙特征
getBLEDeviceCharacteristics(){
console.log("进入特征");
setTimeout(()=>{
uni.getBLEDeviceCharacteristics({
// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
deviceId:this.deviceId,
// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
serviceId:this.serviceId,
success:(res)=>{
console.log(res,'特征getBLEDeviceCharacteristics')
this.characteristics = res.characteristics
console.log(this.characteristics)
//循环所有的uuid

res.characteristics.forEach((item)=>{
if(item.uuid.indexOf("LD") != -1){
console.log('characteristicId:', item.uuid)
//利用传参的形势传给下面的notify,这里的uuid如果都需要用到,就不用做判断了,建议使用setTimeout进行间隔性的调用此方法
this.notifyBLECharacteristicValueChange(item.uuid)
}
})

},
fail:(res)=>{
console.log(res)
}
})
},1000)
},

启用蓝牙设备特征值变化时的 notify 功能

  • 启动notify功能,才能知道我们当前蓝牙的读写状态,
1
2
3
4
5
6
“properties”: {
“read”: true, //读
“write”: true, //写
“notify”: true, //广播
“indicate”: false
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 启用 notify 功能
notifyBLECharacteristicValueChange(characteristicId){
console.log(characteristicId,'characteristicId')
uni.notifyBLECharacteristicValueChange({
state: true, // 启用 notify 功能
deviceId:this.deviceId,
serviceId:this.serviceId,
characteristicId:characteristicId,
success:(res)=> {
console.log(res)
// console.log(this.characteristicId)
console.log('notifyBLECharacteristicValueChange success', res.errMsg)

},
fail:(res)=> {
console.log('notifyBLECharacteristicValueChange success2', res.errMsg)
}
})
},

等待:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//获取蓝牙的所有服务
getBLEDeviceServices(){
setTimeout(()=>{
uni.getBLEDeviceServices({
deviceId:this.deviceId,
success:(res)=>{
console.log('device services:', res)
res.services.forEach((item)=>{
if(item.uuid.indexOf("LD")!=-1){
// this.serviceId = item.uuid;
//存储到状态
this.$store.commit("upserviceId",item.uuid)
console.log(this.serviceId)
// 这里获取回调,读取成功就的值就会在这个地方接收到!!!
uni.onBLECharacteristicValueChange((res)=>{
console.log("监听成功",res)
//res.value是ArrayBuffer类型的,官方给了一个方法转16进制,我们再进行操作
this.shiliu = this.ab2hex(res.value)

})

this.getBLEDeviceCharacteristics()
}
})
}
})
},1000)
}

读取蓝牙设备

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//在页面加载时候初始化蓝牙适配器
uni.openBluetoothAdapter

// 初始化完毕开始搜索
this.startBluetoothDeviceDiscovery()

console.log("开始搜寻智能设备");
uni.startBluetoothDevicesDiscovery
success: res => {
self.onBluetoothDeviceFound();
},

onBluetoothDeviceFound
console.log('开始监听寻找到新设备的事件');

stopBluetoothDevicesDiscovery

uni-app蓝牙:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// 代码
//初始蓝牙模块
this.pDeviceInfo = uni.getStorageSync('deviceInfo');
if(!!this.pDeviceInfo){
this.prevConnected = true;
}

initBluetoothModule(){
//初始蓝牙模块
uni.openBluetoothAdapter({
success:res=> {
this.searchBlueList();
},
fail:err=>{
console.log(err)
}
})
},

searchBlueList(){
//开启蓝牙搜索
uni.startBluetoothDevicesDiscovery({
success:res=> {
setTimeout(()=>{
this.getBlueList();
uni.showToast({
title: '开启成功',
icon: 'success',
duration: 1000
});
},1000);
},
})
},

getBlueList(){
//获取搜索列表
uni.getBluetoothDevices({
success:res=> {
let data = res.devices
let tempList=[];
data.map(device=>{
if(!!device.localName){
tempList.push(device)
}
});
this.deviceNum = tempList.length;
this.deviceList=tempList;
this.listenBluetooth();
}
});
},

listenBluetooth(){
let tempList =this.deviceList;
//监听蓝牙搜索
uni.onBluetoothDeviceFound((res) => {
let flag = false;
res.devices.forEach(device => {
if(!!device.localName){
tempList.push(device)
flag =true;
}
})
if(flag){
this.deviceList=tempList;
this.deviceNum = this.deviceList.length;
}
})
},
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
connetBlue(type,index){
let deviceIndex = index;
let deviceInfo = this.deviceList[deviceIndex];
if(this.prevConnected && type == 1){
deviceInfo = this.pDeviceInfo;
}
let dId = deviceInfo.deviceId;
uni.showLoading({
title: '正在连接...', //提示的内容,
mask: true
});
//连接蓝牙
uni.createBLEConnection({
deviceId: dId,//设备id
success: res=> {
uni.hideLoading();
if(res.errCode == 0){
this.connected = true;
this.connectedName=deviceInfo.name;
uni.setStorageSync('deviceInfo',deviceInfo);
this.deviceId=dId;
uni.showToast({
title: '连接成功',
icon: 'success',
duration: 1000
});
}
uni.stopBluetoothDevicesDiscovery({
success: res => {
console.log('连接蓝牙成功之后关闭蓝牙搜索');
}
})
},
fail:err=>{
uni.showToast({
title: '连接失败!',
icon: 'none',
duration: 2000
});
}
})
},

getBLEDeviceServices(){
//获取服务
uni.showLoading({
title: '正在打印...', //提示的内容,
mask: true
});
let deviceId = this.deviceId;
uni.getBLEDeviceServices({
deviceId,
success: (res) => {
for (let i = 0; i < res.services.length; i++) {
if (res.services[i].isPrimary) {
this.getBLEDeviceCharacteristics(deviceId, res.services[i].uuid);
}
}
},
fail: (res) => {
uni.hideLoading();
console.log("获取蓝牙服务失败:" + JSON.stringify(res))
}
})
},

//获取单个服务的特征值(characteristic)
getBLEDeviceCharacteristics(deviceId, serviceId){
if(!!this.characteristics && !!this.serviceId){
this.PrintStr();
return;
}
uni.getBLEDeviceCharacteristics({
deviceId,
serviceId,
success: (res) => {
uni.hideLoading();
for (let i = 0; i < res.characteristics.length; i++) {
let item = res.characteristics[i];
if (item.properties.write && !this.serviceId) {
this.serviceId = serviceId;
this.characteristics = item.uuid;
this.PrintStr();
}
}
},
fail(res) {
uni.hideLoading();
console.error('获取特征值失败:', res)
}
})
},

closeBluetoothAdapter(){
uni.closeBluetoothAdapter({
success: res => {
console.log('关闭蓝牙适配器');
}
});
},

onUnload() {
this.closeBluetoothAdapter();
}

回看笔者往期高赞文章,也许能收获更多喔!

❤️关注+点赞+收藏+评论+转发❤️

点赞、收藏和评论

我是Jeskson(达达前端),感谢各位人才的:点赞、收藏和评论,我们下期见!(如本文内容有地方讲解有误,欢迎指出☞谢谢,一起学习了)

我们下期见!

文章持续更新,可以微信搜一搜「 程序员哆啦A梦 」第一时间阅读,回复【资料】有我准备的一线大厂资料,本文 https://www.1024bibi.com 已经收录

github收录,欢迎Starhttps://github.com/webVueBlog/WebFamily