我用Fable创建了自己的博客网站

456 阅读5分钟

www.slaveoftime.fun/blog/22

前言

最开始入行的时候我做的是.NET, WPF 和 WinForm。所有的东西都是 MVVM, MVC,面向对象等等。作为一个非计算机专业的入行者,我那时候以为世界就是这样,多写多记总能搞定的。当然我花了很多的时间学习和实践最后才转行成功的。

差不多在2017年,我开始做一些网站开发的外包项目,开始学习angular,后来去了某知名国际电商,那里使用vuejs。所以这两个框架和相应的生态我都有一定的了解和经验,但是如果让我现在来回看用这些框架需要写的代码,我还是觉得很陌生和复杂:

<mat-form-field class="fullwidth">
    <mat-icon matPrefix class="field-prefix-icon">vpn_key</mat-icon>
    <input matInput placeholder="{{'Login.Password' | translate}}" [formControl]="password" type="password"
        [readOnly]="isLoadedIn">
    <mat-error *ngIf="password.invalid">{{'Login.PasswordNotValid' | translate}}</mat-error>
</mat-form-field>
<button 
    class="loginButton" 
    mat-raised-button 
    type="submit" 
    [disabled]="formGroup.invalid"
    *ngIf="!isLoadedIn">
    {{'Common.BtnLogin' | translate}}
</button>

▲ angular 的语法

就比如 *ngIf, translate 管道 , 以及一些带有限制性的嵌入语法,这些东西我都花了很多时间去学习和使用,但是现在我基本都忘了。就比如如何在angular中自定义一个管道,如何创建自己的属性(@)。尽管这些语法很像WPF里的Xaml(这也是我当时在那个项目选择angular的原因),所以开始的时候接受很快,但是后来越搞越复杂,后期的维护也比较困难。尽管有typescript的辅佐,但是还是比较复杂,有时候看自己的代码,我都会以为是别人写的。

<div id="app-2">
  <span v-bind:title="message">
    Hover your mouse over me for a few seconds
    to see my dynamically bound title!
  </span>
</div>

▲ 来自vuejs官网

Vuejs也是类似,有很多模板语法,而且还没有typescript加持(那个时候),加上我大部分的时间都是做后端,所以对这些语法基本上是边查边用。更不要说什么父子组件通信,数据sync,数组的更新,mixin的混乱,method,computed,watch这些了。而且智能提醒又比较差,所以基本上我写代码的时候,先拷贝类似的形式,再修改;深度使用的时候每次得去找到相应的文档对照着使用。

比较典型的错误就是组件重用了,一旦改了break changes,对应的都只能通过字符串匹配去查找使用的地方进行修改,没有运行时错误。项目简单还行,一复杂就。。。

var app5 = new Vue({
  el: '#app-5',
  data: {
    message: 'Hello Vue.js!'
  },
  methods: {
    reverseMessage: function () {
      this.message = this.message.split('').reverse().join('')
    }
  }
})

▲ 来自vuejs官网

好运气来了 F# |> 🤘

也是从2017年,我开始接触F#的编程,毕竟都是.NET生态的东西,得保持学习啊。

最开始的时候我并不觉得它有多好,但是如果就是写写函数的话,它确实方便简洁,写脚本也方便。但是平时的代码都是业务密集型的,也不知道怎么用F#来替代C#让面向对象的东西写起来更优雅。

当然,我现在还是觉得C#写面向对象的东西是最好的。但是,后来我也意识到,我开始用F#的姿势和想法就是错的,不应该去套C#的想法去写F#。

再后来,我接触到了Giraffe和Fable。

General.Handlers.errorHanler
>=> General.Handlers.setCurrentUserForDbContext
>=> General.Handlers.cacheIfHasCacheId
>=> choose [
    GET >=> routeCi "/sitemap.xml" >=> Sitemap.Handlers.getSitemap   
    subRouteCi "/api/v1" apiV1Routes   
    SSR.Handlers.renderMainApp   
    text "404 not found"
]

▲ 用Giraffe写webapi

所有东西都是显式表达出来,我不需要学MVC,以及如何自定义action filter,如何用attribute去管理api版本和权限。我只需要学习什么是HttpHandler就可以了,最后我就成了超级玛丽管道工,我的工作就是制造管道和连接管道了,工作从此变得简单和明了。

div </> [
    Classes [
        Tw.flex
        Tw.``flex-row``
        Tw.``items-center``
        Tw.``my-04``
        Tw.``ml-04``
    ]
    Children [
        if not state.IsRegistering then
            Button.primary [
                ButtonProp.Label (tran "User.Form.Login")
                ButtonProp.OnClick login
                ButtonProp.ButtonAttrs [
                    Disabled hasFormErrors
                ]
            ]
            Button.seconday [
                ButtonProp.Label (tran "User.Form.StartRegister")
                ButtonProp.OnClick (fun _ -> Register |> dispatch)
                ButtonProp.ButtonClasses [ Tw.``ml-04`` ]
            ]
        else
            Button.primary [
                ButtonProp.Label (tran "User.Form.Register")
                ButtonProp.OnClick (fun _ -> Registering |> dispatch)
                ButtonProp.ButtonAttrs [
                    Disabled hasFormErrors
                ]
            ]
    ]
]

▲ Fable

使用Fable,我可以用熟悉的F#函数去控制业务逻辑,UI逻辑。再也不需要去学习和查阅angular和vuejs的模板语法和特殊语法了,以及某些靠字符串约定的东西了。我只需要知道函数需要什么参数,然后传递给它就可以了。div无非就是一个需要传入两个参数的函数,第一个是html属性的数组,第二个是其他子节点的数组。所以使用Fable,我基本上没怎么学,当然也没有多少资料让我来学,但是我还是熟练地掌握了它,以至于在用它做完一些兼职的项目后,还有时间来搞一个自己的网站,以及这个网站的设计本身也是一个可重用的框架,我给一个客户开发的简单门户网站就是基于我自己这个网站的雏形,并且还一直保持着代码的共享。

Fable.React是对reactjs的绑定,所以通过它可以享受整个react的生态。当然也有vuejs的绑定,但是用的人太少,也不成熟。

有时候我觉得自己很幸运,能够遇见这么一些省时的技术来增加自己的收入,F#🖖


结语

当然所有的事情都不是完美的,F#写面向对象的语法我就一直记不住(还好基本不写),工具链也不像C#的那么强,社区也非常小众;Fable的使用和配置,以及和js的交互我也花了很多时间学习。不过还好这些都是基础,并不是框架。以后任世界变化无常,框架流行抑或黯然离场,我都可以以不变应万变。

总体来说,我现在还是喜欢并打算把F#发扬光大的。当然啦,作为一个热爱编程的人,学习还是不能停下的,有了F#和Fable我可以不学那些框架里几年后就会被淘汰的东西,但是新技术,比如WebAssembly,rust,机器学习,云计算,甚至5G还是要学的。

F# |> I 🤘