Sep12

【原创】如何在微信小程序开发中正确的使用vant ui组件

Author: leeon  Click: 3304   Comments: 1 Category: 程序语言  Tag: 微信小程序,weapp,vant

微信小程序终于可以支持npm导入第三方库了(https://developers.weixin.qq.com/miniprogram/dev/devtools/npm.html),但是这种导入模式和使用模式有别于我们使用的npm调用。今天我按照有赞新出的vant小程序ui库来讲解如何导入npm资源。

第一步:

在小程序工程的根目录下执行:

npm i vant-weapp -S --production

第二步:

保证当前你的微信开发者工具是最新版本,然后点击执行“构建npm“


构建成功后会提示:



同时项目根目录中会多出一个目录“miniprogram_npm”,这个就是小程序可以识别的npm第三方库。



第三步:

这时候当我们需要在一个页面中调用vant组件,那么就要在对应的页面json中添加类似如下配置:


{
"usingComponents":{
"van-button":"/miniprogram_npm/vant-weapp/button/index"
}
}
接着你就可以在wxml中直接调用这个ui组件了。

注意,对于vant库来说其实你并不需要在页面对应的js中require vant-weapp组件。
Feb20

Lua C API中文函数手册

Author: 云风  Click: 11380   Comments: 0 Category: 程序语言  Tag: lua,c,api,function,manual

lua_Alloc

typedef void * (*lua_Alloc) (void *ud,
                             void *ptr,
                             size_t osize,
                             size_t nsize);

Lua 状态机中使用的内存分配器函数的类型。内存分配函数必须提供一个功能类似于 realloc 但又不完全相同的函数。它的参数有 ud ,一个由 lua_newstate 传给它的指针; ptr ,一个指向已分配出来或是将被重新分配或是要释放的内存块指针; osize ,内存块原来的尺寸; nsize ,新内存块的尺寸。如果且只有 osize 是零时,ptrNULL 。当 nsize 是零,分配器必须返回 NULL;如果 osize 不是零,分配器应当释放掉 ptr 指向的内存块。当 nsize 不是零,若分配器不能满足请求时,分配器返回 NULL 。当 nsize 不是零而 osize 是零时,分配器应该和 malloc 有相同的行为。当 nsizeosize 都不是零时,分配器则应和 realloc 保持一样的行为。 Lua 假设分配器在 osize >= nsize 时永远不会失败。

这里有一个简单的分配器函数的实现。这个实现被放在补充库中,由 luaL_newstate 提供。

     static void *l_alloc (void *ud, void *ptr, size_t osize,
                                                size_t nsize) {
       (void)ud;  (void)osize;  /* not used */
       if (nsize == 0) {
         free(ptr);
         return NULL;
       }
       else
         return realloc(ptr, nsize);
     }

这段代码假设 free(NULL) 啥也不影响,而且 realloc(NULL, size) 等价于 malloc(size)。这两点是 ANSI C 保证的行为。


lua_atpanic

lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf);

设置一个新的 panic (恐慌) 函数,并返回前一个。

如果在保护环境之外发生了任何错误, Lua 就会调用一个 panic 函数,接着调用 exit(EXIT_FAILURE),这样就开始退出宿主程序。你的 panic 函数可以永远不返回(例如作一次长跳转)来避免程序退出。

panic 函数可以从栈顶取到出错信息。


lua_call

void lua_call (lua_State *L, int nargs, int nresults);

调用一个函数。

要调用一个函数请遵循以下协议:首先,要调用的函数应该被压入堆栈;接着,把需要传递给这个函数的参数按正序压栈;这是指第一个参数首先压栈。最后调用一下 lua_callnargs 是你压入堆栈的参数个数。当函数调用完毕后,所有的参数以及函数本身都会出栈。而函数的返回值这时则被压入堆栈。返回值的个数将被调整为 nresults 个,除非 nresults 被设置成 LUA_MULTRET。在这种情况下,所有的返回值都被压入堆栈中。 Lua 会保证返回值都放入栈空间中。函数返回值将按正序压栈(第一个返回值首先压栈),因此在调用结束后,最后一个返回值将被放在栈顶。

被调用函数内发生的错误将(通过 longjmp)一直上抛。

下面的例子中,这行 Lua 代码等价于在宿主程序用 C 代码做一些工作:

     a = f("how", t.x, 14)

这里是 C 里的代码:

     lua_getfield(L, LUA_GLOBALSINDEX, "f");          /* 将调用的函数 */
     lua_pushstring(L, "how");                          /* 第一个参数 */
     lua_getfield(L, LUA_GLOBALSINDEX, "t");          /* table 的索引 */
     lua_getfield(L, -1, "x");         /* 压入 t.x 的值(第 2 个参数)*/
     lua_remove(L, -2);                           /* 从堆栈中移去 't' */
     lua_pushinteger(L, 14);                           /* 第 3 个参数 */
     lua_call(L, 3, 1); /* 调用 'f',传入 3 个参数,并索取 1 个返回值 */
     lua_setfield(L, LUA_GLOBALSINDEX, "a");      /* 设置全局变量 'a' */

注意上面这段代码是“平衡”的:到了最后,堆栈恢复成原由的配置。这是一种良好的编程习惯。


lua_CFunction

typedef int (*lua_CFunction) (lua_State *L);

C 函数的类型。

为了正确的和 Lua 通讯,C 函数必须使用下列定义了参数以及返回值传递方法的协议: C 函数通过 Lua 中的堆栈来接受参数,参数以正序入栈(第一个参数首先入栈)。因此,当函数开始的时候, lua_gettop(L) 可以返回函数收到的参数个数。第一个参数(如果有的话)在索引 1 的地方,而最后一个参数在索引 lua_gettop(L) 处。当需要向 Lua 返回值的时候,C 函数只需要把它们以正序压到堆栈上(第一个返回值最先压入),然后返回这些返回值的个数。在这些返回值之下的,堆栈上的东西都会被 Lua 丢掉。和 Lua 函数一样,从 Lua 中调用 C 函数也可以有很多返回值。

下面这个例子中的函数将接收若干数字参数,并返回它们的平均数与和:

     static int foo (lua_State *L) {
       int n = lua_gettop(L);    /* 参数的个数 */
       lua_Number sum = 0;
       int i;
       for (i = 1; i <= n; i++) {
         if (!lua_isnumber(L, i)) {
           lua_pushstring(L, "incorrect argument");
           lua_error(L);
         }
         sum += lua_tonumber(L, i);
       }
       lua_pushnumber(L, sum/n);   /* 第一个返回值 */
       lua_pushnumber(L, sum);     /* 第二个返回值 */
       return 2;                   /* 返回值的个数 */
     }

lua_checkstack

int lua_checkstack (lua_State *L, int extra);

确保堆栈上至少有 extra 个空位。如果不能把堆栈扩展到相应的尺寸,函数返回 false 。这个函数永远不会缩小堆栈;如果堆栈已经比需要的大了,那么就放在那里不会产生变化。


lua_close

void lua_close (lua_State *L);

销毁指定 Lua 状态机中的所有对象(如果有垃圾收集相关的元方法的话,会调用它们),并且释放状态机中使用的所有动态内存。在一些平台上,你可以不必调用这个函数,因为当宿主程序结束的时候,所有的资源就自然被释放掉了。另一方面,长期运行的程序,比如一个后台程序或是一个 web 服务器,当不再需要它们的时候就应该释放掉相关状态机。这样可以避免状态机扩张的过大。


lua_concat

void lua_concat (lua_State *L, int n);

连接栈顶的 n 个值,然后将这些值出栈,并把结果放在栈顶。如果 n 为 1 ,结果就是一个字符串放在栈上(即,函数什么都不做);如果 n 为 0 ,结果是一个空串。 连接依照 Lua 中创建语义完成(参见 §2.5.4 )。


lua_cpcall

int lua_cpcall (lua_State *L, lua_CFunction func, void *ud);

以保护模式调用 C 函数 funcfunc 只有能从堆栈上拿到一个参数,就是包含有 ud 的 light userdata。当有错误时, lua_cpcall 返回和 lua_pcall 相同的错误代码,并在栈顶留下错误对象;否则它返回零,并不会修改堆栈。所有从 func 内返回的值都会被扔掉。


lua_createtable

void lua_createtable (lua_State *L, int narr, int nrec);

创建一个新的空 table 压入堆栈。这个新 table 将被预分配 narr 个元素的数组空间以及 nrec 个元素的非数组空间。当你明确知道表中需要多少个元素时,预分配就非常有用。如果你不知道,可以使用函数 lua_newtable


lua_dump

int lua_dump (lua_State *L, lua_Writer writer, void *data);

把函数 dump 成二进制 chunk 。函数接收栈顶的 Lua 函数做参数,然后生成它的二进制 chunk 。若被 dump 出来的东西被再次加载,加载的结果就相当于原来的函数。当它在产生 chunk 的时候,lua_dump 通过调用函数 writer (参见 lua_Writer)来写入数据,后面的 data 参数会被传入 writer

最后一次由写入器 (writer) 返回值将作为这个函数的返回值返回; 0 表示没有错误。

这个函数不会把 Lua 返回弹出堆栈。


lua_equal

int lua_equal (lua_State *L, int index1, int index2);

如果依照 Lua 中 == 操作符语义,索引 index1index2 中的值相同的话,返回 1 。否则返回 0 。如果任何一个索引无效也会返回 0。


lua_error

int lua_error (lua_State *L);

产生一个 Lua 错误。错误信息(实际上可以是任何类型的 Lua 值)必须被置入栈顶。这个函数会做一次长跳转,因此它不会再返回。(参见 luaL_error)。


lua_gc

int lua_gc (lua_State *L, int what, int data);

控制垃圾收集器。

这个函数根据其参数 what 发起几种不同的任务:

  • LUA_GCSTOP: 停止垃圾收集器。
  • LUA_GCRESTART: 重启垃圾收集器。
  • LUA_GCCOLLECT: 发起一次完整的垃圾收集循环。
  • LUA_GCCOUNT: 返回 Lua 使用的内存总量(以 K 字节为单位)。
  • LUA_GCCOUNTB: 返回当前内存使用量除以 1024 的余数。
  • LUA_GCSTEP: 发起一步增量垃圾收集。步数由 data 控制(越大的值意味着越多步),而其具体含义(具体数字表示了多少)并未标准化。如果你想控制这个步数,必须实验性的测试 data 的值。如果这一步结束了一个垃圾收集周期,返回返回 1 。
  • LUA_GCSETPAUSE:data/100 设置为 garbage-collector pause 的新值(参见 §2.10)。函数返回以前的值。
  • LUA_GCSETSTEPMUL:arg/100 设置成 step multiplier (参见 §2.10)。函数返回以前的值。

lua_getallocf

lua_Alloc lua_getallocf (lua_State *L, void **ud);

返回给定状态机的内存分配器函数。如果 ud 不是 NULL ,Lua 把调用 lua_newstate 时传入的那个指针放入 *ud


lua_getfenv

void lua_getfenv (lua_State *L, int index);

把索引处值的环境表压入堆栈。


lua_getfield

void lua_getfield (lua_State *L, int index, const char *k);

t[k] 值压入堆栈,这里的 t 是指有效索引 index 指向的值。在 Lua 中,这个函数可能触发对应 "index" 事件的元方法(参见 §2.8)。


lua_getglobal

void lua_getglobal (lua_State *L, const char *name);

把全局变量 name 里的值压入堆栈。这个是用一个宏定义出来的:

     #define lua_getglobal(L,s)  lua_getfield(L, LUA_GLOBALSINDEX, s)

lua_getmetatable

int lua_getmetatable (lua_State *L, int index);

把给定索引指向的值的元表压入堆栈。如果索引无效,或是这个值没有元表,函数将返回 0 并且不会向栈上压任何东西。


lua_gettable

void lua_gettable (lua_State *L, int index);

t[k] 值压入堆栈,这里的 t 是指有效索引 index 指向的值,而 k 则是栈顶放的值。

这个函数会弹出堆栈上的 key (把结果放在栈上相同位置)。在 Lua 中,这个函数可能触发对应 "index" 事件的元方法(参见 §2.8)。


lua_gettop

int lua_gettop (lua_State *L);

返回栈顶元素的索引。因为索引是从 1 开始编号的,所以这个结果等于堆栈上的元素个数(因此返回 0 表示堆栈为空)。


lua_insert

void lua_insert (lua_State *L, int index);

把栈顶元素插入指定的有效索引处,并依次移动这个索引之上的元素。不要用伪索引来调用这个函数,因为伪索引不是真正指向堆栈上的位置。


lua_Integer

typedef ptrdiff_t lua_Integer;

这个类型被用于 Lua API 接收整数值。

缺省时这个被定义为 ptrdiff_t ,这个东西通常是机器能处理的最大整数类型。


lua_isboolean

int lua_isboolean (lua_State *L, int index);

当给定索引的值类型为 boolean 时,返回 1 ,否则返回 0 。


lua_iscfunction

int lua_iscfunction (lua_State *L, int index);

当给定索引的值是一个 C 函数时,返回 1 ,否则返回 0 。


lua_isfunction

int lua_isfunction (lua_State *L, int index);

当给定索引的值是一个函数( C 或 Lua 函数均可)时,返回 1 ,否则返回 0 。


lua_islightuserdata

int lua_islightuserdata (lua_State *L, int index);

当给定索引的值是一个 light userdata 时,返回 1 ,否则返回 0 。


lua_isnil

int lua_isnil (lua_State *L, int index);

当给定索引的值是 nil 时,返回 1 ,否则返回 0 。


lua_isnumber

int lua_isnumber (lua_State *L, int index);

当给定索引的值是一个数字,或是一个可转换为数字的字符串时,返回 1 ,否则返回 0 。


lua_isstring

int lua_isstring (lua_State *L, int index);

当给定索引的值是一个字符串或是一个数字(数字总能转换成字符串)时,返回 1 ,否则返回 0 。


lua_istable

int lua_istable (lua_State *L, int index);

当给定索引的值是一个 table 时,返回 1 ,否则返回 0 。


lua_isthread

int lua_isthread (lua_State *L, int index);

当给定索引的值是一个 thread 时,返回 1 ,否则返回 0 。


lua_isuserdata

int lua_isuserdata (lua_State *L, int index);

当给定索引的值是一个 userdata (无论是完整的 userdata 还是 light userdata )时,返回 1 ,否则返回 0 。


lua_lessthan

int lua_lessthan (lua_State *L, int index1, int index2);

如果索引 index1 处的值小于索引 index2 处的值时,返回 1 ;否则返回 0 。其语义遵循 Lua 中的 < 操作符(就是说,有可能调用元方法)。如果任何一个索引无效,也会返回 0 。


lua_load

int lua_load (lua_State *L,
              lua_Reader reader,
              void *data,
              const char *chunkname);

加载一个 Lua chunk 。如果没有错误, lua_load 把一个编译好的 chunk 作为一个 Lua 函数压入堆栈。否则,压入出错信息。 lua_load 的返回值可以是:

这个函数仅仅加栽 chunk ;而不会去运行它。

lua_load 会自动检测 chunk 是文本的还是二进制的,然后做对应的加载操作(参见程序 luac)。

lua_load 函数使用一个用户提供的 reader 函数来读取 chunk (参见 lua_Reader)。 data 参数会被传入读取器函数。

chunkname 这个参数可以赋予 chunk 一个名字,这个名字被用于出错信息和调试信息(参见 §3.8)。


lua_newstate

lua_State *lua_newstate (lua_Alloc f, void *ud);

创建的一个新的独立的状态机。如果创建不了(因为内存问题)返回 NULL 。参数 f 是一个分配器函数; Lua 将通过这个函数做状态机内所有的内存分配操作。第二个参数 ud ,这个指针将在每次调用分配器时被直接传入。


lua_newtable

void lua_newtable (lua_State *L);

创建一个空 table ,并将之压入堆栈。它等价于 lua_createtable(L, 0, 0)


lua_newthread

lua_State *lua_newthread (lua_State *L);

创建一个新线程,并将其压入堆栈,并返回维护这个线程的 lua_State 指针。这个函数返回的新状态机共享原有状态机中的所有对象(比如一些 table),但是它有独立的执行堆栈。

没有显式的函数可以用来关闭或销毁掉一个线程。线程跟其它 Lua 对象一样是垃圾收集的条目之一。


lua_newuserdata

void *lua_newuserdata (lua_State *L, size_t size);

这个函数分配分配一块指定大小的内存块,把内存块地址作为一个完整的 userdata 压入堆栈,并返回这个地址。

userdata 代表 Lua 中的 C 值。完整的 userdata 代表一块内存。它是一个对象(就像 table 那样的对象):你必须创建它,它有着自己的元表,而且它在被回收时,可以被监测到。一个完整的 userdata 只和它自己相等(在等于的原生作用下)。

当 Lua 通过 gc 元方法回收一个完整的 userdata 时, Lua 调用这个元方法并把 userdata 标记为已终止。等到这个 userdata 再次被收集的时候,Lua 会释放掉相关的内存。


lua_next

int lua_next (lua_State *L, int index);

从栈上弹出一个 key(键),然后把索引指定的表中 key-value(健值)对压入堆栈(指定 key 后面的下一 (next) 对)。如果表中以无更多元素,那么 lua_next 将返回 0 (什么也不压入堆栈)。

典型的遍历方法是这样的:

     /* table 放在索引 't' 处 */
     lua_pushnil(L);  /* 第一个 key */
     while (lua_next(L, t) != 0) {
       /* 用一下 'key' (在索引 -2 处) 和 'value' (在索引 -1 处) */
       printf("%s - %s\n",
              lua_typename(L, lua_type(L, -2)),
              lua_typename(L, lua_type(L, -1)));
       /* 移除 'value' ;保留 'key' 做下一次迭代 */
       lua_pop(L, 1);
     }

在遍历一张表的时候,不要直接对 key 调用 lua_tolstring ,除非你知道这个 key 一定是一个字符串。调用