刀耕火种

刀耕火种是新石器时代残留的农业经营方式。又称迁移农业,为原始生荒耕作制。
var TodoApp = Nuclear.create({
    add: function (evt) {
        evt.preventDefault();
        var textBox = this.node.querySelector('input');
        this.option.items.push(textBox.value);
    },
    installed: function () {
        var form = this.node.querySelector('form');
        form.addEventListener('submit', this.add.bind(this), false);
    },
    render: function () {
        return '<div>\
                 <h3>TODO</h3>\
                 <ul> {{#items}} <li>{{.}}</li> {{/items}}</ul>\
                  <form >\
                   <input type="text"  />\
                   <button>Add #{{items.length}}</button>\
                 </form>\
                </div>';
    }
});

new TodoApp( { items: [] },"#container");

这种书写方式依赖延续了jQuery时代的思维方式:

  • js里查找dom
  • js里绑定事件

在以前的文章里写过,如果不使用组件化编程,js里查找dom以及在js里绑定事件可能会带来如下问题:

  • 浪费带宽
  • 用户反馈无响应
  • 脚本错误
  • 页面短暂错乱

上面的书写方式粗暴、原始、落后,即:刀耕火种。

石器锄耕

“石器锄耕”是奴隶社会时期的主要耕作方式,这一时期农业已经有了很大的发展。
var TodoApp = Nuclear.create({
    onRefresh: function () {
        this.form.addEventListener("submit", function (evt) {
            evt.preventDefault();
            this.option.items.push(this.textBox.value);
        }.bind(this), false);
    },
    render: function () {
       return '<div>\
                 <h3>TODO</h3>\
                 <ul> {{#items}} <li>{{.}}</li> {{/items}}</ul>\
                 <form nc-id="form" >\
                   <input nc-id="textBox" type="text"  />\
                   <button>Add #{{items.length}}</button>\
                 </form>\
               </div>';
    }
},{
    diff:false
});

new TodoApp( { items: [] },"#container");

会发现,查找dom的代码已销声匿迹。直接标记nc-id,就自动挂载在this下。
值得注意的是,传入了第二参数关闭了DOM diff。关掉diff的结果就是,每次组件HTML会全部重新替换渲染,绑定的事件全部丢失,所以需要将绑定事件的代码写入onRefresh里,这样每次重新渲染都会再绑定一次。
比刀耕火种先进一点:石器锄耕。

直捣黄龙

黄龙:即黄龙府,辖地在今吉林一带,应该是指长春市农安县,为金人腹地。一直打到黄龙府。指捣毁敌人的巢穴。指杀敌取胜。
var TodoApp = Nuclear.create({
    add: function (evt) {
            evt.preventDefault();
            this.option.items.push(this.textBox.value);
    },
    render: function () {
       return '<div>\
                 <h3>TODO</h3>\
                 <ul> {{#items}} <li>{{.}}</li> {{/items}}</ul>\
                 <form onsubmit="add(event)" >\
                   <input nc-id="textBox" type="text"  />\
                   <button>Add #{{items.length}}</button>\
                </form>\
               </div>';
    }
});

new TodoApp( { items: [] },"#container");

会发现,查找dom和绑定的代码同时销声匿迹!!

  • 需要使用input,直接标记nc-id为textBox,就可以this.textBox访问
  • 需要绑定事件,直接在HTML内声明事件和回调onsubmit="add(event)"

也可以通过add(event,this)拿到event和触发该事件的dom元素。

代码通俗简洁干净直接,目的直观明确。故:直捣黄龙。

子承父业

宋·释道原《景德传灯录·利山和尚》:“僧问:不历僧只获法身,请师直指。师云:子承父业。”
var TodoList = Nuclear.create({
    render: function () {
        return '<ul> {{#items}} <li>{{.}}</li> {{/items}}</ul>';
    }
});

var TodoApp = TodoList.create({
    add: function (evt) {
        evt.preventDefault();
        this.option.items.push(this.textBox.value);
    },
    render: function () {
        return '<div>\
                 <h3>TODO</h3>'
                + this._super.render() +
                '<form  onsubmit="add(event)" >\
                   <input nc-id="textBox" type="text"  />\
                   <button>Add #{{items.length}}</button>\
                 </form>\
               </div>';
    }
});

new TodoApp({ items: [] },"#container");

TodoApp不过是TodoList的炎黄子孙,故TodoApp可以通过this._super访问父辈。也可访问父辈任何方法。有人会说:“组合”优于“继承”的。一定要明白:OOP既能组合也能继承,是不冲突的。且看下面例子。

万夫一力

明·刘基 《郁离子·省敌》:“万夫一力,天下无敌。”
var TodoList = Nuclear.create({
    render: function () {
        return '<ul> {{#items}} <li>{{.}}</li> {{/items}}</ul>';
    }
});

var TodoApp = Nuclear.create({
    install: function () {
        this.todoList = new TodoList({ items: [] })
    },
    add: function (evt) {
            evt.preventDefault();
            this.todoList.option.items.push(this.textBox.value);
            this.refresh();
    },
    render: function () {
       return '<div>\
                 <h3>TODO</h3>'
                 + this.todoList.render()+
                 '<form onsubmit="add(event)" >\
                   <input nc-id="textBox" type="text"  />\
                   <button>Add #'+this.todoList.option.items.length+'</button>\
                 </form>\
               </div>';
    }
});

new TodoApp( {},"#todo2Container");

前一个例子的继承,这个例子是组合。不能说你的框架是Class base就不能使用组合,这是天大的误解。而我依稀记得极限编程关于面向对象设计的推论是:优先使用对象组合,而不是类继承。作为框架的设计者,虽然会有一些约束,但是如果连组合和继承都不能共存,那就是设计的最大败笔。
使用Nuclear既能继承也能组合,关键看程序逻辑该怎么抽象和实现复杂度。

藕断丝连

唐·孟郊《去妇》诗:“妾心藕中丝;虽断犹牵连。”
var TodoList = Nuclear.create({
    render: function () {
        return '<ul> {{#items}} <li>{{.}}</li> {{/items}}</ul>';
    }
});

var TodoApp = Nuclear.create({
    install: function () {
        this.todoList = new TodoList(this.option)
    },
    add: function (evt) {
            evt.preventDefault();
            this.option.items.push(this.textBox.value);
    },
    render: function () {
       return '<div>\
                 <h3>TODO</h3>'
                 + this.todoList.render()+
                 '<form  onsubmit="add(event)"  >\
                   <input nc-id="textBox" type="text"  />\
                   <button>Add #{{items.length}}</button>\
                 </form>\
               </div>';
    }
});

new TodoApp( { items: [] },"#container");

这个例子和上个例子的区别是:共用option。option的变更会自动更新依赖option的组件。

四海为家

 《汉书·高帝记》:“且夫天子以四海为家。”
var TodoApp = Nuclear.create({
add: function (evt) {
        evt.preventDefault();
        this.option.items.push(this.textBox.value);
},
render: function () {
   return '<div>\
             <h3>TODO</h3>\
             <ul> {{#items}} <li>{{.}}</li> {{/items}}</ul>\
             <form onsubmit="add(event)" >\
               <input nc-id="textBox" type="text"  />\
               <button>Add #{{items.length}}</button>\
             </form>\
           </div>';
}
});
var todo= new TodoApp( { items: [] });

todo.setNuclearContainer('#container');

且看上面的new TopApp没传第二个参数指定容器。后面使用setNuclearContainer指定容器。这个场景还是比较常见,创建游离态组件,后续根据需要指定容器。AlloyLever就是这么干的: https://github.com/AlloyTeam/AlloyLever/blob/master/src/js/main.js

如虎添翼

三国·蜀·诸葛亮《心书·兵机》:“将能执兵之权,操兵之势,而临群下,臂如猛虎加之羽翼,而翱翔四海。”
var TodoApp = Nuclear.create({
    add: function (evt) {
        evt.preventDefault();
        this.option.items.push(this.textBox.value);
    },
    render: function () {
        return '<div>\
                  <h3>TODO</h3>\
                  <ul> {{#items}} <li>{{.}}</li> {{/items}}</ul>\
                  <form onsubmit="add(event)" >\
                   <input nc-id="textBox" type="text"  />\
                   <button>Add #{{items.length}}</button>\
                 </form>\
               </div>';
    },
    style: function () {
        return 'h3 { color:red; }\
                button{ color:green;}';
    }
});
var todoApp = new TodoApp({ items: [] }, '#container');

todoApp.option.items.push('Nuclear');
todoApp.option.items.push('Hello World!');

style方法内的样式自会对自身生效,不会污染其他组件。可以操作对象实例option,option的变更会自动更新组件,属性设置>方法调用。
双向绑定的好处以前写过一篇文章专门介绍,从上面的例子也能可出:

  • 组件内部的代码更简洁
  • 组件外部的代码更简洁

壁垒森严

壁垒:古代军营四周的围墙;森严:整齐,严肃。原指军事戒备严密。现也用来比喻彼此界限划得很分明。
<template id="myTemplate">
    <style scoped>
        h3 { color:red; }
        button{ color:green;}
    </style>

    <div>
        <div>
            <h3>TODO</h3>
            <ul>{{#items}}<li>{{.}}</li>{{/items}}</ul>
            <form onsubmit="add(event)">
                <input nc-id="textBox" type="text">
                <button>Add #{{items.length}}</button>
            </form>
        </div>
    </div>
</template>

<script>
    var TodoApp = Nuclear.create({
        install:function() {
            this.todoTpl = document.querySelector("#myTemplate").innerHTML;
        },
        add: function (evt) {
            evt.preventDefault();
            this.option.items.push(this.textBox.value);
        },
        render: function () {
            return this.todoTpl;
        }
    });

    new TodoApp({ items: [] }, "#todoListContainer");
</script>

不用担心template标签的兼容性问题,Nuclear帮你处理好了。支持所有现代浏览器(包括IE9+)。
Nuclear也在js里进行了动态插入了template { display: none !important; }。但是js还没执行到且浏览器不兼容template的话,用户会看到一闪而过的模板原始代码。
所以为了避免IE9一闪而过的模板原始代码直接显示,建议在head中加入。

<style>
    template {
        display: none !important;
    }
</style>

如果你像手Q hybrid应用那样只需要兼容webkit的话,天生支持template,就不用加入上面的兼容样式。

鬼斧神工

《庄子·达生》:“梓庆削木为鐻,鐻成,见者惊忧鬼神。”
var TodoApp = Nuclear.create({
    add: function (evt) {
        evt.preventDefault();
        this.option.items.push(this.textBox.value);
    },
    render: function () {
        return `<div>
                  <h3>TODO</h3>
                  <ul> {{#items}} <li>{{.}}</li> {{/items}}</ul>
                  <form onsubmit="add(event)" >
                   <input nc-id="textBox" type="text"  />
                   <button>Add #{{items.length}}</button>
                 </form>
               </div>`;
    },
    style: function () {
        return `h3 { color:red; }
                button{ color:green;}`;
    }
});

人剑合一

剑修者最高境界,人既是剑,剑既是人,剑随心发,人随剑杀
var TodoApp = Nuclear.create({
    add: function (evt) {
        evt.preventDefault();
        this.option.items.push(this.textBox.value);
    },
    render: function () {
        return `<style scoped>
                  h3 { color:red; }
                  button{ color:green;}
                </style>
                <div>
                  <h3>TODO</h3>
                  <ul> {{#items}} <li>{{.}}</li> {{/items}}</ul>
                  <form onsubmit="add(event)" >
                   <input nc-id="textBox" type="text"  />
                   <button>Add #{{items.length}}</button>
                 </form>
                </div>`;
    }
});

Nuclear从出生,API简单稳定,几乎没怎么变动,内部是实现在不断的完善,API驱动非常重要,不能因为实现某些API困难而做任何妥协,比如让使用框架的着多传个参数、多调用一次方法,这都是设计的缺陷。

Nuclear就是不妥协的结果。因为简单的设计,所以可以有很多强大的玩法,待续...

广而告之

Nuclear Github: https://github.com/AlloyTeam/Nuclear

加入Nuclear,一起让组件化开发体验更加惬意、舒适..

基于Nuclear的Web组件-Todo的十一种写法的更多相关文章

  1. 基于JS实现回到页面顶部的五种写法(从实现到增强)

    这篇文章主要介绍了基于JS实现回到页面顶部的五种写法(从实现到增强)的相关资料,本文介绍的非常详细,实用性也非常高,非常具有参考借鉴价值,需要的朋友可以参考下   写法 [1]锚点 使用锚点链接是一种 ...

  2. 基于接口的 InvocationHandler 动态代理(换种写法)

    InvocationHandler is the interface implemented by the invocation handler of a proxy instance. Each p ...

  3. 基于继承的 MethodInterceptor 动态代理(换种写法)

    net.sf.cglib.proxy.Enhancer Generates dynamic subclasses to enable method interception. This class s ...

  4. 10.Web组件复用

    1.静态包含(一个指令) 在软件工程中构建可复用组件可极大的提高软件生产效率.增强系统的可维护性HTML标记对于一个web应用系统中的页面都是通用的,比如公司标志.版权声明.导航菜单JSP中引用的we ...

  5. Web组件的三种关联关系

    Web应用程序如此强大的原因之一是它们能彼此链接和聚合信息资源.Web组件之间存在三种关联关系: ●  请求转发 ●  URL重定向 ●  包含 存在以上关联关系的Web组件可以是JSP或Servle ...

  6. 漫谈Nuclear Web组件化入门篇

    目前来看,团队内部前端项目已全面实施组件化开发.组件化的好处太多,如:按需加载.可复用.易维护.可扩展.少挖坑.不改组件代码直接切成服务器端渲染(如Nuclear组件化可以做到,大家叫同构)... 怎 ...

  7. RSuite 一个基于 React.js 的 Web 组件库

    RSuite http://rsuite.github.io RSuite 是一个基于 React.js 开发的 Web 组件库,参考 Bootstrap 设计,提供其中常用组件,支持响应式布局. 我 ...

  8. Amaze UI 发布基于jQuery新版本v2.0.0之web组件

    首先Amaze Ui第一版时我收到邮件邀请去试用,去了官网看了下,是基于zepto.js的一个类似bootstrap的响应式框架,提到框架当然是好事,快速开发呗.这词2.0的弃用zepto.js改用j ...

  9. SpringMVC内容略多 有用 熟悉基于JSP和Servlet的Java Web开发,对Servlet和JSP的工作原理和生命周期有深入了解,熟练的使用JSTL和EL编写无脚本动态页面,有使用监听器、过滤器等Web组件以及MVC架构模式进行Java Web项目开发的经验。

    熟悉基于JSP和Servlet的Java Web开发,对Servlet和JSP的工作原理和生命周期有深入了解,熟练的使用JSTL和EL编写无脚本动态页面,有使用监听器.过滤器等Web组件以及MVC架构 ...

随机推荐

  1. 关于javascript中的this关键字

    this是非常强大的一个关键字,但是如果你不了解它,可能很难正确的使用它. 下面我解释一下如果在事件处理中使用this. 首先我们讨论一下下面这个函数中的this关联到什么. function doS ...

  2. 我的MYSQL学习心得(八) 插入 更新 删除

    我的MYSQL学习心得(八) 插入 更新 删除 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得( ...

  3. Xamarin.Android之Fragment Walkthrough

    利用Fragment设计能够兼容不同屏幕的应用 这里我们先围观下最后的成果图,给读者打打气: 普通手机上显示的结果: 在平板上显示的结果: 笔者要郑重声明下,虽然看似是两种不同的显示效果,但是同一个应 ...

  4. CSharpGL(8)使用3D纹理渲染体数据 (Volume Rendering) 初探

    CSharpGL(8)使用3D纹理渲染体数据 (Volume Rendering) 初探 2016-08-13 由于CSharpGL一直在更新,现在这个教程已经不适用最新的代码了.CSharpGL源码 ...

  5. Java垃圾回收

    垃圾收集算法 引用计数 堆中的每个对象都有一个引用计数,当对象被引用时引用计数加1,当对象的引用被重新赋值或超出有效区域时引用计数减1,当一个对象被回收后,它所引用的对象的引用计算减1.当一个对象的引 ...

  6. 微信小程序开发工具测评

    1月9日微信小程序正式上线.很多企业都希望能在这个.但是在技术开发的问题上,却不知道该如何下手.经过一些程序员不辞辛苦连夜测试,终于从十余款工具呕心沥血筛选出四款比较靠谱实用的微信小程序开发工具.接下 ...

  7. RowVersion数据类型

    RowVersion数据类型是系统自动生成的,唯一的,二进制数字,数值和binary(8)相同,RowVersion通常用作给Table的数据行加版本戳,存储大小为 8 个字节.RowVersion数 ...

  8. [转]Linux中configure/makefile

    本文教你如何使用autoconf.automake等来制作一个以源代码形式(.tar.gz)发布的软件.并可在执行configure时使用自定义参数. 一.概述和基础知识 在Linux下得到一个以源代 ...

  9. 如何部署Zabbix服务端

    部署环境 RHEL 6.7 Zabbix-server 2.2.14 安装zabbix官方源 # wget http://repo.zabbix.com/zabbix/2.2/rhel/6/x86_6 ...

  10. Handler系列之创建子线程Handler

    上一篇我介绍了Handler机制的工作原理,默认情况下,ActivityThread类为我们创建的了主线程的Looper和消息队列,所以当你创建Handler之后发送消息的时候,消息的轮训和handl ...