点击登录

米环7教程 全坛最详细的开发Zepp OS小程序教程 2023年2月21日更新第二版

Struggle

😱😱😱
🔥创作者
社区会员
米坛社区百万注册纪念勋章 米坛社区五周年纪念勋章 米坛社区四周年纪念勋章 作者大佬
目录
一.JavaScript的基本知识

二.开发小程序

三.Vepp框架的使用

四.手机也能用vscode?


那让我们开始吧

众所周知,小米手环7搭载Zepp OS,Zepp OS的小程序开发语言是JavaScript(简称JS),它的解释器是quick.js
//解释器就是把你写的代码转换为Zepp OS能听懂的代码,加密小程序也就是提前把小程序转换为Zepp OS能听懂的代码
Zepp OS是纯JavaScript的环境,类node(CSS可以使用外挂CSS代替,但没必要,动效照样实现不了)
所以我们要掌握JavaScript的一些基本知识
一.JavaScript的基本知识
1.变量
声明变量的方式有两种,分别是 var ,let
变量就像一个装东西的盒子,里面装东西就叫赋值
其中var的全称叫做variable,意思是变量,可变物,而let是"让"的意思,所以就是让×××=×××
其中var是很老很老的声明变量方式了,它可以重新赋值,用于声明一个函数作用域或全局作用域的变量//看不懂也
let是偏现代的声明变量方式,let语句声明一个块级作用域的局部变量,也可以重新赋值。还有一种和变量相似的,叫做常量,常量只有const,常量不能重新赋值,而const全称是constant,常量,恒量,总之,以后变量用let,常量用const

变量的使用
注意!变量名只能以$,字母,下划线开始,如果变量赋值是大写,使用时是小写,则不是同一个变量,输出结果为undefined
我这里拿Apple健康的做演示
JavaScript:
let step = hmSensor.createSensor(hmSensor.id.STEP);
其中var后面的step,就是变量名,等于号后面的则是将此变量赋值为获取到的系统步数
也可以这样写
JavaScript:
let step;
step = hmSensor.createSensor(hmSensor.id.STEP);
这种是先声明一个变量,再对其进行赋值,但这种比较麻烦,而且当你忘记赋值时获取变量会被输出undefined
而我们后续使用这个变量时,我们可以这样写
JavaScript:
hmUI.createWidget(hmUI.widget.TEXT, {//创建控件
x: 5,//x坐标
y: 10,//y坐标
w: 200,//宽度
h: 70,//长度
color: 0xFFF200,//文本颜色
text_size: 40,//文本大小
text: step.current//将文本输出为先前定义好的变量值,.current是当前值,仅部分更新式变量使用,其它变量请自行去掉
});//结束
当然,我们还可以设置变量为x坐标,y坐标,宽度还有长度
此处参考Battery program
变量:
JavaScript:
const battery = hmSensor.createSensor(hmSensor.id.BATTERY)
控件
JavaScript:
hmUI.createWidget(hmUI.widget.FILL_RECT, {
x: 20,
y: 80,
w: battery.current,
h: 50,
radius: 15,
color: 0x078707,
});
一般变量过多可以全部放开头
2.注释
//是单行注释,/* */是多行注释,可以用来暂时封存代码或者解释某段代码,在团队开发中能提高代码可读性,从而提升开发效率
3.字符串,布尔值
字符串就是单双引号包起来的文字
布尔值是true或false
4.条件语句
(1).switch语句
switch语句简单讲就是分情况匹配相应代码
switch语句的作用一般用于小程序简易语言国际化,如环管和像素鸟都采用了这种方法
JavaScript:
const language = hmSetting.getLanguage();// const 常量
switch(language){// ()是赋值的变量
case 0:// 当输出结果为0,则执行以下代码(0在官方文档里的是中文)
Battery_text = "电量";
break;
case 1:
Battery_text = "電量";
break;
case 2:
Battery_text = "Battery";
break;
default: // 当输出结果不属于以上的任何代码时执行以下代码
Battery_text = "Battery";
}
这段代码可以使小程序语言简易国际化,我们也可以用if语句代替(或者直接用po文件)
(2).if语句
if语句和switch语句差不多,只不过if语句一般用来确定一个范围的值,而switch只能用来返回数值
if语句也有多分支
双分支一般是if (/条件判断/){/执行语句/} else {/反之执行语句/}
多分支一般是if(/条件判断/) {/执行语句/}} else if(/条件判断/) {/执行语句/}}
其中圆括号里填的是条件判断,建议和下面讲到的运算符搭配使用,如果条件判断里没有运算符,则是判断是否有这个变量
具体事例
JavaScript:
if (indexcolortext == undefined) {
indexcolortext = "0x000000";
indexcolorrec = "0xFFFFFF";
} else if (indexcolortext == 1) {
indexcolortext = "0xFFFFFF";
indexcolorrec = "0x000000";
} else if (indexcolortext == 2) {
indexcolortext = "0x000000";
indexcolorrec = "0xFFFFFF";
}
5.break,continue 和 return
前两者可以提前跳出循环
break 语句中止当前循环,switch,并把程序控制流转到紧接着被中止语句后面的语句
continue 并不会终止循环的迭代,而是在 while 循环中,控制流跳转回条件判断,在 for 循环中,控制流跳转到更新语句
return 语句终止函数的执行,并返回一个指定的值给函数调用者
给大家举个简单的例子
JavaScript:
function getRectArea(width, height) {
  if (width > 0 && height > 0) {
    return width * height;
  }
  return 0;
}

console.log(getRectArea(3, 4));

console.log(getRectArea(-3, 4));
那么大家觉得这个输出结果是多少
答案分别是12,0
首先我们看第一行,我定义了一个名为getRectArea的函数,里面的参数是width和height,这个函数里面有一个if语句,用来条件判断
当width和height大于0,那么返回结果是width乘以height,反之输出0,之后打印的语句就无需多讲了,第一个都大于0,所以返回结果是12,第二个-3小于0,所以返回结果是0
6.运算符
(1).算数运算符
JavaScript算数运算符,无非加、减、乘、除、取余、自增,自减运算符
比如
JavaScript:
var a = 10;
var b = 2;
var c = a++;
var d = a--;
var e = ++a;
var f = --a;
var s1 = a + b;
var s2 = a - b;
var s3 = a * b;
var s4 = a / b;
console.log(c);
console.log(d);
console.log(e);
console.log(f);
console.log(s1);
console.log(s2);
console.log(s3);
console.log(s4);
前几个好说,但是cd和ef有什么区别呢
区别就是运行c和d时,得出结果是10和11,而e和f得出来是11和10
这是为什么呢
因为自增或自减运算符,它分为前置和后置,前置就是在变量的
前面写一个“++或--”,后置就是在变量的后面写一个“++或--”
后置的特点是先让变量参与运算,运算结束以后再进行自增
而前置就是a的意思是先让a的值自增一次,a本来是10,经过自增就变成了11,因为前置++的含义是先让变量自增,再放进式子里面运算,所以这个代码的结果就是11
(2).比较运算符
==等于
!=不等于
大于号是大于
<小于
大于号加=是大于或等于
<=小于或等于
(3).逻辑操作符
((1)).逻辑与操作符
用处是确定一个范围
简单写一个
JavaScript:
let battery = hmSensor.createSensor(hmSensor.id.BATTERY);

if (battery.current => 10 && battery.current <= 20) {

hmUI.showToast({text: '电量不足20%'})

}
其中&&就是逻辑与操作符,可以理解为"且"这个字
((2)).逻辑或操作符
用处是有多个条件而且只要有一个符合条件就执行
我们就需要用到逻辑或运算符||,不要以为我打错了啊,它就是两条竖线
((3)).逻辑非操作符
它就是一个!,用处是取反,就是当得到结果是true,转为false,false转为true,如果是在if语句或switch语句中要将条件判断再加一个括号
7.console的多种用途

console.clear()
清空控制台,并输出 console was cleared

console.error()
打印一条错误信息

console.log()
打印内容

console.warn()
打印警告信息
8.循环
(1).for循环
for循环的用处是一遍又一遍地运行相同的代码,并且每次的值都不同
for (表达式1;表达式2;表达式3)
{
语句
}
首先要强调两点:
((1)).表达式1、表达式2和表达式3之间是用分号;隔开的,千万不要写成逗号
((2)).for(表达式1;表达式2;表达式3)的后面千万不要加分号,很多新手都会犯这种错误——会情不自禁地在后面加分号
实践
JavaScript:
for(var i = 0;i<10;i++){
console.log(i);
}
(2).while循环
和for循环差不多
实践
JavaScript:
var i = 0;
while(i<10){
console.log(i);
i++;
}
它和for循环只是在语法上有所不同,其作用和for循环是一样的
9.数组
数组可以生成一个有多个数据的变量
数组有4种定义方式
这里我就采用最常用的直接量
JavaScript:
var arr =
[
"first","second","third"
]
hmUI.showToast({text: arr})
得到的结果就是生成了一个拥有3个元素的数组,数组的名字是arr
或者我们可以先创建一个数组,不往里面放数据
JavaScript:
var arr = new Array();
这个括号里放的是数组的数据数量,不填也可以
然后再给它填入数据
JavaScript:
arr [0] = "first";
arr [1] = "second";
arr [2] = "third";
hmUI.showToast({text: arr});
如果我们需要指定输出的数据,只需这样写
hmUI.showToast({text: arr [0]})
如果我们想用数组创建多个数组可以这么写
JavaScript:
const dataList = [
{ text: '九转大肠', x: 5, y: 10, w: 200, h: 70, color: 0xFFF200, text_size: 40, id: hmUI.widget.TEXT},
{ text: '老马', x: 5, y: 10, w: 200, h: 70, color: 0xFFF200, text_size: 40, id: hmUI.widget.TEXT}
]
hmUI.showToast({text: dataList.text})

10.函数
函数 function 翻译过来是功能
函数有八大要素
(1).函数的定义
函数是一组可以被重复调用的代码语句,它可以大大减少你的代码,函数的格式是这样的
funtion 函数名(参数,可不填){
执行的代码,叫做函数体
}
做个示范
JavaScript:
funtion showToast(){
hmUI.showToast({text: '函数被调用了'});
}
我定义了一个函数,函数的名字就是showToast,后面的这小括号里面是用来放参数的,也就是说,函数里面如果需要用到一些从外面传进来的数据,就可以通过参数变量做传递。最后就是函数体了,用大括号扩起来的部分就是函数的函数体。在函数体中可以编写多条JavaScript代码,当然,因为只是举一个例子,所以我的函数里面只写了一个最基本的showToast控件,只会弹出一个提示,接下来,我们需要调用函数
showToast();
调用函数只需写一个函数名加一个括号(里面写的是参数,也可不传)然后加分号即可调用函数,执行函数的函数体了
这是第一种函数定义方法,还有的二种方法
JavaScript:
var showToast = function(){
hmUI.showToast({text: '函数被调用了'});
}
这是第二种定义函数的方法,和第一种方法有所不同,第二种定义函数的方法就是按照变量的方式来定义函数,变量的名字就是函数的名字,也就是说,我要想调用这个函数,就直接调用变量的名字即可
不过这种方法也有缺点,比如我在这个定义这个变量前调用这个变量(函数),那就会报错,而用第一种方法则不会有这种问题
(2).作用域
在JavaScript中,作用域分为两种,第一种是全局作用域,第二种是函数作用域,作用域就是指当你要查找某一个变量的时候,你可以在什么范围内找到这个变量。这个寻找的范围,就是作用域,关于全局作用域,先看个比较简单的例子
JavaScript:
var a = 10;
function test(){
console.log(a);
}
变量a和test函数都直接暴露在外面,因此它们都是全局作用域,而test函数的代码(函数体)就是函数作用域,因为test函数属于全局作用域,而它自己还有一个函数作用域,那么这样一来,全局作用域里面有一个函数作用域,函数体可以访问全局作用域中的变量,但是反过来不行,请看刚才的例子
JavaScript:
function test(){
console.log(a);
}
var a = 10;
test();
如果我直接调用test函数,答案必然是10。在这个例子中,函数作用域里面的a会先去函数作用域里面找变量a。找不到就去全局作用域中找。全局作用域中有一个变量a。那么,在执行函数体的时候,就访问全局作用域里的变量a,但是反过来就不行,比如这样
JavaScript:
function test(){
var a = 10;
}
console.log(a);
刚才已经说了,函数作用域里可以访问全局作用域里面的变量。但是全局作用域想调用函数作用域中定义的变量却是做不到的,因此当发生作用域嵌套的时候,只能函数访问全局,全局无法访问函数。而且作用域嵌套一般是全局作用域和函数作用域,或者是函数作用域和其他函数作用域。比如,下面这种形式就不是作用域嵌套
JavaScript:
if(true){
var a = 20;
}
console.log(a);
代码运行结果是20
虽然变量a的定义写在了花括号里面,但是JavaScript只有全局作用域和函数作用域以及块级作用域,这里没有函数所以不算作用域嵌套,这里的a是全局作用域里的,console.log也是全局作用域里的,自然可以访问同为全局作用域里面的变量a
块作用域就是用花括号包起来的,ECMAScript6中新增了块级作用域,使用let声明的变量只能在块级作用域里访问,块作用域由 { } 包括,if语句和for语句里面的{ }也属于块作用域
(3).参数传递
参数就是函数调用时传进来的值,也就是说,我们在定义参数的时候并不知道调用的过程中会有什么样的值传过来
JavaScript:
function add(a,b,c){
let sum = a + b + c;
hmUI.showToast({text: sum})
}
add(1,2,3);
代码运行结果是6
这是一个最简单的参数传递的例子,函数名字的定义要让人一看便知,这个例子中,add函数就是做加法。传进去了三个参数,分别是1,2,3,这三个参数分别对应add函数中圆括号内,也就是参数列表内的a、b、c三个变量
在刚才的例子中,如果你要调用add函数,就必须传入三个参数,就像下面的代码
add(1,2,3);
函数的调用就是在函数名字的右边加上一对小括号,这样就会执行函数里面的代码体,也就是下面这个部分
JavaScript:
function add (a,b,c){
var sum = a + b + c;
hmUI.showToast({text: sum})
}
函数的代码体一般都是用花括号扩起来的,每写完一句,就要打一个分号,现在我们来看一下这个函数的函数体里面都发生了些什么事情,首先是第一行
var sum = a + b + c;
sum是一个新定义的变量,这个变量是定义在函数作用域里面的,外面的全局作用域是没有办法直接访问函数作用域里面的sum变量的。所以,这个sum变量只能被这个函数的函数体被访问,它被叫作局部变量,然后是加法和赋值,把a、b、c三个变量相加之后得到一个总量,然后把这个总量赋给局部变量sum。下面是一个showToast控件,就是把sum变量弹出提示
如果我们调用函数是只传了一个参数该怎么办
对于这个问题,我们可以把它单独拆分出来看。比如,我定义了一个函数,设置了一个参数,但是传参的时候却一个参数都没有传
JavaScript:
function fun(a){
hmUI.showToast({text: a})
}
这是一个简单的函数,fun函数设置了一个叫a的参数,这个a还没有说明是什么,我在这个函数的函数体中写了一条showToast控件,接下来,我要调用这个函数,而且不写参数,就像这样
fun();
这是一个非常古怪的例子,因为fun函数是要求填写一个叫a的参数的,可是在调用函数时没有参数传递进来,这是不允许的,可是当这种情况真的发生了会怎样呢?试一下便知
输出结果是undefined
没错,结果就是undefined。其实,可以把这个例子再次细分。刚才的函数中有一个参数a,那么这个参数属于函数作用域,就相当于这样
JavaScript:
function fun(){
var a;
hmUI.showToast({text: a});
}
函数的参数可以简单地看成是在函数体,即里面的第一行定义了一个变量。因为我们并没有给这个变量赋值,所以这个局部变量就是undefined,任何变量在被赋值之前,都是undefined,这些函数的参数可以被理解为一种预备变量。接下来说说正常的情况,比如我调用fun函数,传递一个参数18。传参的过程就相当于是给预备变量赋值的过程。如果没有传参,那么预备变量自然还是undefined。再回到刚开始的例子,看一下如果只传一个参数的情况
JavaScript:
function add(a,b,c){
var sum = a + b + c;
console.log(sum);
}
add(1);
这种情况下,a的值是1,b和c的值就是undefined,那么数字1和2个undefined相加会是多少呢?真是有意思的问题。结果是NaN,代表无法计算。没错,如果真的那样做,那么就是没有任何意义的。最起码在这个函数中,那样的做法是毫无意义的
那么我们多传一个参数会怎么样呢
对于这个问题,其实也可以单独拆解出来。好比我定义了一个函数fun,但没有参数,如果我在调用fun函数的时候故意给它加了一个参数,会发生什么?比如像这样
JavaScript:
function fun(){
}
fun(10);
结果可想而知,自然是什么都不会发生啦。再回到刚才的例子中,就算你强行加了第四个参数,对结果也不会有什么影响
(4).闭包
用处:
((1)).子函数使用父函数变量的行为
直接说你可能不懂,我们来举个例子吧
JavaScript:
function a(){
    let leo = 1;
        function b(){
        hmUI.showToast({text: leo});
        };
        b();
}
可以理解为a函数是一个大圈,b函数是一个小圈,a函数包着b函数,a函数有一个leo变量,然后b函数访问a的变量
((2)).延长被调用父函数变量的生命周期
首先,JavaScript中一个变量如果你后面不使用了,就会被回收,拿上面的例子举例,因为b函数调用了a函数里的leo变量,所以可以延长a函数的变量的生命周期,也就是父函数的生命周期
((3)):拓展父函数的空间
简单来说就是父函数代码变多了,因为里面有个子函数
(5).自执行函数
很多时候,我们只想执行一个函数,却无所谓这个函数叫什么名字。那么在这种情况下,就可以考虑使用自执行函数了。自执行函数的格式是这样子的
语法 : (定义一个没有名字的函数)();
接下来举一个具体的例子,看看如何定义一个自执行函数
JavaScript:
(
function(){
console.log(123);
}
)();
这便是一个简单的自执行函数了,所谓自执行函数,顾名思义,就是在定义之后就立刻执行的函数,它一般是没有名字的。也正因为自执行函数没有名字,所以它虽然会被立刻执行,但是它只会被执行一次
自执行函数一般可以和闭包配合使用,举个例子
JavaScript:
function test (){
var a = 0;
return function (increment){
a = a + increment;
hmUI.showToast({text: a})
}
}
在这个闭包的例子中,其实我想要得到test函数里面的内部函数,所以我并不是很需要知道外面这个函数叫什么名字,它可以叫任何名字,甚至不需要有名字,所以我要使用自执行函数
(6).this
先看代码
JavaScript:
function hello(){
console.log(this);
}
我定义了一个函数hello,里面只有一个打印语句,打印出this对象。this是JavaScript中的一个关键字,它的意思就是this永远指向当前函数的调用者 这句话是关于this的一条铁律,首先,这句话透露出的第一个信息是,this只出现在函数中。第二个信息是,这个函数是谁调用的,this就是谁
(8).new函数
前面说过,JavaScript里面分为全局作用域和函数作用域,在全局作用域里面定义的任何东西,都属于window对象。也就是说,hello函数也是window对象的hello函数。而对象可以通过两种方式调用它里面的属性。第一种是点的方式,比如这样
window.hello();
第二种方式是使用中括号,即对象[属性名称],属性名称可以是一个字符串,也可以是一个变量,比如我这样写都是可以的
JavaScript:
window['hello']();
var p = 'hello';
window[p]();
我之前说了,this永远指向当前函数的调用者。那么,我们调用hello函数,其实也就是window对象调用了这个hello函数。既然如此,hello函数里面的this自然就指向了window对象。因此,hello函数调用后打印出来的就是window。好了,再回到new关键字的问题上,如果我在调用函数的时候使用了new,那么会发生什么呢
JavaScript:
function hello(){
hmUI.showToast({text: this})
new hello();
就是函数内部产生了一个新对象,并且this指向了这个新对象,然后函数默认返回了这个新对象
JavaScript:
function hello(){
hmUI.showToast({text: this})
}
new hello();

var newObject = new hello();
console.log(newObject);
这样的结果就是,newObject就是函数里面的this,也就是函数内部新产生的那个对象了
这种函数还有一个别称,叫作构造函数,我可以通过构造函数构建一个对象模板
所谓对象模板,就是指用一个函数的形式设计一种对象的种类。说得简单些,比如苹果、香蕉、板栗这些食物,它们都是食物,那么我就可以设计一个对象模板描述食物的一些共同特点。比如,食物有名字、味道、颜色等属性,那么我就可以在函数中用this关键字设计这些属性
JavaScript:
function Fruit(name,smell,color){
this.name = name;
this.smell = smell;
this.color = color;
}
我定义了一个函数Fruit,一般来说,如果这是一个构造函数,那么首字母就需要大写

因为函数在使用了new关键字以后会从内部新产生一个对象出来,而this就指向了这个对象,我就可以直接在函数里面给未来即将生成的那个对象设置属性,也可以理解为特点,在这个例子中,我设计的是一个水果构造函数,配合new关键字就会产生很多种水果对象。我也可以在这个构造函数里面给食物对象的名字属性、食用属性和效果属性,Fruit本来就是一个函数,既然是函数,自然是可以传递参数的,所以我干脆就把这些食物特点作为参数传进去
var apple = new Fruit('屎','一天吃三斤屎','越吃越牛逼');
除了用函数创建一个对象,也可以直接制作一个自定义对象出来
JavaScript:
var apple2 ={
name:"屎",
today:"一天吃三斤屎",
niuboyi:"越吃越牛逼"
}
这是创建对象的一种方式,使用花括号就可以直接定义一个对象了。对象里面的属性和属性值都是键值对的形式,当中用冒号,不同的键值对只能用逗号分隔。键值对,键就是属性的名字,值就是属性的值。键可以用引号,也可以不用。值并不是只能是字符串,它可以是数字,也可以是字符串,甚至是函数或者另外一个对象
用构造函数的方法定义对象是有好处的。比如我需要2个苹果,使用构造函数的话,直接调用两次new函数就行了,可以非常方便地获得两个苹果。而使用大括号的方式就得写两次
JavaScript:
var apple1 = new Fruit('大苹果','香甜可口','红色');
var apple2 = new Fruit('大苹果','香甜可口','红色');
var apple3 = {
name:"苹果",
smel1:"甜的",
color:"红色"
}
var apple4 = {
name:"苹果”,
smell:"甜的”,
color:"红色”
}
你可能会说,这太TM麻烦了吧,直接
JavaScript:
var apple3 = {
name:"苹果",
smel1:"甜的",
color:"红色"
}
var apple4 = apple3;
不就行了吗

卜卜卜卜卜卜卜卜卜卜卜卜,这样写的话,apple3和apple4其实都是一个苹果的,不信的话,我来做一个测试
首先,给苹果对象添加一个是否被吃掉的属性
JavaScript:
var apple3 = {
name:"苹果",
smel1:"甜的",
color:"红色",
isEat:false
}
然后让变量apple4等于apple3,修改apple4的eat属性,把没有被吃掉的状态改成已经被吃掉。接着,查看apple3是否跟着一起被改变就知道了
JavaScript:
var apple3 = {
name:"苹果",
smel1:"甜的",
color:"红色",
isEat:false
}

var apple4 = apple3;
apple4.isEat = true;
console.log(apple3);
输出结果是isEat:true
8.回调函数
回调函数就是把一个函数的定义当作参数传递给另一个函数,举个例子
正常情况下,函数传参可以是一个数字,也可以是一个字符串,这都没有问题。但是JavaScript提供了一种强大的特性,就是:函数也可以作为另一个函数的参数。比如我现在有一个‘吃饭’的函数,既然是‘吃饭’的函数,我就得考虑吃什么、怎么吃、要加什么佐料的问题
JavaScript:
function eat(food,howToEat,tiaoliao){
hmUI.showToast({text:tiaoliao + ',' + howToEat + "吃" + food});
}
这是一个‘吃饭’函数,并且我把食物、怎么吃和佐料都当作参数传了进去。那么,当我要调用这个‘吃饭’函数的时候,可能是这个样子的
eat('羊肉串','笑嘻嘻的','撒上一撮孜然');
代码运行结果是:撒上一撮孜然,笑嘻嘻地吃羊肉串。

这样做is very good,但是如果我要给这个函数添加新的条件该怎么办?我就要修改函数的参数列表,函数的代码体。如果改动比较大,会非常麻烦。所以怎么吃难道不是应该在我真的吃饭的时候才决定吗?所以,食物变量照样可以当作参数传递,因为吃什么可能是预先就想好的,但是怎么吃就很难预先考虑好了,而加什么佐料则有很大的随机性。那么,我能不能把吃的方法当作一个参数传入这个eat方法呢?到时候,在真正需要考虑怎么吃时直接调用这个已经作为参数的函数不就好了吗
JavaScript:
function eat (food,callback){
callback(food);
}
你可能会觉得这个代码有点奇怪
不要着急,容我慢慢道来。首先,callback就是那个函数,既然是函数,我们都知道打一个括号就可以执行函数。那么在这个eat函数中,直接执行了callback,并且把另一个food参数传入了callback。意思就是说,到底怎么吃是在你调用eat函数的时候通过临时编写一个新的函数实现的!
JavaScript:
eat('羊肉串',function(food){
hmUI.showToast({"笑嘻嘻的,撒上一撮孜然,开心地吃" + food});
}
这个函数我希望它进入eat函数执行。同时,我在编写这个匿名函数的时候也设计了参数food,这就是要吃的食物了
这就是JavaScript的常识,毕竟大部分时间看官方文档就行了
二.开发小程序
准备工作
首先我们在米坛下载我的联网小程序模板\helloworld模板
手机用mt管理器打开,电脑解压后用VSCode(Visual Studio Code)打开
概览
我们会看到两个文件和六个文件夹(helloworld模板后四个没有)
assets:储存一些小程序需要的文件,如图标图片,电子书文本,图片控件等
page(不同小程序显示不同):储存代码文件
app.js:小程序逻辑
app.json:小程序信息
app-side:联网小程序会有
setting:使用设置应用的小程序会有
utils:跑龙套的
shared:共享
首先我们进入到app.json来配置小程序信息
JSON:
{
"configVersion": "v2",
"app": {
"appIdType": 0,
"appType": "app",
"version": {
"code": 1,//第几个版本
"name": "1.0.0"//小程序版本号
},
"appId": 100001,//appid,来保证小程序不会被覆盖,类似安卓包名
"appName": "小程序",//小程序名字
"icon": "icon.png",//小程序图标
"vender": "bandbbs",//开发者名字
"description": "helloworld"//小程序简介
},
"permissions": ["gps"],//小程序权限
"runtime": {
"apiVersion": {
"compatible": "1.0.0",
"target": "1.0.1",
"minVersion": "1.0.0"
}
},
"i18n": {
"en-US": {
"name": "helloworld"//多语言
}
},
"defaultLanguage": "en-US",//默认语言
"debug": false,//调试选项
"module": {
"page": {
"pages": [
"page/192x490_s_l66/index.page"//默认打开路径
],
"window": {
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTextStyle": "black",
"navigationBarTitleText": "",
"backgroundColor": "#eeeeee",
"backgroundTextStyle": "light"
}
}
},

"platforms": [
{
"name": "l66",
"deviceSource": 260
},
{
"name": "l66w",
"deviceSource": 261
},
{
"name": "l66_1",
"deviceSource": 262
},
{
"name": "l66w_2",
"deviceSource": 263
},
{
"name": "l66_3",
"deviceSource": 264
},
{
"name": "l66_4",
"deviceSource": 265
},
{
"name": "l66_5",
"deviceSource": 266
}
],
"designWidth": 192,
"packageInfo": {
"mode": "production",
"timeStamp": 1648534836,
"expiredTime": 172800,
"zpm": "2.1.49"
}
}
反正看着改就行了
//我的联网小程序模板appld更改后要在app.js里更改appld
接着进入page中的192x490_s_l66的index.page
然后你就可以写代码了
小程序开发注意事项:
1.小米手环7搭载的系统是Zepp OS1.0,无法使用2.0的API
//也不可能升到2.0,官方的解释是小米手环7升级2.0需要综合评估设备性能及用户体验,短期内无法实现
3.不支持使用 new Function 创建函数(可使用Vepp框架解决)
new Function('return this') 除外
4.Zepp OS的ECMAScript不支持以下特性
Promise
Generator 函数
定时器
5.小米手环7不支持异步,比如不能提前加载好界面再进入

这里汇总一下开放时用的工具
电脑手机通用
官方文档:https://docs.zepp.com/zh-cn/docs/1.0/reference/app-json/
小程序模板:https://www.bandbbs.cn/threads/4250/
小程序表盘模板:https://www.bandbbs.cn/threads/4007/
修改图片尺寸:https://www.gaitubao.com/
图片转换:https://watchface-web-editor.rth1.one/
跳转官方应用API:https://www.bandbbs.cn/threads/4859/page-2#post-221632
MDN文档(学JavaScript必备):https://developer.mozilla.org/zh-CN/
电脑专属
图片转换:https://www.bandbbs.cn/threads/3953/或https://melianmiko.ru/zmake/
Zeus开发:https://www.bandbbs.cn/threads/5237/
Vepp框架:https://www.bandbbs.cn/threads/5754/(使用方法见下面)
模拟器:https://melianmiko.ru/zepp_player/(电脑端强烈建议,无需配置)
常用API
控件方面
文本
JavaScript:
hmUI.createWidget(hmUI.widget.TEXT, {//创建控件
x: 5,//x坐标
y: 10,//y坐标
w: 200,//宽度
h: 70,//长度
color: 0xFFF200,//文本颜色
text_size: 40,//文本大小
text: "hhh"
});//结束
图片
JavaScript:
hmUI.createWidget(hmUI.widget.IMG, {
x: 78,
y: 421,
src: "help.png"
})
跳转页面,跟在非按钮控件后
JavaScript:
.addEventListener(hmUI.event.CLICK_UP, function (c) {
hmApp.gotoPage({
url: "page/192x490_s_l66/index.page2",
param: "..."
})
});
图片帧
JavaScript:
hmUI.createWidget(hmUI.widget.IMG_ANIM, {
x: 0,
y: 189,
anim_path: "images/Mars", //目录
anim_prefix: "bg",//前缀
anim_ext: "png",//后缀
anim_fps: 3,//帧率
anim_size: 313,//数量
repeat_count: 5,
anim_repeat: false,
display_on_restart: true,
});
填充矩形
JavaScript:
hmUI.createWidget(hmUI.widget.FILL_RECT, {
x: 125,
y: 125,
w: 230,
h: 150,
radius: 20,//圆角
color: 0xfc6950//颜色,十六进制
})
描边矩形
JavaScript:
hmUI.createWidget(hmUI.widget.STROKE_RECT, {
x: 125,
y: 125,
w: 230,
h: 150,
radius: 20,
line_width: 4,//线宽
color: 0xfc6950
})
圆形
JavaScript:
hmUI.createWidget(hmUI.widget.CIRCLE, {
center_x: 240,//圆心x坐标
center_y: 240,//圆心y坐标
radius: 120,//半径
color: 0xfc6950,
alpha: 200//透明度
})
按钮
JavaScript:
hmUI.createWidget(hmUI.widget.BUTTON, {
x: 40,
y: 240,
w: 400,
h: 100,
radius: 12,//圆角
normal_color: 0xfc6950,//一般按钮色
press_color: 0xfeb4a8,//按压按钮色
text: 'Hello',//文字
click_func: () => {//回调,触发事件
hmApp.gotoPage({url: "page/192x490_s_l66/index.page4",param: "..."});//跳转页面
}
})
提示
JavaScript:
hmUI.showToast({
text: 'Zepp'//文本内容
})
其它方面
跳转页面
JavaScript:
hmApp.gotoPage({url: "page/192x490_s_l66/index.page4",param: "..."});
简易全局变量
JavaScript:
hmFS.SysProSetInt('fps');
let fps = hmFS.SysProGetInt('fps');
简易主题
JavaScript:
var menusittuughhsdgbfjhgwaqeurdfgaiehriuaq = menufou.createWidget(hmUI.widget.BUTTON, {
x: 0,
y: 5,
w: 192,
h: 45,
radius: 10,
color: 0xffffff,
text_size: 25,
text: "黑配白",
click_func: () => {
hmFS.SysProSetInt("indexcolor", 1);
}
})
var menugale = menufou.createWidget(hmUI.widget.BUTTON, {
x: 0,
y: 50,
w: 192,
h: 45,
radius: 10,
color: 0xffffff,
text_size: 25,
text: "白配黑",
click_func: () => {
hmFS.SysProSetInt("indexcolor", 2);
}
})
调用:
JavaScript:
var indexcolortext = hmFS.SysProGetInt("indexcolor");
var indexcolorrec;
if(indexcolortext == undefined){
indexcolortext="0xffffff"
indexcolorrec="0x000000"
}else if(indexcolortext == 1){
indexcolortext="0xffffff"
indexcolorrec="0x000000"
}else if(indexcolortext == 2){
indexcolortext="0x000000"
indexcolorrec="0xffffff"
}
多语言
JavaScript:
const language = hmSetting.getLanguage();
switch(language){
case 0:
Battery_text = "电量";
case 1:
Battery_text = "電量";
break;
case 2:
Battery_text = "Battery";
break;
default:
Battery_text = "Battery";
}
hmUI.createWidget(hmUI.widget.TEXT, {
x: 5,//x坐标
y: 10,//y坐标
w: 200,//宽度
h: 70,//长度
color: 0xFFF200,//文本颜色
text_size: 40,//文本大小
text: Battery_text
});//结束
三.Vepp框架的使用
然后再来讲一下Vepp的功能以及如何使用
官方的解释是Vepp的核心功能是声明式渲染,订阅式更新
首先除声明式之外还有一种叫做命令式,两个的区别是
命令式:在哪里做什么,怎么做
声明式:在哪里做什么
比如说我们有一个数组,要让里面的每个数字乘以2
命令式:
JavaScript:
var arr=[2,4,5,6]
var arr2=[]
for(var i=0;i<arr.length;i++){
arr2.push(arr*2)
}
声明式:
JavaScript:
var arr=[2,4,5,6]
var arr2=arr.map(item=>item*2)
console.log(arr2)
这样就少写了很多的代码,至于订阅式更新的意思就是让手环在云端注册并自动接收最新的资源
另外,Vepp绕过了new Functuon,而且可以在官方的基础上套壳打造控件系统
使用教程
电脑打开https://github.com/coreybutler/nvm-windows/releases下载并安装
电脑同时按住Win+R,输入cmd,输入npm install vepp
下载完成后返回桌面
右键,新建文本文档
将后缀名改为.js,用Vscode打开
然后看着Vepp官方的介绍图
第一行是import Vepp from 'vepp'
其实就是使用下载好的Vepp框架
把这段代码插入到js文件顶部即可
然后后两行就是写好的小程序逻辑(helloword模板不需要,我的联网小程序模板直接复制即可)
第四行是一个let变量,也是用VML创建控件,这一行直接复制粘贴即可
然后ui这里就是控件的属性,可参照官方的改

然后data这里也是配置这个控件的一些信息

这段代码总结起来就是Vepp创建新页面,该页面会有一个名为mytext的文本控件,这个文本控件可以被点击,然后触发myfunc函数,这样就能打印出mytext的值
试练一下
#BUTTON x: 0, y: 6, w: 2, h: 1, color: 0x49406d, normal_color: 0xc9bdff, press_color: 0xeae5ff, radius: 12, text: "是故意的", click_func: () => hmUI.showToast({text: '你尝了一口吗'})
我创建了一个按钮,是不是非常简单,使用VML创建控件比官方使用的代码要少得多

四.手机也能用vscode?
你是否觉得,手机端的开发工具mt管理器功能太匮乏了?甚至连代码纠错的功能都没有,而电脑端的vscode强大的一批,那我们有没有办法使手机用上vscode呢
答案是
有!不仅有官方的网页版vscode还有第三方移植的vscode,那让我们一起来看看吧
1.官方网页
在去年,啊不,在前年10月末的时候,微软发布了在网页端运行的vscode,网址是vscode.dev,切记!一定要用edge或chrome浏览器打开,否则白屏
不过这个网页版虽然方便,但是啊,它不支持插件(或许对于手机端根本不需要插件)
2.Code FA
虽然有很多第三方的vscode,但是Code FA是我感觉最流畅的
具体使用
下载并安装https://www.coolapk.com/apk/com.nightmare.code
下载https://www.123pan.com/s/YOtKVv-BXN0A
解压第二个链接里面的文件到/storage/emulated/0/目录
打开Code FA,将版本号改为4.6.1
加载完成后如果白屏,就用有独立内核的浏览器打开白屏的网址(我也忘了)
找到下载的两个插件,选择并等待安装
没了
 
最后编辑:
6,出书吧
对了,在这里说一下,可能因为网页托管的原因,表盘在线编辑器不能使用上传图片等功能。我同时在github上挂载了一遍,可以正常使用。如果你所在的地区以及运营商可以访问,请使用这个,原网页也可正常访问,望周知。
 
最后编辑:
wc,置顶了
 
小米手环7的小程序开发语言是JavaScript(简称js)
所以我们要掌握JavaScript的一些常识
一.认识JavaScript常识
1.变量
定义变量的方式有两种,分别是var,let
其中var是很老很老的变量方式了,它可以重新赋值
let和是偏现代的变量方式,let也可以重新赋值。还有一种和变量相似的,叫做常量,常量只有const,常量不能重新赋值,总之,以后变量用let,常量用const

变量的使用
注意!变量名只能以$,字母,下划线开始,如果变量赋值是大写,使用时是小写,则不是同一个变量,输出结果为undefined
我这里拿Apple健康的做演示
var step = hmSensor.createSensor(hmSensor.id.STEP);
其中var后面的step,就是变量名,等于号后面的则是将此变量赋值为获取到的系统步数
也可以这样写
var step;
step = hmSensor.createSensor(hmSensor.id.STEP);
这种是先声明一个变量,再对其进行赋值,但这种比较麻烦,而且当你忘记赋值时获取变量会被输出undefined
而我们后续使用这个变量时,我们可以这样写
hmUI.createWidget(hmUI.widget.TEXT, {//创建控件
x: 5,//x坐标
y: 10,//y坐标
w: 200,//宽度
h: 70,//长度
color: 0xFFF200,//文本颜色
text_size: 40,//文本大小
text: step.current//将文本输出为先前定义好的定义值
});//结束
当然,我们还可以设置变量为x坐标,y坐标,宽度还有长度
此处参考Battery program
变量:var battery = hmSensor.createSensor(hmSensor.id.BATTERY);
控件hmUI.createWidget(hmUI.widget.FILL_RECT, {
x: 20,
y: 80,
w: battery.current,
h: 50,
radius: 15,
color: 0x078707,
});
一般变量过多可以全部放开头
2.注释
//是单行注释,/* */是多行注释,可以用来暂时封存代码
3.switch语句
switch语句简单讲就是分情况匹配相应代码
switch语句的作用一般用于小程序语言国际化,如环管pro和像素鸟都采用了这种方法
const language = hmSetting.getLanguage();// const 变量
switch(language){// ()是赋值的变量
case 0:// 当输出结果为0,则执行以下代码(0在官方文档里的是中文)
var Battery_text = "电量";
var attention_text = "高功耗功能";
var attentiontwo_text = "请检查您的充电习惯!\n电池管家建议的健康充电为20%到80%\n不要让手环充电超过8小时,\n因为这可能会导致过度充电";
var clock_text = "设置闹钟";
var didian_text = "剩余电量不足10%";
var didiantwo_text = "剩余电量不足20%";
break;
case 1:
var Battery_text = "電量";
var attention_text = "高功耗功能"
var attentiontwo_text = "請檢查您的充電習慣!\n電池管家建議的健康充電爲20%到80%\n不要讓手環充電超過8小時,\n因爲這可能會導緻過度充電";
var clock_text = "設置闹鐘";
var didian_text = "賸餘電量不足10%";
var didiantwo_text = "賸餘電量不足20%";
break;
case 2:
var Battery_text = "Battery";
var attention_text = "high power function";
var attentiontwo_text = "Please check your charging habits!\nBatteryGuru recommends a healthy charge of 20% to 80%\nDon't charge your band for more than 8 hours\nas this may lead to overcharging";
var clock_text = "set alarm";
var didian_text = "The remaining battery is less than 10%";
var didiantwo_text = "The remaining battery is less than 20%";
break;
default: // 当输出结果不属于以上的任何代码时执行以下代码
var Battery_text = "Battery";
var attention_text = "high power function";
var attentiontwo_text = "Please check your charging habits!\nBatteryGuru recommends a healthy charge of 20% to 80%\nDon't charge your band for more than 8 hours \nas this may lead to overcharging";
var clock_text = "set alarm";
var didian_text = "The remaining battery is less than 10%";
var didiantwo_text = "The remaining battery is less than 20%";
}
这段代码可以使小程序语言国际化,我们也可以用if语句代替
4.if语句
if语句和switch语句差不多,只不过if语句一般用来确定一个范围的值,而switch只能用来返回数值
if语句也有多分支
双分支一般是if (){} else() {}
多分支一般是if() {} else if() {}
其中圆括号里填的是条件判断,建议和下面讲到的运算符搭配使用,如果条件判断里没有运算符,则是判断是否有这个变量
比如
if (indexcolortext == undefined) {
indexcolortext = "0x000000";
indexcolorrec = "0xFFFFFF";
indexnormal = "0x8FBC8F";
indexpress = "0x2E8B57";
} else if (indexcolortext == 1) {
indexcolortext = "0xFFFFFF";
indexcolorrec = "0x000000";
indexnormal = "0xA9A9A9";
indexpress = "0xA9A9A9";
} else if (indexcolortext == 2) {
indexcolortext = "0x000000";
indexcolorrec = "0xFFFFFF";
indexnormal = "0x8FBC8F";
indexpress = "0x2E8B57";
} else if (indexcolortext == 3) {
indexcolortext = "0x000000";
indexcolorrec = "0xFFFFFF";
indexnormal = "0x555555";
indexpress = "0x555555";
}
5.break,continue和return
前两者可以提前跳出循环
break是
6.算数运算符
JavaScript算数运算符,无非加、减、乘、除、取余、自增,自减运算符
比如
var a = 10;
var b = 2;
var c = a++;
var d = a--;
var e = ++a;
var f = --a;
var s1 = a + b;
var s2 = a - b;
var s3 = a * b;
var s4 = a / b;
console.log(c);
console.log(d);
console.log(e);
console.log(f);
前几个好说,但是cd和ef有什么区别呢
区别就是运行c和d时,得出结果是10,而e和f得出来是11和9
这是为什么呢
因为自增或自减运算符,它分为前置和后置,前置就是在变量的
前面写一个“++或--”,后置就是在变量的后面写一个“++或--”
后置的特点是先让变量参与运算,运算结束以后再进行自增
而前置就是a的意思是先让a的值自增一次,a本来是10,经过自增就变成了11,因为前置++的含义是先让变量自增,再放进式子里面运算,所以这个代码的结果就是11
7.比较运算符
==等于
!=不等于
大于号是大于
<小于
大于号加=是大于或等于
<=小于或等于
8.输出
console.log(/输出的东西/);
9.for循环
for循环的用处是一遍又一遍地运行相同的代码,并且每次的值都不同
for (表达式1;表达式2;表达式3)
{
语句
}
首先要强调两点:
1.表达式1、表达式2和表达式3之间是用分号;隔开的,千万不要写成逗号。
2.for(表达式1;表达式2;表达式3)的后面千万不要加分号,很多新手都会犯这种错误——会情不自禁地在后面加分号。
实践
for(var i = 0;i<10;i++){
console.log(i);
}
10.while循环
和for循环差不多
实践
var i = 0;
while(i<10){
console.log(i);
i++;
}
它和for循环只是在语法上有所不同,其作用和
for循环是一样的。
11.数组
在JavaScript中,数组是一个非常灵活的类型。简单来说,数组就
是一个容器,可以存放一个或者多个对象。当然,这些对象的类型是
没有限制的,不管它是什么,数组都可以存放
数组的定义方式
数组有4种定义方式
这里我就采用最常用的直接量吧
例如这样
var arr = ["first","second","third"];
console.log(arr);
得到的结果就是生成了一个拥有3个元素的数组对象,对象的名字是arr,这种方法的好处是在定义数组的时候可以直接对这个数组进行初始化
12.函数//难点,看不懂可以消化一下
这里讲一下函数的七个要素
1.函数定义
函数是一组可以被重复调用的代码语句,格式是这样的
funtion showToast(){
hmUI.showToast({text: '函数被调用了!'});
}
我刚才定义了一个函数,函数的定义需要用到function关键字,然后空一格,再加上函数的名字。刚才的代码中,函数的名字就是showToast,后面的这小括号里面是用来放参数的。也就是说,函数里面如果需要用到一些从外面传进来的数据,就可以通过参数变量做传递。最后就是函数体了,用大括号扩起来的部分就是函数的函数体。在函数体中可以编写多条JavaScript代码,当然,因为只是举一个例子,所以我的函数里面只写了一个最基本的showToast控件,只会弹出一个提示罢了,接下来,我们需要调用函数
调用函数只需写一个函数名();即可调用函数,执行函数的函数体了
我们也可以这样写
function myFuntion(){
document.write("This is My First Function");
}
里面的document.write方法表示用JavaScript向页面输出一段话
这是第一种方法,还有的二种方法
var a = function(){
document.write("This is My First Function");
}
这便是第二种定义函数的方法了,和第一种方法有所不同,第二种定义函数的方法需要先定义一个变量,比如‘vara’,然后还是用function关键字定义一个函数,再把这个函数赋值给变量a。因为最后要赋值给变量a,因此这里在定义函数的时候就不需要加上函数的名字了,这就是其中的一个区别。用这种方法定义出来的函数,函数的名字就是变量的名字,也就是说,我要想调用这个函数,就直接调用变量的名字即可
第二种也有一些缺点,比如如果我在这个变量赋值前调用这个变量(函数),那就会报错,而用第一种方法则不会有这种问题
2.作用域
在JavaScript中,作用域分为两种,一种是全局作用域,另一种是函数作用域。所谓作用域,就是指当你要查找某一个变量的时候,你可以在什么范围内找到这个变量。这个寻找的范围,就是作用域。不管是全局作用域还是函数作用域,都被定义在词法阶段。词法阶段就是刚才所说的JavaScript编译代码的第一个步骤——分词。所以,词法阶段也叫作分词阶段。关于全局作用域,先看个比较简单的例子
var a = 10;
function test(){
console.log(a);
}
变量a和test函数都直接暴露在外面,因此它们都属于全局作用域。而test函数的函数体,即用花括号包起来的部分则是函数作用域。没错,函数的函数体都属于函数作用域。又因为test函数属于全局作用域,而它自己又拥有一个函数作用域,那么这样一来,就形成了一个作用域的嵌套。也就是说,全局作用域里面嵌套了一个函数作用域。在函数作用域里面可以访问全局作用域中的变量,但是反过来不行。请看刚才的例子
function test(){
console.log(a);
}
var a = 10;
test();
如果我直接调用test函数,答案必然是10。在这个例子中,函数作用域里面的a会先去当前函数作用域里面寻找是否有一个变量a。如果找不到,就去上一层包着它的父级作用域中寻找。那么,从这个例子不难看出,外面的父级作用域,也就是全局作用域中确实有一个变量a。那么,在执行函数体的时候,就可以访问外面的变量a啦。但是反过来就不行,比如这样
function test(){
var a = 10;
}
console.log(a);
刚才已经说了,全局作用域包着一个函数作用域,在函数作用域里面可以访问全局作用域里面的变量。但是反过来的话,全局作用域想要调用函数作用域中定义的变量却是做不到的。因此当发生作用域嵌套的时候,只能里面的访问外面的,外面的无法访问里面的。而且需要注意一点,那就是作用域嵌套一般是针对全局作用域和函数作用域,或者是函数作用域和其他函数作用域而言的。比如,下面这种形式就不是作用域嵌套
if(true){
var a = 20;
}
console.log(a);
代码运行结果是20
虽然变量a的定义写在了花括号里面,但是这里并没有出现函数,因此不算作用域嵌套。而且我刚才也说了,在JavaScript中,只有全局作用域和函数作用域,你可以认为这里的a也属于全局作用域,这样更方便理解。既然都是在全局作用域里面,那么console.log方法自然可以访问同为全局作用域里面的变量a
如果我们把布尔值true换成false,然后运行出来的结果是undefined//未定义
var a = 20;’这句话在if判断中,而if判断的条件是false,所以这句话的确不会执行。但是,执行代码是在运行阶段,在代码的分词阶段和解析阶段,变量a依然会被获取,并且系统会默认给它一个undefined。又因为变量a是在全局作用域里面,所以console.log方法依然可以访问这个变量,因此获取变量a的值就是undefined
3.参数传递
所谓的参数,就是指当函数调用的时候会传进来的值,也就是说,我们在定义参数的时候并不知道调用的过程中会有什么样的值传过来
function add(a,b,c){
var sum = a + b + c;
console.log(sum);
}
add(1,2,3);
代码运行结果是6
这就是一个最简单的函数调用配上参数传递的例子。一般来说,函数的名字定义要让人一看就知道是什么意思。比如这个例子中,一看add函数就能够明白它的目的是做加法。调用函数的时候传进去了三个参数,分别是1、2、3,这三个参数分别对应add函数中圆括号内,也就是参数列表内的a、b、c三个变量。在定义这个函数的时候,a、b、c三个变量的变量名是随便取的,当然,能够见名知意最好
在刚才的例子中,add函数的调用需要三个参数,分别是a、b、c,换句话说,如果你要调用add函数,就必须传入三个参数,就像下面的代码
add(1,2,3);
函数的调用就是在函数名字的右边加上一对小括号,这样就会执行函数里面的代码体,也就是下面这个部分
function add (a,b,c){
var sum = a + b + c;
console.log(sum);
}
函数的代码体一般都是用花括号扩起来的,在里面正常写JavaScript代码就行了。每写完一句,就要打一个分号,这是JavaScript代码的编写规范。现在我们来看一下这个函数的函数体里面都发生了些什么事情,首先是第一行
var sum = a + b + c;
sum是一个新定义的变量,注意,这个变量是定义在add函数的函数体内部的,根据作用域的范围限定,这个变量是定义在函数作用域里面的,函数作用域是一个相对封闭的空间,也就是说,外面的全局作用域是没有办法直接访问函数作用域里面的sum变量的。所以,这个sum变量只能在该函数的函数体内被访问,它也被叫作局部变量。好,继续看,接下来就是一个简单的加法和赋值了。从代码的字面上也可以看出,就是把a、b、c三个变量相加之后得到一个总量,然后把这个总量用等号(赋值运算符)赋给局部变量sum。下面是一个打印语句,就是把sum变量在控制台上打印出来
如果我们调用函数是只传了一个参数该怎么办//省流,返回结果是NaN,无法计算
对于这个问题,我可以把它单独拆分出来看。比如,我定义了一个函数,设置了一个参数,但是传参的时候却一个参数都没有传
function fun(a){
console.log(a);
}
这是一个简单的函数,函数名叫fun,这个函数设置了参数,参数的名字是a,当然,这个a到底是什么是没有限定的,它可以是一个字符串,也可以是一个数字,甚至可以是一个对象,哪怕是另一个函数也可以。因为只是测试,所以我只是在这个函数的函数体中写了一条打印语句而已。接下来,我要试着调用这个函数,而且故意不写参数,就像这样
fun();
这是一个非常古怪的例子,因为fun函数明明是要求填写一个参数的,那就是a。可是在调用函数的时候,却偏偏没有参数传递进来。这按理说是不被允许的,可是当这种情况真的发生了会怎样呢?也就是说,如果没有参数传进来,那么函数中已经设置好的参数会等于什么呢?试一下便知
输出结果是undefined
没错,结果就是undefined。其实,对于函数传参到底是怎么回事,可以把这个例子再次细分。刚才的函数中有一个参数a,那么这个参数自然也属于函数作用域,就相当于这样
function fun(){
var a;
console.log(a);
}
为了方便理解,函数的参数可以简单地看成是在函数体,也就是花括号扩起来的地方,即里面的第一行定义了一个变量。因为我们并没有给这个变量赋值,所以这个局部变量就是undefined。可以这么说,任何变量在被赋予真正的值之前,其在编译阶段都是undefined。或者说,任何变量不管其最终的值是什么,它都曾经是undefined。这些函数的参数可以被理解为一种预备变量。接下来说说正常的情况,比如我调用fun函数,传递一个参数18。传参的过程就相当于是给预备变量赋值的过程。如果没有传参,那么预备变量自然还是undefined。再回到刚开始的例子,看一下如果只传一个参数的情况
function add(a,b,c){
var sum = a + b + c;
console.log(sum);
}
add(1);
这种情况下,a的值是1,b和c的值就是undefined,那么数字1和2个undefined相加会是多少呢?真是有意思的问题。结果是NaN,代表无法计算。没错,如果真的那样做,那么就是没有任何意义的。最起码在这个函数中,那样的做法是毫无意义的
那么我们多传一个参数会怎么样呢
对于这个问题,其实也可以单独拆解出来。好比我定义了一个函数fun,但没有参数,如果我在调用fun函数的时候故意给它加了一个参数,会发生什么?比如像这样
function fun(){
}
fun(10);
结果可想而知,自然是什么都不会发生啦。再回到刚才的例子中,就算你强行加了第四个参数,对结果也不会有什么影响
4.闭包
闭包的技术异常晦涩和难以理解,其难度在JavaScript中是出了名的
说到闭包,还是先提一下最后讲到的函数返回值
function add(){
var sum = 0;

for(var i = 0;i<arguments.length;i++){
sum =sum + arguments;
}

return sum;

}
因为sum是函数作用域里面的变量,因此也叫局部变量,外面是没有办法直接访问这个局部变量的,除非把sum作为返回值返回出去,外面才可以访问sum变量。好了,既然是在函数中,如果我可以把一个变量返回出去,那么自然也就可以把一个函数也返回出去啊,比如这样
function test(){
return function(){
}
}
在这个例子中,就是在一个函数里面嵌套了另外一个函数,因为我只是想要把一个函数返回出去,而并不在乎这个内部函数叫啥名字,所以干脆就不给它取名字了,那么里面的这个函数就是一个匿名的函数,这种写法虽然有点奇怪,但它依然是正确的
你可能会问你做这么奇怪的事情干什么
当然有意义,因为函数作用域可以嵌套,所以里面的函数作用域就可以访问外面函数作用域中的变量了,比如这样
function test(){
var a = 0;
return function(){
console.log(a);
}
}
test函数里面定义了一个局部变量a,这个变量a就属于test函数的函数作用域,而最终返回的函数也属于test函数作用域,这个匿名函数的内部就有权限访问外部的作用域。换句话说,外面的变量a可以被它访问到。这个道理就和函数作用域可以访问全局作用域是一样的。接下来就是重点了。因为test函数返回的结果是一个函数,既然是函数,不去调用的话就不会执行里面的代码,所以如果需要执行内部函数的函数体,就必须要这样
test()();
第一个小括号是调用test函数,这个test函数中定义了一个局部变量a,还返回了一个内部函数。因此,第一次调用的结果就是返回一个内部函数,而第二个圆括号才会调用那个内部函数
代码执行结果是0
刚才的例子就是一个典型的闭包,现在我总结一下产生闭包的条件。第一点,在函数内部也有一个函数。就好比这个例子,在test函数里面还有一个函数。第二点,函数内部的函数里面用到了外部函数的局部变量。还是这个例子,test函数里面有一个局部变量a,并且被内部
函数使用了。第三点,外部函数把内部函数作为返回值return出去了

这样的好处是正常情况下,我们调用一个函数,其里面的局部变量会在函数调用结束后销毁,这也是我们在全局作用域里面无法访问函数局部变量的原因。但是,如果你使用了闭包,那么就会让这个局部变量不随着原函数的销毁而销毁,而是继续存在。比如我反复调用这个内部函数,就会发现这个变量a一直存在,就好像是一个全局作用域里面的变量似的
var innet = test();
inner();
inner();
inner();
代码运行结果都是0
你可能会问变量a本来就是0,你怎么证明打印出来的是同一个变量呢?
这好办,我可以给内部函数设置一个累加的参数,在每次调用内部函数的时候都把这个参数的值加上

function test (){
var a = 0;
return function (increment){
a = a + increment;
console.log(a);
}
}
var innet = test();
inner(1);
inner(1);
inner(1);
代码执行结果分别为 1、2、3
这样就可以证明在每次调用内部函数的时候,里面访问的都是同一个变量a了。这种写法就相当于在全局作用域里面定义了一个变量a,然后在函数中操作全局变量。但是用这样的形式操作,也就是利用闭包操作可以减少很多不必要的全局变量。全局作用域是一块公共区域,如果为了某个单一的功能而定义一个全局变量,则会导致全局变量过多,代码就变得一团糟了。因此在这种情况下,还是要优先考虑使用闭包
那么外部函数中的局部变量还可以被抹除吗
当然可以
只要你在某一个特定的时刻手动将那个变量赋值为null就行了。JavaScript会自动扫描函数中值为null的变量,一旦找到就会自动清除这些无用的变量
5.自执行函数
很多时候,我们只想执行一个函数,却无所谓这个函数叫什么名字。那么在这种情况下,就可以考虑使用自执行函数了。自执行函数的格式是这样子的
语法 : (定义一个没有名字的函数)();
接下来举一个具体的例子,看看如何定义一个自执行函数
(
function(){
console.log(123);
}
)();
这便是一个简单的自执行函数了,所谓自执行函数,顾名思义,就是在定义之后就立刻执行的函数,它一般是没有名字的。也正因为自执行函数没有名字,所以它虽然会被立刻执行,但是它只会被执行一次
自执行函数一般可以和闭包配合使用,比如之前的例子
function test (){
var a = 0;
return function (increment){
a = a + increment;
console.log(a);
}
}
在这个闭包的例子中,其实我真正想要得到的是test函数里面的内部函数。因为这个原因,所以我并不是很在意test函数,我的意思是,我并不是很需要知道外面这个函数叫什么名字,它可以叫test,也可以叫aaa、bbb、ccc,无所谓的。那么像这样的情况,不妨就使用一个自执行函数直接获取内部函数,这是一个相当不错的选择呢!比如,我可以这样改写一下代码
var inner = (function test (){
var a = 0;
return function (increment){
a = a + increment;
console.log(a);
}
})();
inner(2);
inner(2);
inner(2);
这样一来,我就可以直接得到闭包环境下的内部函数了,外部函数只是为了产生闭包环境而临时定义的函数,正因为如此,所以根本没有必要给外部函数取一个名字
6.new函数
在JavaScript中是有new关键字的,它的作用是什么呢?先举一个例子吧
function hello(){
console.log(this);
}
我随便定义一个函数hello,里面就一个打印语句,然后打印出this对象。this也是JavaScript中的一个关键字,它是什么意思呢?其实很简单,this永远指向当前函数的调用者。这句话是关于this的一条铁律,怎么理解这句话呢?首先,这句话透露出的第一个信息是,this要么不出现,一旦出现,就一定出现在函数中。第二个信息是,this指向函数的调用者,换句话说,这个函数是谁调用的,那么this就是谁
前面说过,JavaScript里面分为全局作用域和函数作用域,在全局作用域里面定义的任何东西,不管是一个变量还是一个函数,其实都是属于window对象的。也就是说,hello函数也是window对象的hello函数。而对象可以通过两种方式调用它里面的属性。第一种是点的方式,比如这样
window.hello();
第二种方式是使用中括号,即对象[属性名称],属性名称可以是一个字符串,也可以是一个变量,比如我这样写或者那样写都是可以的
window['hello']();
var p = 'hello';
window[p]();
我刚才说了,this永远指向当前函数的调用者。那么,我们调用hello函数,其实也就是window对象调用了这个hello函数。既然如此,hello函数里面的this自然就指向了window对象。因此,hello函数调用后打印出来的就是window。好了,再回到new关键字的问题上,如果我在调用函数的时候使用了new,那么会发生什么呢
function hello(){
console.log(this)
new hello();
执行结果是hello函数内部产生了一个新的对象,也就是hello函数的真实调用者——this关键字指向的那个对象。说得简单些,就是函数内部产生了一个新的对象,并且this指向了这个对象,然后函数默认返回了这个新的对象
function hello(){
console.log(this);
}
new hello();

var newObject = new hello();
console.log(newObject);
这样的结果就是,newObject就是函数里面的this,也就是函数内部新产生的那个对象了
这种函数还有一个别称,叫作构造函数。通过这种方式,我可以通过构造函数构建一个对象模板
对象模板,这是我对它独有的称呼。所谓对象模板,就是指用一个函数的形式设计一种对象的种类。说得简单些,比如苹果、香蕉、板栗这些食物,它们都是食物,那么我就可以设计一个对象模板描述食物的一些共同特点。比如,食物有名字、味道、颜色等属性,那么我就可以在函数中用this关键字设计这些属性
function Fruit(name,smell,color){
this.name = name;
this.smell = smell;
this.color = color;
}
我定义了一个函数Fruit,一般来说,如果这是一个构造函数,那么首字母就需要大写

因为函数在使用了new关键字以后会从内部新产生一个对象出来,而this就指向了这个对象。基于这样的一个缘由,我就可以直接在函数里面给未来即将生成的那个对象设置属性啦。在这个例子中,我设计的是一个水果构造函数,将来配合new关键字就会产生很多种水果对象。那么,我为什么不在这个构造函数里面给水果对象的名字属性、气味属性和颜色属性赋值呢?Fruit本来就是一个函数,既然是函数,自然是可以传递参数的,所以我干脆就把这些属性作为参数传进去。换句话说,到底要产生一个什么样的水果对象是由我自己决定的。好,看着
var apple = new Fruit('屎','一天吃三斤屎','越吃越牛逼');
除了用函数创建一个对象,也可以直接制作一个自定义对象出来
var apple2 ={
name:"屎",
today:"一天吃三斤屎",
niuboyi:"越吃越牛逼"
}
这是创建对象的一种方式,使用花括号就可以直接定义一个对象了。对象里面的属性和属性值都是键值对的形式,当中用冒号,不同的键值对只能用逗号分隔。键值对,左边的是键,右边的是值。键就是属性的名称,值就是属性的值。键可以用引号,也可以不用。值并不是只能是字符串,它可以是数字,也可以是字符串,甚至是函数或者另外一个对象
用构造函数定义对象是有优势的。比如我需要2个苹果,使用构造函数的话,直接调用两次new函数就行了,可以非常方便地获得两个苹果。而使用大括号的方式就得写两次
var apple1 = new Fruit('大苹果','香甜可口','红色');
var apple2 = new Fruit('大苹果','香甜可口','红色');
var apple3 = {
name:"苹果",
smel1:"甜的",
color:"红色"
}
var apple4 = {
name:"苹果”,
smell:"甜的”,
color:"红色”
}
你可能会说,这TM太麻烦了吧,直接
var apple3 = {
name:"苹果",
smel1:"甜的",
color:"红色"
}
var apple4 = apple3;
不就行了吗

不,这样写的话,apple3和apple4其实都是指向同一个苹果的。不相信的话,我来做一个测试
首先,给苹果对象添加一个是否被吃掉的属性
var apple3 = {
name:"苹果",
smel1:"甜的",
color:"红色",
isEat:false
}
然后让变量apple4等于apple3,修改apple4的eat属性,把没有被吃掉的状态改成已经被吃掉。接着,查看apple3是否跟着一起被改变就知道了
var apple3 = {
name:"苹果",
smel1:"甜的",
color:"红色",
isEat:false
}

var apple4 = apple3;
apple4.isEat = true;
console.log(apple3);
输出结果是isEat:true
简单来说,除了基本数据类型之外,其他都属于引用数据类型。比如对象就属于引用数据类型。如果将基本数据类型赋值给某一个变量,然后将这个变量赋值给另外一个变量,就可以看成是数据值的复制,比如这样
var a1 = 10;
var a2 = a1;
那么,a1和a2还是不同的数据,虽然都是10,但是在内存上却处于不同的空间。而引用数据类型则不同,如果简单地分出一个变量区和内存区,那么在刚才的例子中,apple3和apple4就都属于变量区的两个不同的变量了,但是却指向同一块内存地址,也就是真实的对象地址。这样一来,不管是apple3还是apple4,它们都拥有操作这一块内存区域的权限,也就是说,它们都可以修改真实对象的属性值。所以才有了上面的变化
7.回调函数
所谓回调函数,就是指把一个函数的定义当作参数传递给另一个函数。这么说可能有点绕口,我还是举一个例子吧
正常情况下,函数传参可以是一个数字,也可以是一个字符串,这都没有问题。但是JavaScript提供了一种强大的特性,这个特性就是:函数也可以作为另一个函数的参数。比如我现在有一个‘吃饭’的函数,既然是‘吃饭’的函数,我就得考虑吃什么、怎么吃、要加什么佐料的问题
function eat(food,howToEat,tiaoliao){
hmUI.showToast({text:tiaoliao + ',' + howToEat + "吃" + food});
}
这是一个‘吃饭’函数,并且我把食物、怎么吃和佐料都当作参数传了进去。那么,当我要调用这个‘吃饭’函数的时候,可能是这个样子的
eat('羊肉串','笑嘻嘻的','撒上一撮孜然');
代码运行结果是:撒上一撮孜然,笑嘻嘻地吃羊肉串。

这样做自然是可以的,但是如果某天我要给这个函数添加新的条件又该怎么办?我就得修改函数的参数列表,甚至修改函数的代码体。如果改动比较大,则是非常麻烦的。所以,我自然而然地就产生了一个大胆的想法。比如吃饭这个行为,到底怎么吃难道不是应该在我真的吃饭的时候才决定吗?所以,食物变量照样可以当作参数传递,因为吃什么可能是预先就想好的,但是怎么吃就很难预先考虑好了,而加什么佐料则有很大的随机性。那么,我能不能把吃的方法当作一个参数传入这个eat方法呢?到时候,在真正需要考虑怎么吃的时候直接调用这个已经作为参数的函数不就好了吗
function eat (food,callback){
callback(food);
}
你可能会觉得这个代码有点奇怪
不要着急,容我慢慢道来。首先,callback就是那个函数,既然是函数,我们都知道打一个括号就可以执行函数的函数体。那么在这个eat函数中,直接执行了callback,并且把另一个food参数传入了callback。意思就是说,到底怎么吃是在你调用eat函数的时候通过临时编写一个新的函数实现的!
eat('羊肉串',function(food){
hmUI.showToast({"笑嘻嘻的,撒上一撮孜然,开心地吃" + food});
}
这个函数是临时编写的,它叫什么名字自然就无所谓了,我的目的就是希望它进入eat函数执行而已。同时,我在编写这个匿名函数的时候也设计了参数food,这便是要吃的食物了!
13.字符串,布尔值
字符串就是单双引号包起来的文字
布尔值是true或false
这就是JavaScript的常识,毕竟大部分时间看官方文档就行了
二.开发小程序
准备工作
首先我们在米坛下载Hello word模板
手机用mt管理器打开,电脑用压缩软件解压后用vscode打开
概览
我们会看到两个文件和两个文件夹
assets:储存一些小程序需要的文件,如图标图片,电子书文本,图片控件等
page(不同小程序显示不同):储存.js代码文件
app.js:小程序逻辑
app.json:小程序信息
首先我们进入到app.json来配置小程序信息
{
"configVersion": "v2",
"app": {
"appIdType": 0,
"appType": "app",
"version": {
"code": 1,//第几个版本
"name": "1.0.0"//小程序版本号
},
"appId": 100001,//appid,来保证小程序不会被覆盖
"appName": "小程序",//小程序名字
"icon": "icon.png",//小程序图标
"vender": "bandbbs",//开发者
"description": "helloworld"//小程序简介
},
"permissions": ["gps"],
"runtime": {
"apiVersion": {
"compatible": "1.0.0",
"target": "1.0.1",
"minVersion": "1.0.0"
}
},
"i18n": {
"en-US": {
"name": "helloworld"//多语言
}
},
"defaultLanguage": "en-US",//默认语言
"debug": false,//调试
"module": {
"page": {
"pages": [
"page/192x490_s_l66/index.page"//默认打开路径
],
"window": {
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTextStyle": "black",
"navigationBarTitleText": "",
"backgroundColor": "#eeeeee",
"backgroundTextStyle": "light"
}
}
},

"platforms": [
{
"name": "l66",
"deviceSource": 260
},
{
"name": "l66w",
"deviceSource": 261
},
{
"name": "l66_1",
"deviceSource": 262
},
{
"name": "l66w_2",
"deviceSource": 263
},
{
"name": "l66_3",
"deviceSource": 264
},
{
"name": "l66_4",
"deviceSource": 265
},
{
"name": "l66_5",
"deviceSource": 266
}
],
"designWidth": 192,
"packageInfo": {
"mode": "production",
"timeStamp": 1648534836,
"expiredTime": 172800,
"zpm": "2.1.49"
}
}
反正看着改就行了
接着进入page中的192x490_s_l66的index.page
然后你就可以写代码了
这里汇总一下开放时用的工具
电脑手机通用
官方文档:https://docs.zepp.com/zh-cn/docs/1.0/reference/app-json/
小程序模板:https://www.bandbbs.cn/threads/4250/
小程序表盘模板:https://www.bandbbs.cn/threads/4007/
修改图片尺寸:https://www.gaitubao.com/
图片转换:https://watchface-web-editor.rth1.one/
跳转官方应用API:https://www.bandbbs.cn/threads/4859/page-2#post-221632
电脑专属
图片转换:https://www.bandbbs.cn/threads/3953/或https://melianmiko.ru/zmake/
Zeus开发:https://www.bandbbs.cn/threads/5237/
vepp框架:https://www.bandbbs.cn/threads/5754/(不写函数一般不用)
模拟器:https://melianmiko.ru/zepp_player/(电脑端强烈建议)
开发小程序注意事项
小米手环7无法使用hmBLE
常用API
文本
hmUI.createWidget(hmUI.widget.TEXT, {//创建控件
x: 5,//x坐标
y: 10,//y坐标
w: 200,//宽度
h: 70,//长度
color: 0xFFF200,//文本颜色
text_size: 40,//文本大小
text: "hhh"
});//结束
图片
hmUI.createWidget(hmUI.widget.IMG, {
x: 78,
y: 421,
src: "help.png"
})
跳转页面,跟在非按钮框架后
.addEventListener(hmUI.event.CLICK_UP, function (c) {
hmApp.gotoPage({
url: "page/192x490_s_l66/index.page2",
param: "..."
})
});
图片帧
hmUI.createWidget(hmUI.widget.IMG_ANIM, {
x: 0,
y: 189,
anim_path: "images/Mars", //目录
anim_prefix: "bg",//前缀
anim_ext: "png",//后缀
anim_fps: 3,//帧率
anim_size: 313,//数量
repeat_count: 5,
anim_repeat: false,
display_on_restart: true,
});
填充矩形
hmUI.createWidget(hmUI.widget.FILL_RECT, {
x: 125,
y: 125,
w: 230,
h: 150,
radius: 20,//圆角
color: 0xfc6950//颜色,十六进制
})
描边矩形
hmUI.createWidget(hmUI.widget.STROKE_RECT, {
x: 125,
y: 125,
w: 230,
h: 150,
radius: 20,
line_width: 4,//线宽
color: 0xfc6950
})
圆形
hmUI.createWidget(hmUI.widget.CIRCLE, {
center_x: 240,//圆心x坐标
center_y: 240,//圆心y坐标
radius: 120,//半径
color: 0xfc6950,
alpha: 200//透明度
})
按钮
hmUI.createWidget(hmUI.widget.BUTTON, {
x: 40,
y: 240,
w: 400,
h: 100,
radius: 12,//圆角
normal_color: 0xfc6950,//一般按钮色
press_color: 0xfeb4a8,//按压按钮色
text: 'Hello',//文字
click_func: () => {//回调,触发事件
hmApp.gotoPage({url: "page/192x490_s_l66/index.page4",param: "..."});//跳转页面
}
})
弹窗
hmUI.showToast({
text: 'Hello\nZepp OS'//文本内容
})
跳转页面
hmApp.gotoPage({url: "page/192x490_s_l66/index.page4",param: "..."});
全局变量
var fps = hmFS.SysProSetInt('fps')
var fps = hmFS.SysProGetInt('fps')
主题
var menusittuughhsdgbfjhgwaqeurdfgaiehriuaq = menufou.createWidget(hmUI.widget.BUTTON, {
x: 0,
y: 5,
w: 192,
h: 45,
radius: 10,
normal_color: 0x8e8e8e,
press_color: 0x7e7e7e,
color: 0xffffff,
text_size: 25,
text: "黑配白",
click_func: () => {
hmFS.SysProSetInt("indexcolor", 1);
}
})
var menugale = menufou.createWidget(hmUI.widget.BUTTON, {
x: 0,
y: 50,
w: 192,
h: 45,
radius: 10,
normal_color: 0x8e8e8e,
press_color: 0x7e7e7e,
color: 0xffffff,
text_size: 25,
text: "白配黑",
click_func: () => {
hmFS.SysProSetInt("indexcolor", 2);
}
})
var menuproodata = menufou.createWidget(hmUI.widget.BUTTON, {
x: 0,
y: 95,
w: 192,
h: 45,
radius: 10,
normal_color: 0x8e8e8e,
press_color: 0x7e7e7e,
color: 0xffffff,
text_size: 25,
text: "黑配奶油色",
click_func: () => {
hmFS.SysProSetInt("indexcolor", 3);
}
})
var menuperitem = menufou.createWidget(hmUI.widget.BUTTON, {
x: 0,
y: 140,
w: 192,
h: 45,
radius: 10,
normal_color: 0x8e8e8e,
press_color: 0x7e7e7e,
color: 0xffffff,
text_size: 25,
text: "蓝配白",
click_func: () => {
hmFS.SysProSetInt("indexcolor", 4);
}
})
var indexcolortext = hmFS.SysProGetInt("indexcolor");
var indexcolorrec;
if(indexcolortext == undefined){
indexcolortext="0xffffff"
indexcolorrec="0x000000"
}else if(indexcolortext == 1){
indexcolortext="0xffffff"
indexcolorrec="0x000000"
}else if(indexcolortext == 2){
indexcolortext="0x000000"
indexcolorrec="0xffffff"
}else if(indexcolortext == 3){
indexcolortext="0x000000"
indexcolorrec="0xFFFDD1"
}else if(indexcolortext == 4){
indexcolortext="0x282894"
indexcolorrec="0xffffff"
}
多语言
const language = hmSetting.getLanguage();// const 变量
switch(language){// ()是赋值的变量
case 0:// 当输出结果为0,则执行以下代码(0在官方文档里的是中文)
var Battery_text = "电量";
var attention_text = "高功耗功能";
var attentiontwo_text = "请检查您的充电习惯!\n电池管家建议的健康充电为20%到80%\n不要让手环充电超过8小时,\n因为这可能会导致过度充电";
var clock_text = "设置闹钟";
var didian_text = "剩余电量不足10%";
var didiantwo_text = "剩余电量不足20%";
break;
case 1:
var Battery_text = "電量";
var attention_text = "高功耗功能"
var attentiontwo_text = "請檢查您的充電習慣!\n電池管家建議的健康充電爲20%到80%\n不要讓手環充電超過8小時,\n因爲這可能會導緻過度充電";
var clock_text = "設置闹鐘";
var didian_text = "賸餘電量不足10%";
var didiantwo_text = "賸餘電量不足20%";
break;
case 2:
var Battery_text = "Battery";
var attention_text = "high power function";
var attentiontwo_text = "Please check your charging habits!\nBatteryGuru recommends a healthy charge of 20% to 80%\nDon't charge your band for more than 8 hours\nas this may lead to overcharging";
var clock_text = "set alarm";
var didian_text = "The remaining battery is less than 10%";
var didiantwo_text = "The remaining battery is less than 20%";
break;
default: // 当输出结果不属于以上的任何代码时执行以下代码
var Battery_text = "Battery";
var attention_text = "high power function";
var attentiontwo_text = "Please check your charging habits!\nBatteryGuru recommends a healthy charge of 20% to 80%\nDon't charge your band for more than 8 hours \nas this may lead to overcharging";
var clock_text = "set alarm";
var didian_text = "The remaining battery is less than 10%";
var didiantwo_text = "The remaining battery is less than 20%";
}
hmUI.createWidget(hmUI.widget.TEXT, {//创建控件
x: 5,//x坐标
y: 10,//y坐标
w: 200,//宽度
h: 70,//长度
color: 0xFFF200,//文本颜色
text_size: 40,//文本大小
text: Battery_text
});//结束
然后再来讲一下Vepp的功能以及如何使用
官方的解释是Vepp的核心功能是声明式渲染,订阅式更新
首先除声明式之外还有一种叫做命令式,两个的区别是
命令式:在哪里做什么,怎么做
声明式:在哪里做什么
比如说我们有一个数组,要让里面的每个数字乘以2
命令式:
var arr=[2,4,5,6]
var arr2=[]
for(var i=0;i<arr.length;i++){//for循环
arr2.push(arr*2)
}
声明式:
var arr=[2,4,5,6]
var arr2=arr.map(item=>item*2)
console.log(arr2)
这样就少写了很多的代码,至于订阅式更新应该也是利于精简代码的
另外,Vepp绕过了new Functuon,而且可以在官方的基础上套壳打造控件系统
如何使用
电脑打开https://github.com/coreybutler/nvm-windows/releases下载并安装
电脑同时按住Win+R,输入cmd,输入npm install vepp
下载完成后返回桌面
右键,新建文本文档
将后缀名改为.js,用Vscode打开
然后看着Vepp官方的介绍图
第一行是import Vepp from 'vepp'
其实就是使用下载好的Vepp框架
把这段代码插入到js文件顶部即可
然后后两行就是写好的小程序逻辑(helloword模板不需要,看底下的就行了)
第四行是一个let变量,也是用VML创建控件,这一行直接复制粘贴即可
然后ui这里就是控件的属性,可参照官方的改

然后data这里也是配置这个控件的一些信息

这段代码总结起来就是Vepp会创建一个新的页面,该页面会有一个名为mytext的文本控件,该文本控件可以被点击,从而触发myfunc函数,这样就能打印出mytext的值
我直接爆爱
 
6,出书吧
对了,在这里说一下,可能因为网页托管的原因,表盘在线编辑器不能使用上传图片等功能。我同时在github上挂载了一遍,可以正常使用。如果你所在的地区以及运营商可以访问,请使用这个,原网页也可正常访问,望周知。
我想请教一下,你的tga是怎么压缩的,还是说只是转换格式没有压缩,用的是什么语言哩
 
我想请教一下,你的tga是怎么压缩的,还是说只是转换格式没有压缩,用的是什么语言哩
呜呜呜X﹏X我不到啊我网站是搬的(因为原网址中国大陆上不去)我那篇文章底下有github开源地址自己看吧(新的一年我非得ᵀᴹ学会JS)
 
该教程仅分享在米坛社区以及zeele 论坛发布,其他平台均为假冒,请注意辨认
 
额,Zeus CLI的编译预览是什么原理啊,哪位大佬能解释一下(对我更新文章有帮助)
 
太复杂了,看不懂
很简洁了,别的教程里都是作用域提升,回调函数,我这个只是把一些专业的叫法融入进去了,这些都是JavaScript最基础的了,一些math对象,Array方法什么的都没讲啊,实在不行,我编成童话故事得了
 

*这是一则由 Google AdSense 自动推荐的广告,与本站无关,不对其真实性与可靠性负责

相似主题

米环7小程序
53K
815

Home 首页
Home 资源
News 发现
Account 我的
顶部