JavaScript 高级框架设计

在现在,jQuery等框架已经非常完美,以致于常常忽略了JavaScript原生开发,但是这是非常重要的.

所以,我打算写一个简单的框架,两个目的

  • 熟练框架的思想

  • 熟练DOM操作.

所以我打算,模仿jQuery,实现一个简单的类似jQuery的库 Hpawn.

关于JavaScript面向对象高级,会在以后介绍.

关于我所有的代码,都会托管到 github上,https://github.com/apawn

我的开发环境是VSCode.


在Hpawn中,我会分为七个模块.

  • 选择器模块

  • dom操作模块

  • 事件模块(click,on) 比较简单

  • 属性模块

  • 样式模块

  • 动画模块,使用缓动函数而不是css3.

  • 面向对象封装

选择器模块

在这里,我们要实现一个类似于jQuery选择器的东西,但是要简单很多.

代码 01.html

<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
div{
width: 300px;
height: 100px;
border: 1px red solid;
}
</style>
</head>
<body>
<div></div>
<div></div>
</body>

现在我们要给上面的div添加绿色背景,按照传统的办法,可能会这么写

01.js

   onload = function(){
var divs = document.getElementsByTagName("div");
for(var i = 0,length = divs.length;i<length;i++){
divs[i].style.backgroundColor="green";
}
}

但是,这样的DOM操作真的很麻烦.

代码冗余.丑,易错, 还会影响性能,为什么?

因为代码要压缩,document.getElementsByTagName()不会改变,但是如果改为get方法,只会存在一个g.

现在开始解决,首先解决代码冗余

02.js

先封装一个get方法

var get = function (tag) {
return document.getElementsByTagName(tag);
}

代码可能会变成现在这样,

var divs = get("div");
for(var i = 0,length = divs.length;i<length; i++){
divs[i].style.background = "green";
}

但是,似乎还是很冗余,继续封装.

03.js

var get = function (tag) {
return document.getElementsByTagName(tag);
}
var each = function (arr,style,value) {
for(var i = 0,length = arr.length;i<length; i++){
arr[i].style[style] = value;
}
} var divs = get("div");
each(divs,"backgroundColor","green") ;

代码变成了上面那样,有木有觉得好了很多呢.

可能并不觉得会简单,那是因为我只包含了两个元素.

但是,上面的代码只能做一件事情,就是设置样式,可是我还设置动作,设置属性.

好了,第一步优化完成,下面开始第二部.

04.js

var get = function (tag) {
return document.getElementsByTagName(tag);
}
var each = function (arr,func) {
for(var i = 0,length = arr.length;i<length; i++){
func(arr[i],i);
}
} var divs = get("div");
each(divs,function (item,index) {
item.style.background = "red";
});

我传递了一个函数进去,我将arr[i] 和i 传给函数,这是最关键的一步.

但是,一个问题出现了.

比如,我先查找数组 arr =[1,2,3,4] 中元素为3的索引,上面的代码可以吗?

我找到了,怎么跳出呢?

也许想到这样的代码

each(arr,function(v,i){
if(v===5){
breadk;
}
})

但是,break 可以写在函数中吗??

// 为了查看单独的js代码,我使用了node作为运行环境,所以代码库里有一些并没有对应的html文件.

还是需要再修改each 函数

05.js

 var each = function (arr, func) {
for (var i = 0, length = arr.length; i < length; i++) {
if (func(arr[i], i) === false) {
break;
}
}
}; var a = [1, 2, 3, 4];
var index = -1;
each(a, function (v, i) {
if (v === 3) {
index = i;
return false;
}
});
console.log(index); // 输出2

大功告成!

但是,我们每次调用函数的时候都要传一个v和i 才能使用,如果不小心忘了呢?

似乎有更好的办法

07.js,继续回到第一个例子

var get = function (tag) {
return document.getElementsByTagName(tag);
}
var each = function (arr, func) {
for (var i = 0, length = arr.length; i < length; i++) {
if (func.call(arr[i],arr[i], i) === false) {
break;
}
}
};
var divs = get("div");
each(divs,function (item,index) {
this.style.background = "red";
});

现在,我们看看jQuery的each是怎么实现的.

each: function( obj, callback, args ) {
var value,
i = 0,
length = obj.length,
isArray = isArraylike( obj ); else
if ( isArray ) {
for ( ; i < length; i++ ) {
value = callback.call( obj[ i ], i, obj[ i ] ); if ( value === false ) {
break;
}
}
} else {
for ( i in obj ) {
value = callback.call( obj[ i ], i, obj[ i ] );
if ( value === false ) {
break;
}
}
} return obj;
},

是不是差不多呢....

现在,继续优化get方法.

如果用get方法获得多个元素,就会获得多个数组,为了简化开发,可以考虑合并到一个数组中,调用多次get方法.

给get添加一个result参数

var get = function (tag, result) {
result = result || [];
result.push.apply(result, document.getElementsByTagName(tag));
return result;
}
var each = function (arr, func) {
for (var i = 0, length = arr.length; i < length; i++) {
if (func.call(arr[i], arr[i], i) === false) {
break;
}
}
};
var divs = get("div");
each(divs, function (item, index) {
this.style.background = "red";
});

但是,这里为什么要用apply呢?

因为document.getElementsByTagName() 返回一个伪数组,但是push方法只能接受真数组,在这里调用apply,因为apply接受的其他参数必须是一个数组,这里把document.getElementsByTagName() 的返回结果进行展开,然后一个一个push进去.

当然也可以这么写,但是性能肯定不及原生方法性能高.

each( document.getElementsByTagName(tag),function(){
result.push(this);
})

再次体现了封装的意义.

下面JavaScript高级框架设计(二) 将会开始介绍基本选择器的实现

JavaScript 框架设计的更多相关文章

  1. JavaScript框架设计(三) push兼容性和选择器上下文

    JavaScript框架设计(三) push兼容性和选择器上下文 博主很久没有更博了. 在上一篇 JavaScript框架设计(二) 中实现了最基本的选择器,getId,getTag和getClass ...

  2. JavaScript框架设计(四) 字符串选择器(选择器模块结束)

    JavaScript框架设计(四) 字符串选择器(选择器模块结束) 经过前面JavaScript框架设计(三) push兼容性和选择器上下文的铺垫,实现了在某一元素下寻找,现在终于进入了字符串选择器 ...

  3. 偶的《javascript框架设计》终于出版

    #cnblogs_post_body p{ text-indent:2em!important; } 历时两年多,我的书终于付梓出版了.应各方面的要求,写软文一篇,隆重介绍一下此书对各位程序员的钱途有 ...

  4. JS读书心得:《JavaScript框架设计》——第12章 异步处理

    一.何为异步   执行任务的过程可以被分为发起和执行两个部分. 同步执行模式:任务发起后必须等待直到任务执行完成并返回结果后,才会执行下一个任务. 异步执行模式:任务发起后不等待任务执行完成,而是马上 ...

  5. Javascript框架设计思路图

    这个系列的随笔都是关于Javascript框架设计一书的读书笔记(作者是司徒正美),不是本人原创!!! 一.简介: 1.市面上主流的JS框架,大多数是由一个个模块组合而成,模块化是大多数让软件所遵循的 ...

  6. JavaScript 框架设计(二)

    JavaScript 高级框架设计 (二) 上一篇,JavaScript高级框架设计(一)我们 实现了对tag标签的选择 下来我们实现对id的选择,即id选择器. 我们将上一篇的get命名为getTa ...

  7. 浅谈JavaScript框架设计

    在这个js框架随处乱跑的时代,你是否考虑过写一个自己的框架?下面的内容也许会有点帮助. 一个框架应该包含哪些内容? 1.语言扩展 大部分现有的框架都提供了这部分内容,语言扩展应当是以ECMAScrip ...

  8. javascript框架设计(读书笔记)

    我觉得多看几本进阶的书 与其十本书读一遍,不如一本书读十遍 读书的启示: 读好书(看推荐) 精读(重复看) 能读厚书(javascript权威指南) Object.keys Object.keys=O ...

  9. JavaScript框架设计 第14章 动画引擎

    easing-js <!DOCTYPE html> <html> <head> <meta charset="utf-8"> < ...

随机推荐

  1. 爬虫笔记(四)------关于BeautifulSoup4解析器与编码

    前言:本机环境配置:ubuntu 14.10,python 2.7,BeautifulSoup4 一.解析器概述 如同前几章笔记,当我们输入: soup=BeautifulSoup(response. ...

  2. STM32之DAC君

    如花说得好:呃呃呃.是俗话说得好:有了ADC,怎可少了DAC..我觉得奇怪.今天我开头就直奔主题了.我想了想,总结了一句话:孙悟空纵然有七十二变.无论是变成猫也好,变成狗也罢.始终还是会变回他本身.所 ...

  3. (转)windows系统下Python环境的搭建

    原博文地址:http://www.cnblogs.com/windinsky/archive/2012/09/20/2695520.html 这段时间在做python,觉得这个配置环境的帖子还不错,分 ...

  4. <十四>JDBC_c3p0数据库连接池

    配置文件:c3p0-config.xml <!-- Hibernate官方推荐使用的数据库连接池即c3p0;dbcp是Tomcat在数据源中使用 --><c3p0-config> ...

  5. JSONP跨域处理实例

    <!DOCTYPE> <html> <head> <meta http-equiv="Content-Type" content=&quo ...

  6. CF2.D 并查集+背包

    D. Arpa's weak amphitheater and Mehrdad's valuable Hoses time limit per test 1 second memory limit p ...

  7. Altium Designer之AD16在Win10系统下无法切换走线/布线模式的解决办法

    有些童鞋会在Win10下使用AD16的时候发现,走线模式/布线模式(切换直角,45°,弧形等)不能切换. 问题出在输入法上,一般是切换到英文输入法即可解决,但是有一种情况是win10系统自带输入法有时 ...

  8. wamp2.5 局域网无法访问问题

    1.打开http.conf文件,在对应处修改为如下内容(通常经过步骤一之后就能访问了,若不行则再执行后面步骤) <Directory /> Options FollowSymLinks A ...

  9. GDB调试汇编分析

    GDB调试汇编分析 代码 本次实践我参照了许多先做了的同学的博客,有卢肖明,高其,张梓靖同学.代码借用的是卢肖明同学的代码进行调试运行. GCC编译 使用gcc -g gdbtest.c -o gdb ...

  10. android——自定义listView

    都知道微信主机面 有个界面会一行一一行的聊天记录,那个效果就可以用listview来实现(当然这只是其中的一种) listView是一种比较常见的组件它用来展示列的view,它是根据数据的长度来显示数 ...