美文网首页
【译】FuseJS简介(上)

【译】FuseJS简介(上)

作者: 赵赵811 | 来源:发表于2015-12-28 23:29 被阅读0次

官网原文:https://www.fusetools.com/learn/fusejs

FuseJS简介

FuseJS 是一个用来给跨平台App写业务逻辑的JavaScript框架。

提示:目前FuseJS还不支持输出WebGL。

起步

FuseJS代码有两种用法,一是可以嵌入在UX标记文件里的<JavaScript>标签内,二是外链JavaScript文件,就像这样:

<JavaScript File="SomeCode.js" />

代码嵌入的例子:

<JavaScript>
    console.log("Hello, FuseJS!");
</JavaScript>

模块 Modules

FuseJS执行的是CommonJS模块化系统的规范,每个代码文件或嵌入的代码段都是一个模块。

如果想要模块内的东西为外部可见,需要使用module.exports构造器:

<JavaScript>
    module.exports = {
        exportedSymbol: "Hello, rest of the world!"
    };
</JavaScript>

模块内没有通过module.exports输出的定义数据,则在外部不能直接访问:

<JavaScript>
    var data = [1, 2, 3];
    var invisible = "I'm invisible";

    module.exports = {
        data: data
    };
</JavaScript>

有时对其它JavaScript模块和UX代码的调用需要隐藏执行细节,这就起作用了。

导入模块

每个代码文件或嵌入的代码块都是一个模块。在JavaScript标签内加上一个模块并赋予ux:Global属性,其它模块就可以通过require导入该模块,如下例所示:

<JavaScript File="parse-1.5.0.min.js" ux:Global="Parse" />

同一个项目内的其它模块想要导入上例模块时,代码如下:

var Parse = require("Parse").Parse;

备注:目前只通过JS文件路径的话,还不能直接引用该模块,我们正在解决,请耐心等待!

具体示例:TODO App with Parse backend example

设计与动力

FuseJS的关键设计目标是使代码短小、干净并且只专注于App的实用功能,而那些UX导向的功能,如Layout、数据呈现、动画和手势回馈都留给UX声明标记和原生UI组件去解决。

在Fuse中,JavaScript写业务逻辑而UX标记负责呈现,这么分开的做法有如下明显的益处:

  • 性能 - 所有对性能要求高的任务都交给原生代码和原生UI组件搞定
  • 简单 - 声明代码易写、易读、易理解,甚至对编程不胜了解的人也能做到(易学)
  • 少犯错 - 少的声明意味着出事儿的机率少
    • 可视化工具 - Fuse有inspectortimelines等“拖放即可”的工具用来编辑UX标记。

注意Fuse有非常多的声明API(就是设计好的UX标记)可以代替JavaScript代码能做的任务,比如可控制的动画效果。

很多其他JavaScript框架将命令式的UI代码、动画和高性能要求的任务统统混入JavaScript,因此有些FuseJS的新手开始的时候也试着在Fuse中这么做,技术上的确有可能,但我们并不鼓励这么做。我们推荐新手花些时间研究Fuse官网的示例,找找用新方式做事的感觉。

用"view"(UX标记)和"logic"(JavaScript)分开的方式净化代码,这么做可以大大减少代码量,且更容易维护,还可以让UX设计师与程序员有效的分工合作。

如果你需要写高性能要求的业务逻辑,我们推荐你用原生代码写,或者用Uno,而不要用Javascript。

Observables(观察量?)

Observables(还是不翻译了,Observable是Fuse中一种特别的变量,用来处理数据变化的。)

Observables是一个FuseJS应用中的关键成分,主要处理数据绑定、反应式(Reactive)编程和异步编程。

一个Observable代表了一个可被观察的值,在Fuse里,Observables主要用于在JavaScript代码与UX标记之间做数据绑定。

Observables可以保存一个单独的值,也可以是一个0或多个元素的值的列表。当Observable里的值发生变化,它的subscribers(订户)就会收到通知。

Observables支持反应式(Reactive)编程和异步编程,极大简化了数据驱动的UI编程。

如何导入

var Observable = require('FuseJS/Observable');

基础用法

要创建一个Observable,首先需要调用Observable函数,初始值可以是0到多个。

  • Observable(<initial values>) - 构造函数

示例:

var emptyObservable = Observable();
var isSomethingEnabled = Observable(true);

如果Observable的初始值为空,则其.value === undefined.length === 0

Observable的值

如果Observable只有一个值,我们可以用.value属性来getset这个值:

var someString = Observable('foobar');
Console.Log(someString.value); // prints 'foobar'
someString.value = 'barfoo'; // sets the value, notifies subscribers.

当用.value属性设定了一个值后,所有订户都会被通知。

Observable 值列表

如果使用Observable保存一个值列表(多个值),我们可以用.add(item).remove(item)方法来操控这些值。

下例是用.length属性查询列表里值的数量:

var friends = Observable('Jake', 'Jane', 'Joe');
Console.Log(friends.length); // prints 3

friends.add('Gina');
Console.Log(friends.length); // prints 4

Observable函数

当用一个函数作为唯一的参数来初始化一个Observable时,它的.value的值是评估该函数后计算生成的。

当函数估值时,所有反应式依赖(Reactive dependencies)都会用所有其它关联Observables的值自动生成。

示例:

var firstName = Observable('John');
var lastName = Observable('Doe');

var fullName = Observable(function() {
    return firstName.value + ' ' + lastName.value;
})

上例中,如果firstNamelastName发生变化,fullName就会随之自动更新。

对,就这么神奇。

成员 Members

值的操作符 Value operators

value

该属性可以取得或设置当前Observable的值。

.value属性实际上相当于getAt(0)replaceAt(0)的简写,通常是用于单一值的Observerable,虽然这不一定是必须的。

if (isSomethingEnabled.value) {
    doSomething();
}
isSomethingEnabled.value = false;

值列表的操作符 List operators

length

该属性返回Observable值的总数。

var fruits = Observable('Orange', 'Apple', 'Pear');
Console.Log(fruits.length); //output: 3
getAt(index)

该属性返回给定索引位置的值。

var seasons = Observable('Summer', 'Fall', 'Winter', 'Spring');
Console.Log(seasons.getAt(2)); //output: 'Winter'
add(value)

Observables的值列表里添加值。

var colors = Observable('Red', 'Green');
colors.add('Blue');
remove(value)

Observable的值列表里删除首个 remove给出的值。

var shapes = Observable('Round', 'Square', 'Rectangular');
shapes.remove('Rectangular');
tryRemove(value)

试着从Observable的值列表里删除首个tryRemove给出的值,如果成功,返回true, 否则,返回false

var shapes = Observable("Round", "Square", "Rectangular");
if(shapes.tryRemove("Rectangular")) {
    Console.Log("success");
}
removeAt(index)
removeAt(index)

删除给定索引位置的值。

var shapes = Observable('Round', 'Square', 'Rectangular');
shapes.removeAt(2);
removeWhere(func)

用一个函数遍历值列表里的值,删除满足条件(func返回true的)的所有的值。

var hotPlaces = Observable(
    {name: "Oslo", temperature: 30},
    {name: "New York", temperature: 24},
    {name: "California", temperature: 27},
    {name: "Sydney", temperature: 10}
).removeWhere(function(place){
    return place.temperature < 20;
}); //Removes Sydney from the list
forEach(func)

Observerable值列表里的每个值调用一遍给定的函数。

var numbers = Observable(10, 2, 50, 3);
numbers.forEach(function(number) {
    Console.Log(number + " is a nice number!");
});
replaceAt(index, value)

把给定索引位置的值替换为新值。

var ingredients = Observable('sugar', 'milk', 'potato');
ingredients.replaceAt(2, 'flour'); //Replaces 'potato' with 'flour'
replaceAll(array)

Observable里的所有值全部替换为给定数组里的值。

var colors = Observable("Red", "Green", "Blue");
colors.replaceAll(["Orange", "Cyan", "Pink"]);
clear()

清除Observable里所有的值。

var colors = Observable("Red", "Green");
colors.clear();
indexOf(value)

Observable里找到首个给定的值,返回其索引位置。

var seasons = Observable("Summer", "Fall", "Winter", "Spring");
var index = seasons.indexOf("Winter"); // 2
contains(value)

如果变量里存在给定的值,返回true

Observable seasons = Observable("Summer", "Fall", "Winter", "Spring");
var winterExists = seasons.contains("Winter"); // true
refreshAll(newValues, compareFunc, updateFunc, mapFunc)

一共四个参数,第一个newValues用于更新Observable里所有项,基于什么条件要看后面的函数,第二个compareFunc函数用于比较两个项是否相等,如果发现相等则应用第三个函数updateFunc, 将现有项替换为新值,最后一个mapFunc函数将新发现的项映射到新的对象中。

var items = Observable({
    {id: 1, text: "one" },
    {id: 2, text: "two" },
    {id: 3, text: "tres" },
})
var newItems = [
    {id: 3, text: "three" },
    {id: 4, text: "four" },
    {id: 5, text: "five" }
]
items.refreshAll(newItems, 
    //Compare on ID
    function(oldItem, newItem){
        return oldItem.id == newItem.id;
    },
    // Update text
    function(oldItem, newItem){
        oldItem.text.value = newItem.text;
    },
    // Map to object with an observable version of text
    function(newItem){
        return { id:newItem.id, Observable(newItem.text)
    }
);

相关文章

网友评论

      本文标题:【译】FuseJS简介(上)

      本文链接:https://www.haomeiwen.com/subject/swtihttx.html