拥抱haXe之javascript 也玩mvc

简介:

haXe是高级语言的高级语言,可以将一个haXe程序转换为其它的高级语言,如JS。haXe有很多优点,比如,强类型、泛型、内联、宏、动态语言特性、命名空间……,用haXe写程序比用JS写程序舒服得多。本文尝试使用haXe开发js程序,搭建一个前端mini型mvc例子。

语言:haXe。haXe编译器可以把haXe程序编译成js程序。

开发工具:FlashDevelop

haXe的简介及安装见《html5 canvas 版 hello world! 暨haXe简介》。开发之前,需要修改Flash Develop配置,将Tools->Program Setting->HaXeContext->Disable Compiler-based Completion 设置为 true。否则的话,haXe的自动完成会很痛苦。

image

项目结构如上图。其中:index.html是演示页面。页面中引用的jsTest.js就是本haXe项目所生成的js文件。js程序的入口就是Main.hx中的main方法(后文详述) 。main方法查找本页面中的所有的haXe标签,根据标签的name,分派出不同的Controller出来,然后根据haXe标签的map配置,把haXe所在节点的父节点及兄弟节点中id对应的节点映射到控制器里的字段。这样一来,一个页面可以对应0个、1个或多个Controller,每个页面片段也可以对应0个、1个或多个Controller,具有极大的灵活性。

有map的存在,在Controller那边,可以少写很多代码。map语法为:

(1)不同的map项由“;”分割;

(2)每个map项语法为“元素id:映射到字段的id”,如果省略掉“:”和之后的内容,则使用元素id作为映射字段的id。

这样一来,就可以把客户端的行为封装成强类型的、严格规划好命名空间的、有严格文档的haXe代码。开发前端时,只需要将不同的元素id映射到不同的Controller中即可实现不同的控制行为。

下面看看核心类:

(1)Page.hx

Page类封装了一些常用的方法:

package ;

import js.Dom;

#if hack 
import js.HtmlDom; 
import js.Document; 
import js.HtmlCollection; 
#end

import js.Lib;

class Page 

    public static function getControllers():HtmlCollection<HtmlDom> 
    { 
        return doc().getElementsByTagName("haXe"); 
    } 
    public static inline function doc():Document 
    { 
        return Lib.document; 
    } 
    public static function getById(id:String,node:HtmlDom=null):HtmlDom 
    { 
        if (id == null || id == '') return null; 
        else if (node == null) 
        { 
            return doc().getElementById(id); 
        } 
        if (node.id == id) return node; 
        else 
        { 
            if (node.hasChildNodes() == true) 
            { 
                var item:HtmlDom = node.firstChild; 
                while (item != null) 
                { 
                    if (item.id == id) return item; 
                    item = item.nextSibling; 
                } 
            } 
        } 
        return null; 
    } 
    public static function getsByName(name:String):HtmlCollection<HtmlDom> 
    { 
        return doc().getElementsByName(name); 
    } 
}

这里有一个技巧:FlashDevelop 对haXe自动完成支持的不完善。很多js命名空间下的类不能正确支持。比如,Page.hx文件,如果不引入js.HtmlDom等三个类(红色部分),则无法提供自动完成支持,而如果引入这三个类,则编译报错(这三个类已经在js.Dom中了)。解决方案就是使用一个haXe不认识的编译开关,比如“hack”,既能让FlashDevelop提供智能支持,又不会参与到编译过程中去。

(2)Controller.hx

Controller.hx 类主要完成map功能,代码为:

import js.Dom;

#if hack 
import js.HtmlDom; 
import js.Document; 
import js.Event; 
#end

import js.Lib;

class Controller 

    public function new(map:String = null, node:HtmlDom = null):Void 
    { 
        if (map == null) return; 
        var mapItems:Array<String> = map.split(';'); 
        var dy:Dynamic = this; 
        for (i in 0 ... mapItems.length) 
        { 
            var itemTxt:String = mapItems[i]; 
            var pairs:Array<String> = itemTxt.split(':'); 
            if (pairs.length > 0) 
            { 
                var v0:String = StringTools.trim(pairs[0]); 
                var v1:String = v0; 
                if (pairs.length > 1) 
                { 
                    v1 = StringTools.trim(pairs[1]); 
                } 
                if (v0.length > 0 && v1.length > 0) 
                { 
                    untyped { 
                        dy[v1] = Page.getById(v0,node); 
                    }    
                } 
            } 
        } 
    }    
}

(3)Test.hx

Test类为具体的Controller,为页面添加控制,代码为:

package orc;

import js.Dom;

#if hack 
import js.HtmlDom; 
import js.Document; 
import js.Event; 
#end

import js.Lib;

class Test extends Controller 

    private var btnSubmit:HtmlDom; 
    private var tbOutput:HtmlDom; 
    public function new(map:String = null, node:HtmlDom = null):Void 
    { 
        super(map, node); 
        var self:Test = this; 
        this.btnSubmit.onclick = function(e:Event):Void 
        { 
            self.tbOutput.innerHTML = "测试一下"; 
        }; 
    } 
}

(4)Main.hx

Main类负责调度,且提供程序的入口,代码为:

package ;

import js.Dom;

#if hack 
import js.HtmlCollection; 
import js.HtmlDom; 
import js.Document; 
import js.Event; 
#end

import js.Lib; 
import orc.Test;

class Main 

    static function main() 
    { 
        var ctrls:HtmlCollection<HtmlDom> = Page.getControllers(); 
        if (ctrls != null) 
        { 
            var l:Int = ctrls.length; 
            for (i in 0 ... l) 
            { 
                handle(ctrls[i]); 
            } 
        } 
    } 
    static function handle(node:HtmlDom):Void 
    { 
        var className:String = node.getAttribute("name"); 
        var map:String = node.getAttribute("map"); 
        var root:HtmlDom = map != null ? node.parentNode: null; 
        switch(className) 
        { 
            case "orc.test": 
                new Test(map,root); 
        } 
    } 
}

测试结果图:

image

所得到的JS文件大小为12K,其中约6K为haXe的js库。压缩后,文件大小为 4k。如果有多个页面的话,这个js文件会变大,但因为只下载一次,对于一般的网站或应用可以接受。

这样做有什么好处呢?

(1)强类型,可以充分利用IDE的提示和完成功能;

(2)可以把代码放在公共的地方,方便代码的积累。代码抽象好了,一般的应用,只映射一下就搞定了;

(3)代码结构清晰。

随着html5的到来,前端的代码量会越来越大,越来越复杂。js太灵活了不好用。拥抱haXe吧!

本文转自xiaotie博客园博客,原文链接http://www.cnblogs.com/xiaotie/archive/2011/08/26/2154078.html如需转载请自行联系原作者


xiaotie 集异璧实验室(GEBLAB)

相关文章
|
3月前
|
JavaScript
Node.js【GET/POST请求、http模块、路由、创建客户端、作为中间层、文件系统模块】(二)-全面详解(学习总结---从入门到深化)
Node.js【GET/POST请求、http模块、路由、创建客户端、作为中间层、文件系统模块】(二)-全面详解(学习总结---从入门到深化)
30 0
|
3月前
|
消息中间件 Web App开发 JavaScript
Node.js【简介、安装、运行 Node.js 脚本、事件循环、ES6 作业队列、Buffer(缓冲区)、Stream(流)】(一)-全面详解(学习总结---从入门到深化)
Node.js【简介、安装、运行 Node.js 脚本、事件循环、ES6 作业队列、Buffer(缓冲区)、Stream(流)】(一)-全面详解(学习总结---从入门到深化)
81 0
|
11天前
|
存储 移动开发 JavaScript
学习javascript,前端知识精讲,助力你轻松掌握
学习javascript,前端知识精讲,助力你轻松掌握
|
17天前
|
JavaScript 前端开发 测试技术
学习JavaScript
【4月更文挑战第23天】学习JavaScript
13 1
|
25天前
|
JavaScript 前端开发 应用服务中间件
node.js之第一天学习
node.js之第一天学习
|
2月前
|
运维 JavaScript 前端开发
发现了一款宝藏学习项目,包含了Web全栈的知识体系,JS、Vue、React知识就靠它了!
发现了一款宝藏学习项目,包含了Web全栈的知识体系,JS、Vue、React知识就靠它了!
|
2月前
|
JavaScript
Vue.js学习详细课程系列--共32节(6 / 6)
Vue.js学习详细课程系列--共32节(6 / 6)
28 0
|
2月前
|
JavaScript
Vue.js学习详细课程系列--共32节(5 / 6)
Vue.js学习详细课程系列--共32节(5 / 6)
30 0
|
2月前
|
JavaScript
Vue.js学习详细课程系列--共32节(4 / 6)
Vue.js学习详细课程系列--共32节(4 / 6)
35 0
|
2月前
|
JavaScript
Vue.js学习详细课程系列--共32节(3 / 6)
Vue.js学习详细课程系列--共32节(3 / 6)
12 0