Qjs直出实现过程

直出要做什么

在服务端为Qjs填充默认的值,例如

输入:

<div q-text="name"></div>
{"name": "Qjs"}

直出:

<div q-text="name">Qjs</div>

原理

编译阶段处理directives, 输出阶段处理filters对数据取值渲染模板获取到html

编译:

<div q-text="name">Qjs</div>
<div q-class="red: isRed"></div>

处理directives编译成underscore模板:

<div q-text="name"><%= name %></div>
<div q-class="red: isRed" class="<% if (isRed) { %>red<% } %>"></div>

输出:

处理filters, 使用模板函数对数据做渲染

实现

编译阶段虚拟dom的大框架:

编译过程基本都在cheerio建立的虚拟dom上操作, 因此解析Qjs语法等都可以直接复用Qjs的, 只需重写一套directives

q-text

var $ = require('cheerio');
directives.text = function(exp) {
    $(this.el).html('{{- __filterValue(__obj, {}) }}');
}
<div q-text="list | length"></div>

获得的模板

<div q-text="list | length"><%- __filterValue(__obj, {"arg":null,"name":"list","filters":[["length"]]}) %></div>

q-show

var $ = require('cheerio');
directives.show = function(exp) {
    $(this.el).css('__tplstrings1', 0);
}
var tpl = dom.toString().replace('__tplstrings1', '<% if (__filterValue()) { %>display:block;<% } %>');

先添加一个无用的style,之后替换成想要的

子模块:

q-vm在编译阶段只简单地植入一个变量

<div q-vm="head_module"><%= _vm[0] %></div>

在输出阶段,先获取子模块的html, 而后放入数据中渲染

var output = compiled(_.extend({}, data, {
    _vm: '<div>head_module</div>'
}});

filters异常:

filter复用浏览器端的, 但某些filter是无法正常运行的, 例如

filters.width = function(val) {
    return Match.min(val, $(window).width());
};

因此必须考虑无法兼容的问题:

function __filterValue(data, exp) {
    var root = data[exp.name];
    var name, args;
    for (var i = 0; i < exp.filters.length; i++) {
        try {
            name = exp.filters[i][0];
            args = [].concat(exp.filters[i]);
            args[0] = root;
            root = filters[name].apply(data, args);
        } catch(ex) {
            console.warn('filter failed: ' + name);
            return root;
        }
    }
    return root;
}

完整的一个例子

var fs = require('fs');
var Promise = require('promise');
// QLoader 会自动处理模块依赖关系
var QLoader = require('q-tpl/loader');

// 编译
var q = QLoader.compile({
    root: 'root',
    getQ: function(id) {
        if (id === 'root') {
            return {
                raw: [
                    '<div q-text="list | length"></div>',
                    '<div q-vm="submodule"></div>'
                ].join(''),
                filters: {
                    length: function(list) {
                        return list.length;
                    }
                },
                data: function(loader) {
                    return Promise.resolve({
                        list: [23, 3, 22]
                    });
                }
            };
        } else if (id === 'submodule') {
            return {
                raw: '<h1 q-text="text"></h1>',
                data: function(loader) {
                    return Promise.resolve({
                        text: 'hello world submodule'
                    });
                }
            };
        }
    }
});

module.exports = function(req, res) {
    // 用户请求,输出
    var loader = new Loader(req);
    q(loader).done(function(html) {
        res.write(html);
    });
};

github: [https://github.com/feix760/Q.tpl]

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏加米谷大数据

MapReduce API 基本概念

在正式分析新旧 API 之前,先要介绍几个基本概念。这些概念贯穿于所有 API 之中,因此,有必要单独讲解。 1、 序列化 序列化是指将结构化对象转为字节流以便...

2687
来自专栏Java Edge

大道缓存1 缓存特征2 缓存介质3 缓存分类和应用场景缓存实战

用户请求从界面(浏览器/App)到网络转发、应用服务再到存储(数据库或文件系统),然后返回到界面呈现内容。

561
来自专栏Windows Community

Windows 8.1 应用再出发 (WinJS) - 几种新增控件(1)

Windows 8.1 和 WinJS 引入了以下新控件和功能,分别是:AppBarCommand、BackButton、Hub、ItemContainer、...

28510
来自专栏腾讯移动品质中心TMQ的专栏

Web 自动化:一种基于 Page Object 的实现及常见异常处理

Page Object 设计模式是 Selenium 官网推荐的一种自动化构建模式。PageObject 设计模式对网页进行一个简单抽象,将每个页面设计成一个类...

1670
来自专栏aCloudDeveloper

Linux探秘之I/O效率

一、文章来由   最近看了《UNIX环境高级编程》,对以前比较模糊的一些知识结构又做了进一步的加强,特别是前两章讲到不带缓冲的文件I/O和带缓冲的标准I/O,对...

2027
来自专栏前端达人

在 React 应用中获取数据

可以说 React 是构建 web 应用最流行的库。然而,它并不是全能的 web 框架。它只关注 MVC 中的 view 模块。

732
来自专栏*坤的Blog

Java分层概念(转)

3094
来自专栏微信公众号:Java团长

Java Web从前端到后台常用框架介绍

Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解...

803
来自专栏葡萄城控件技术团队

Web Components是不是Web的未来

今天 ,Web 组件已经从本质上改变了HTML。初次接触时,它看起来像一个全新的技术。Web组件最初的目的是使开发人员拥有扩展浏览器标签的能力,可以自由的进行定...

1977
来自专栏DT乱“码”

java中接口的作用

很多JAVA初级程序员对于接口存在的意义很疑惑。不知道接口到底是有什么作用,为什么要定义接口。       好像定义接口是提前做了个多余的工作。下面我给大家总结...

17810

扫码关注云+社区