ul.nav
each item in tabs
li= item.title
ul.bd
li
+mod-#{tabs[0].mod}(tabs[0])
li
+mod-#{tabs[1].mod}(tabs[1])
...
li
+mod-#{tabs[n].mod}(tabs[n])
于是我们得这么写
var data = {
tabs: [{
title: 1,
mod: '001'
}, {
title: 2,
mod: '002'
}]
}
{% raw %}
ul.nav
each item in tabs
li= item.title
ul.bd
{{ for (var i = 0; i < tabs.length; i++) { }}
li
+mod-{{= tabs[i].mod}}(tabs[i])
{{ } }}
{% endraw %}
// 好吧, 上面是我刚开始不知道有dynamicMixin的方案, 现在简洁多了
ul.nav
each item in tabs
li= item.title
ul.bd
each tab in tabs
li
+#{'mod-' + tab.mod}(tabs[i])
var data = {
...
}
// main
$('xxx').click()
// 然后我们像requirejs或者nodejs那样给他套commonjs的wrapper, 我们甚至可以给他套AMD的define wrapper..
// 选择权在我们这里, 因此去掉原function势在必行
$(function() {
var data = {
...
}
// main
$('xxx').click()
})
最近一直在想一个web组件到底应该是啥样的
说到web组件, 大多数第一反应都是
<template>
, shadowDOM这样标准化的组件, 也会想到像ng这样的模块化组件. 但这些组件牢牢依靠polymer, angular这些库, 无法重用. 我一直想做个组件, 它啥都不依赖, 直接复制进html就可以跑, 但同时他又不会影响其他组件. 这组件的原理极度简单, 任何人一看就明白原理有个ppt说到, shadowDOM和iframe最像, 我一想确实啊, iframe相当于是完美沙盒, shadowDOM同样非常独立, 但iframe无法使用宿主的css, 因此用iframe当组件略显丑陋, 而且性能有点蛋疼, 当然我不排斥iframe这个想法
要说组件, 必然还是有
css, js, html
三部分CSS
其中css是最简单的, 因为css自己本身就能重用, 同时我们使用less的话, 给用户编辑的css外面套一个
.mod-001 {}
就轻松做到了不污染他人, 这也有个问题, 就是用户无法自己使用.mod本身, 如果也要定义一个整体, 只能自己加一个box(比如由图片顶宽的组件)HTML
html我依然选择了jade, 因为jade支持轻松编译pretty(带缩进)和不带缩进两种模式, 这也使我不需要再去自己压缩html了, 同时使用jade能保证代码的完美, 不会有直接复制过来的垃圾html混进来. html如何组件化呢, 其中最最重要的一点就是组件是可以嵌套的, 就是说
没错, mixin就是组件, 这和less的mixin不同, css的mixin是常用样式, 不像jade的mixin是类似一个一段小html, 有了jade的mixin, 生活如此愉快, 前端可以很爽的预览模板输出了
JS
最后是js, 我曾想过用amd那样
这样看着很美, 很简洁, 但其实js连这都不需要, 只需要这么写
直接就按jQuery那么写是最好的, 没有任何门槛, 也可以直接沿用以前写好的代码. 唯一不同的就是这个
$
这样这个$只在自己的mod内作用, 不会污染别人, 调用的时候也只需要
这样每个mod都执行了一遍, 当然以后也可能需要区分全部mod一起执行, 和每个单个执行, 这个等实际写的时候再说
共用变量
共用变量是极其重要的一点, 因为不管在less, 还是jade, 还是js中都需要变量, 也许你不理解为何less需要变量, 可以举个例子
一个轮播, 既然作为一个通用组件, 他就可以自由的选择是放多少张图, 我们知道轮播一般都是放在一个很长的
<ul>
中, 然后修改其left值来进行运动的ul的宽度必然由轮播的数量
n
来决定(+1是因为还有个克隆的元素)因此这里非常简单的处理一下
data远不止这些作用, data本身是用来mod数据渲染的
数据结构
因此渲染需要三个数据
一个是全部的用到的全部mod(jade, less, js)
我们必须知道其用到的mod才能进行渲染
另一个是全部的data, 和id有关
最后就是grid的结构了, 还是那句话mod只关心它下面的那个mod, 不会管孙子mod
动态mixin
首先我们要知道, 大多数模板, 都不支持
include(#{var})
这种写法的, 一般我们需要预先知道子模板叫啥. jade的mixin也是如此这儿的处理办法是在jade上再套一个模板
不过这又有问题了, 谁说每个tab或者每个div都是用一样的mixin/mod啊, 我想第一个用mod-001, 第二个用mod-002, ..不行吗
我们的目标jade是长这样的, 拿tab来举例
于是我们得这么写
这种模板套模板的方式实在不优雅, 但是为了mixin动态化, 不得不这么做, 这个时候, 又引出一个问题
Grid是不是一个组件
这是个很复杂的问题, 如果grid是组件, 那我们真正做到了递归, 看着非常完美. 但问题就在与, grid是可以拖动, 添加行, 如果其他组件也能做到这样, 操作起来会不会很乱? 不过这也很好解决, 每次只能操作主mod和他的一级son mod, 要操作son mod, 必须把主mod切换成son mod, 大小的话可以用transiform的scale变大嘛
那grid写成组件是啥样呢?
grid的数据结构就是上文的结构, 可以看出非常的简洁, 完全可以组件化
因此可以看出整个页面可以彻底数据化了, 注意, 仅仅是数据化, 而不是mvvm中model的意思, 此工具想做的是通过数据快速渲染整个页面, 和mvvm要做的完全无关, mvvm将会在组件中用
渲染一个页面需要的数据
单个mod的结构是固定的(不按前文了)
通过modid判断一个对象是否为mod对象
渲染的过程如下
$.extend(_data, data); mod.data = _data
less.parse(mod.less)
data处理方法
现在最复杂的反而是默认data的处理, 首先要支持单个使用, 就是用户看到直接复制下来就能直接用, 然后又能完美支持模块化
现在要变成
如果我们要在js用的话, 期望是这样
不管这两咋整, 都非常复杂, 要在function里插东西, 怎么写都不会优雅, 我们不得不重新定义js的格式, wrapper由我们自己加...
但不管如何, 我们都无法正确的取出data的值, 并回显到js中, 这时候我们想到了jekyll的做法
数据通过在前面的yaml预先声明, 这样还可以定义小型validator
恩, 这个实在是分分钟就解决了, 现在一切都貌似准备好了, 就剩明天真正渲染一个页面了!
总结
可以看到, 这些看起来都无比简单, 没有难度, 关键是它在写法上不需要任何专门的学习, 同时也保证了组件的通用性, 不过这还只是我口头说说, 具体是否真能像我想的这么美好这么屌还得等我写出来再看..
需要解决的问题
col
来定啊, 但没这么简单, 因为有些单图组件, 图片的宽度是定死的include(#{var})
, (预处理模板)