条件停止。当(If)条件为真时停止(stop)执行后续逻辑(即终止事件执行),取而代之去执行表达式(如果有,后端运行时执行结果将返回前端)。即使此表达式是在循环/$exp/函数里也一样,但除了异步函数外。
同步执行(execute)表达式,多个表达式字符串用分号;
隔开,先后依次执行,等待上一个表达式执行完成后才执行下一个。
环境是个对象,可选,将与当前上下文数据$ctx合并后给表达式使用。
异步执行表达式,不阻塞当前线程;不等待上一个表达式执行完成马上执行下一个。
A表示异步(Async)。参考异步函数。
多次执行表达式,$x是当前执行次数,从0次开始。
把表达式作为函数体包装成同步执行的函数,它会等待表达式执行完成后才返回(所以实际返回的是承诺Promise),适合在事件中使用(不应该用在页面展示中使用,否则会造成页面卡顿),比如读取数据库需要花费较长时间:$v.查询 = fx('$v.商品 = $product.find({ type: "商品" })')
。
调用函数时传入的参数可以通过$args
数组读取,第一个参数也可以通过$arg
读取,如果传入的第一个参数是个对象则可以直接访问对象里的值,大多数时候是直接把当前执行上下文传进去:$v.查询($ctx)
。
用法同上,但包装成异步执行的函数,它不等待表达式内耗时的任务的执行就直接返回,所以不会造成页面卡顿,可以用在页面展示中。它适合需要立即返回结果的场景,比如把它作为另一个函数的参数。
上面例子如果用fxA()包装,那它里面的$v.商品
将取不到查询结果(实际得到的是Promise)。
exc()和fx()会等待内部耗时任务的执行,自己返回Promise
excA()和fxA()则不等待,自己有返回值,内部耗时任务返回Promise
参考异步函数。
直接执行exc(表达式)与函数调用$v.函数 = fx(表达式); $v.函数()的异同
用法不同
第一种是在当前环境直接执行表达式。第二种是先定义成函数(即把表达式封装成函数)再执行。
传参不同
第一种通过传入环境对象合并到其执行环境中,表达式直接取用;第二种通过传入任意数量的参数,函数体通过$args数组及其参数位置下标取得。
受stopIf()的影响不同
stopIf()里的条件为真时第一种会立刻停止所有表达式的执行,不管是exc()被执行体内部的表达式还是当前执行体外部表达式。而第二种仅会停止函数体内部后续表达式的执行而不会影响调用它的当前环境外部后续的表达式的执行。当然,如果是异步执行(excA)则与第二种相同。
执行上下文不同
函数的执行上下文来自于被调用时传入的第一个参数和其定义的地方的上下文,而执行表达式是直接把表达式拿到当前上下文执行,无论它是哪里定义的。
当需要被多个地方多次执行时推荐使用函数;如果只是临时执行一下,比如符合某种条件时执行两三句表达式时推荐用直接执行。
比如一个组件C的事件中要执行在页面ready中定义的内部表达式$exp.A,而$exp.A又需要执行另一个内部表达式$exp.B。
如果是第一种方式,需要先把ready定义的内部表达式转换成作用域更大的变量中(如页面表达式),$v.A = $exp.A; $v.B = $exp.B,在$exp.A里应该用$v.B而不是$exp.B,因为组件C不认识ready的内部表达式$exp.B,这样在组件C执行exc($v.A)时就好像$exp.A和$exp.B都是在组件C中定义的一样。但此时$exp.A和$exp.B里要谨慎使用stopIf()
如果是第二种方式,需要先把$exp.A封装成函数$v.A = fx($exp.A),在组件C中调用$v.A()即可。但要注意$exp.A和$exp.B拿到的上下文数据都是ready的而不是组件C的。此时$exp.A或$exp.B中的stopIf()并不会阻住组件C继续执行函数后面的表达式。