xinglie / xinglie.github.io

blog
https://xinglie.github.io
153 stars 22 forks source link

magix的API设计 #99

Open xinglie opened 2 years ago

xinglie commented 2 years ago

magix5的核心目标是高性能,同时要兼顾框架大小、开发者便捷上手体验等事情。

对于性能的处理,自然是magix5内部的事情,关键是看API如何透出给开发者使用。

API的设计上,目标是简洁易用,对于初上手的用户来讲,只需要掌握很少的API即可完成简单的页面,而对于资深用户来讲,magix5依然能够提供足够的API去完成复杂的应用实现。

个人总结了下,对于API分为显式API隐式API

显式API

显式API指用户必须掌握的入门API,这类会反复强调,让用户掌握

比如对于一个view的实现,通常分为样式文件(css或less)界面文件(html)核心执行文件(javascript或typescript)

/*user.css*/
.user-name-card{
    border:solid 1px #ccc
}
<!--user.html-->
<div class="user-name-card">
   name card
</div>
import Magix5 from 'magix5';
let {View,applyStyle}=Magix5;
applyStyle('@:user.css');
export default View.extend({
    tmpl:'@:user.html',
    render(){
        this.digest();
    }
});

以上文件即是一个view的基础构成,使用到的API即是显式API,必须要熟练掌握。其它诸如view上的getset方法也同理,这些是完成一个简单应用的基本方法,需要开发者初学时就要掌握

隐式API

隐式API指开发者在处理复杂场景时才需要掌握的APImagix5在暴露这些API时,部分API不像基础API那样直接调用或使用

比如对于需要响应当前view销毁的动作,magix5就是以事件的方式提供的,参考代码如下

import Magix5 from 'magix5';
let {View,applyStyle}=Magix5;
applyStyle('@:user.css');
export default View.extend({
    tmpl:'@:user.html',
    init(){
        this.on('destroy',()=>{
            console.log('view destroy');
       }
    },
    render(){
        this.digest();
    }
});

magix5提供destroy事件供开发者监听,并没有提供像destroy方法之类的钩子,这是因为监听销毁在大多数场景下并不需要,因此在初上手时也无须让用户掌握这个生命周期的API

使用事件的另外一个好处是,可以在任意view方法内监听destroy事件,不必像示例代码这样,写在init方法里。

同样,随着开发者慢慢的深入学习,会发现每个view都会有一个壳子(vframe),这是因为view加载是异步的,而为了更好的管理view,维持它们之间的关系(父子、兄弟等),magix5抽象了vframe来进行管理。

vframe并不是上手magix5就需要掌握的,而是随着应用的复杂,比如需要访问它们之间的关系时才需要了解和掌握的。

import Magix5 from 'magix5';
let {View,applyStyle,Vframe}=Magix5;
applyStyle('@:user.css');
export default View.extend({
    tmpl:'@:user.html',
    render(){
        this.digest();
        console.log(this.owner);//输出当前view所在的vframe对象
        let vf=Vframe.byId('other-vframe');//通过id查找其它vframe对象
    }
});

再以路由为例,平常开发使用时,如果处理简单的url,可以使用magix5提供的parseUrltoUrl方法进行路由转换,如果遇到复杂的路由处理,则需要掌握magix5提供的router对象

以拿地址栏参数对象为例,这样的url//domain.com/path/to/entry.html?a=b#/user/info?c=d&a=1,这样的url就是一个复杂的url,如何确定路径名称?参数如何处理?同名的参数如何合并?我只想要前面的参数怎么办?我只想要后面的参数怎么办?

我们可以使用routerparse方法获取解析后的对象

import Magix5 from 'magix5';
let {View,Router}=Magix5;
export default View.extend({
    tmpl:'@:user.html',
    render(){
        let loc=Router.parse();
        console.log(loc)
        this.digest();
    }
});

当然,parse接收一个复杂的url,如果不传,则为地址栏当前的url

如果遇到更复杂的场景,比如我想知道路由是如何变化的,到底是路径变化引起的路由改变,还是参数变化引起的路由改变?还是用户直接进入的当前页面?

import Magix5 from 'magix5';
let {View,Router}=Magix5;
export default View.extend({
    tmpl:'@:user.html',
    render(){
        let diff=Router.diff();
        console.log(diff)
        this.digest();
    }
});

可以使用diff方法,能够给你足够的信息来完成这样的需求。

magix5就希望通过逐渐深入的方式,慢慢的把这些API呈现出来,显式API隐式API有界线吗?其实并没有,或许也不应该这样分,而是给API一些分值,比如从0~9,0是必须掌握的,9是极端情况下才需要掌握的,提供一份这样的文档,让开发者根据分值来快速知道哪些是需要学习的,哪些是可以略过的会更好吗?