640 likes | 839 Views
UI 组件的发展史. 基于阻塞模式的控件前世今生. 远古时代 : 属性声明和 window 对象. 例子 01. <script> function selectOptions(){ var selected = window.showModalDialog("child.html"); alert(selected); } </script> <input type="button" value="select" onclick="selectOptions()">. <script>
E N D
<script> function selectOptions(){ var selected = window.showModalDialog("child.html"); alert(selected); } </script> <input type="button" value="select" onclick="selectOptions()">
<script> function selectOption(value){ window.returnValue = value; window.close(); } </script> <input type="button" value="select" onclick="selectOption(1)"> <input type="button" value="select" onclick="selectOption(2)"> <input type="button" value="select" onclick="selectOption(3)">
局限性: 1,不是所有浏览器都支持 2,不易控制外观
<style> #myOptions{ width:60%; height:400px; display:none; position:absolute; left:100px; top:100px; background-color:#ccc; } </style> <input type="button" value="select" onclick="showOptions()"> <div id="myOptions"> <input type="button" value="select" onclick="selectOption(1)"> <input type="button" value="select" onclick="selectOption(2)"> <input type="button" value="select" onclick="selectOption(3)"> </div>
<script> function selectOption(value){ alert(value); document.getElementById('myOptions').style.display = "none" } function showOptions(){ document.getElementById('myOptions').style.display = "block" } </script>
不完善: 1,过程式编程 2,HTML代码和后台代码混杂 3,不能还原业务数据
<style> .hide{ width:60%; height:400px; display:none; position:absolute; left:100px; top:100px; background-color:#ccc; } .show{ display:block; } </style> <body onload="onloaded()"> <input type="button" value="select" onclick="selectComponet.show()"> </body>
<script> …..//类的定义 var selectComponet; function onloaded(){ selectComponet = new SelectComponet(); } </script>
function SelectComponet(){ var values = ['A','B','C']; this.getValues = function(){ return values; } …..//生成DOM } SelectComponet.prototype.show = function(){ this.container.className += " show"; } SelectComponet.prototype.hide = function(){ this.container.className = "hide"; }
var container = document.createElement("div"); this.container = container; container.className = "hide"; document.body.appendChild(container); var len = values.length; for(var i=0; i<len; i++){ (function(){ var idx = i; var input = document.createElement("input"); input.type = "button"; input.value = "select"; input.onclick = function(){ alert(selectComponet.getValues()[idx]); selectComponet.hide(); } container.appendChild(input); })(); }
1,HTML+JS+CSS各司其职 A,HTML 内容 B,CSS 表现 C,JS 类封装 DOM构造 事件响应 样式更换 2,各种JS特性 A,prototype B,私有属性 C,闭包
造成JS错误频发的主要原因 1,不安全的使用全局变量 2,组件没有做到真正意义的高内聚,低耦合 3,多人协作开发,HTML或者JS的变更无人知晓 4,对HTML/CSS/JS语言特性了解不深入,对JS库提供的API不熟悉
<html> <script> ….//module </script> <style> .hide{ width:60%; height:400px; display:none; position:absolute; left:100px; top:100px; background-color:#ccc; } .show{ display:block; } </style> <body> <input id="myButton" type="button" value="select"> </body> </html>
Module = { comps : [], register : function(){ //TODO check if the arguments is valid var name = arguments[0]; var comp = arguments[1]; this.comps[name] = comp; }, use : function(){ //TODO check if the arguments is valid var name = arguments[0]; var config = arguments[1]; return Module.comps[name].call(window, config); } }
window.onload = function(){ var values = ['A','B','C']; var selectComp = new Module.use('SelectComponet',{ element : 'myButton', data : values }); selectComp.bind('click',function(data){ alert(data); }) selectComp.render(); }
Module.register('SelectComponet',function(){ //TODO check if the arguments is valid var COMP = this; var config = arguments[0]; var events = {}; function show(){ //show the componet } function hide(){ //hide the componet } function bind(){ //build a event map } function render(){ //build the dom //attach click event to the element } //return a instance return {bind:bind, render:render, show:show}; })
Module.register('SelectComponet',function(){ //TODO check if the arguments is valid var COMP = this; var config = arguments[0]; var events = {}; function bind(){ //build a event map } function render(){ //build the dom //attach click event to the element } function show(){ //show the componet } function hide(){ //hide the componet } //return a instance return {bind:bind, render:render, show:show}; })
function bind(){ //TODO check if the arguments is valid var name = arguments[0]; var fn = arguments[1]; events[name] = fn; }
function render() { //build the dom var container = document.createElement("div"); container.id = config['element'] + '-comp'; container.className = "hide"; document.body.appendChild(container); var values = config['data']; var len = values.length; for (var i = 0; i < len; i++) { (function () { var value = values[i] var input = document.createElement("input"); input.type = "button"; input.value = "select"; input.onclick = function () { var fn = events['click']; fn.call(input, value); hide(); } container.appendChild(input); })(); }
function show() { document.getElementById(config['element'] + '-comp').className = 'hide show'; } function hide() { document.getElementById(config['element'] + '-comp').className = 'hide'; }
Library作用: • 为所有浏览器提供统一接口 • 基本的XML, JSON 处理功能 • 对象操作 • DOM 操作 • 事件处理 • AJAX 异步通信
Framework作用: • 1,提供开发工具集(水,电等基础设施) • 2,提供组件使用(房子) • 3,保证组件的高内聚,低耦合(保护个人隐私) • 4,组件通讯(利用宽带建立小区虚拟社区)
<body> <input id="myButton" type="button" value="select"> <div id="firstView"> </div> <br><br><br> <div id="secondView"> </div> </body>
Module = { comps: {}, instances: {}, events: {}, instanceseq: 1000, getSeq: function () { return Module.instanceseq++; }, register: function () { //todo }, use: function () { //todo }, listen: function () { //todo }, dispatch: function () { //todo } }
use: function () { //TODO check if the arguments is valid var name = arguments[0]; var config = arguments[1] || {}; config.id = Module.getSeq(); var instance = Module.comps[name].call(window, config); Module.instances[config.id] = instance; return instance; },
listen: function () { //TODO check if the arguments is valid var name = arguments[0]; var instance = arguments[1]['instance']; var fn = arguments[1]['fn']; var events = Module.events; if (!events[name]) events[name] = {}; events[name][instance] = fn; },
dispatch: function () { //TODO check if the arguments is valid var name = arguments[0]; var from = arguments[1]['instance']; var data = arguments[1]['data']; var events = Module.events; var instances = Module.instances; if (events[name]) { for (var instance in events[name]) { var fn = events[name][instance]; fn.call(instances[instance], data); } } }