1 Star 1 Fork 0

PaddyWang / paddy

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README

paddy

PaddyWang

paddy-03.js 较完善

paddy 对象是一个伪数组

paddy 框架里面所有的处理对象都是按照伪数组 paddy 来处理的

这样做的好处就是:不管传过来的参数是什么类型的都把它包装成 paddy 对象

  • 可以是:
    • 选择器字符串
    • html 字符串
    • dom 对象
    • dom 数组对象
    • 函数
    • paddy 对象

并做了兼容性处理

分为以下几个模块进行实现:

  • 基本选择器 可扩展 -> Sizzle
  • DOM 操
  • 事件模块
  • css模块 + class系列
  • html模块
  • 属性处理模块
  • 动画模块

静态成员

  • 判断函数
    • isString
    • isNumber
    • isBoolean
    • isFunction
    • isLikeArray
    • isPaddy
    • isDOM
    • isObject
  • 辅助性方法
    • each
    • trim
    • firstChild
    • lastChild
    • nextSibling
    • nextAllSibling
    • getText
    • setText
    • select
    • parseHTML

能力检测

  • support
    • getElementsByClassName
    • firstElementChild

实例成员

  • 实例方法
    • appendTo
    • append
    • remove
    • prependTo
    • prepend
    • next
    • nextAll
    • each
    • hover
    • toggle
    • css
    • hasClass
    • addClass
    • removeClass
    • toggleClass
    • attr
    • val
    • html
    • text
    • animate
    • stopAnimating
    • isAnimating

事件

  • Event
    • on
    • off
    • click input change mouse...

框架搭建:

  • 将整个框架放入一个沙箱中 避免对全局作用域的污染
  • 将 paddy 对象添加到 window 对象上 避免了对原生对象的修改
  • 将所有的要操作的 DOM 对象包装成 paddy 对象
  • 即可实现通过 P 或 paddy 进行方法直接调用
    (function(windown, undefined){
        function paddy(p){ 
            return new paddy.fn.init(p);
        }
        windown.P = windown.paddy = paddy;
    })(windown);

初始化函数:init

paddy对象参数处理

对传入的参数 p 进行判断

  • 如果是空直接 return 掉
  • 如果是字符串 可能为选择器 selector 也可能为 html 标签字符串
    • 如果是 selector 则调用 paddy.select 方法
      • 将查询到的 dom 对象添加到 paddy 对象上
    • 如果是 html 标签字符串则调用 paddy.parseHTML方法
      • 将解析后的标签添加到 paddy 对象上
  • 如果是 DOM 对象 -> 包装成 paddy 对象
  • 如果是 paddy 对象 -> 将该对象中的成员拷贝到新的 paddy 对象中
  • 如果是数组 -> 则将数组中的成员添加到 paddy 对象上
  • 如果是 function 则代表入口函数
入口函数

等页面加载完成之后再进行执行的函数体

有三种处理方法:

1 >  在IE中执行顺序会出现问题
window.onload = fn;
if(window.addEventListener){
    window.addEventListener('load', fn);
}else {
    window.attachEvent('onload', fn);
}

2 >
var arr = [ ];
function load( fn ){
    arr.push( fn );
    wondow.onload = function( ){
        for(var i = 0; i < arr.length; i++){
            arr[ i ]( );
        }
    }
}

3 >
function load( fn ){
    var oldLoad = window.onload;
    if(typeof oldLoad != 'function'){
        window.onload = fn;
    }else {
        oldLoad( );
        fn( );
    }
}

extend:

添加静态方法和添加实例方法公用一个 extend 方法

  • 添加静态方法
    • paddy.extend({ });
  • 添加实例方法
    • paddy.fn.extend({ });

搜索引擎模块 select

paddy-03.js 采用的是在沙箱全局声明一个 select 函数

paddy-04.js 则把 select 当成 paddy 的一个静态方法来处理

  • 思路:
    • 通过正则对选择器字符串进行匹配处理
    • 在这里只对基本选择器进行实现
    • 基本选择器:id class tag *
    • 最终将获取到的元素放到一个数组中返回

id选择器:

需要注意的是:当页面中没有指定 id 的标签时会返回 null

此时的处理是:进行判断如果不为 null 则添加到数组中 否则将数组赋值为 null

class选择器:

在IE低版本中不支持 getElementsByClassName 方法

  • 兼容处理

    • 先进行浏览器能力检测,如果存在该方法就用该方法
    • 如果不存在,则获取页面中所有的标签,并进行循环遍历
    • 对每个标签的 className 属性值进行判断是否符合要求
  • 判断技巧

    • 用 indexOf 方法进行字符串查找
    • 为了查找的精确性,进行空格处理
    • 当标签存在多个 class 属性时
    • 每个 class 中间用空格隔开的
    • 所以在这里先给每个标签的 class 属性两端添加一个空格
    • 这样每个 class 两端都有一个空格了
    • 接下来给匹配的字符串两端也加上空格,这样就可以达到精确匹配了

tag 和 * 选择器:

将标签和 * 选择器放一块处理是因为它们公用一个 getElementsByTagName 方法

这里采用了一个小技巧:利用 exec 方法的返回值,匹配到有值,匹配不到 undefined

扩展:

为了让选择引擎更加强大可以调用 select.js (暂时实现了基本选择器和后代选择器)

也可以调用 jQuery 的 Sizzle.js

paddy.select = Sizzle;

字符串解析 parseHTML

'<div><div>div</div><p>p</p></div>'

当传入的是 html 字符串时,需要将其解析成对应的标签

利用的是 innerHTML 可以将 html 字符串解析成对应的标签这一特性

再将解析出来的标签放入一个数组中,并返回

最后再把 select 和 parseHTML 方法添加到 paddy 的静态成员上

辅助方法 each 和 trim

each
  • 两个参数:一是数组或对象,二是回调函数

当为数组时进行 for 循环遍历

当为对象时进行 for-in 循环遍历

回调函数可以传入两个参数:一个是循环的当前项,一个是当前项的值,即键值对

这里的回调函数用 call 上下文调用的

将函数中的 this 指向到循环的当前项的值

当回调函数返回 false 时,则终止循环

注意:如果数组里面是基本类型的值则 this 会把基本类型的值变成包装对象

trim
  • 去除字符串两端的空格

IE 低版本中不支持该方法

兼容性处理:进行 replace 字符串两端空格替换为 ''

实例方法

appendTo
  • 将调用者添加到指定的对象中,并返回调用者 paddy 对象

调用者是 paddy 对象,指定者也是 paddy 对象

循环遍历指定对象和调用者对象

方法 1 > 通过双重 for 循环进行遍历

方法 2 > 通过 each 套 each 的方法进行双重循环遍历

最终都是通过 appendChild 方法将调用者添加到指定对象中

为了达到链式编程的效果这里返回的是 paddy 对象

注意:每个标签对象只能有一个父元素

所以要对标签进行深克隆

在进行克隆的时候进行判断

如果是指定对象的最后一个标签则不需要进行克隆

这里通过指定对象的长度来进行判断

demo

P('<div><p>p</p><div>').appendTo('.box');  
// 将 P 中的的标签添加到所有的 .box 中   

P('.div').appendTo('.box');
// 将所有的 .div 标签添加到 .box 中
append

将指定对象添加到调用者中,返回指定对象 paddy

直接调用appendTo方法即可

demo

P('.box').append('<div><p>p</p><div>');  
// 将 append 中的的标签添加到所有的 .box 中   

P('.box').appendTo('.div');
// 将所有的 .div 标签添加到 .box 中
remove

移除调用者元素 ,无返回值

each 遍历,removeChild

demo

P('.box').remove( );
// 移除所有的 .box
prependTo
  • 将调用者添加到指定对象的最前面,返回调用者 paddy 对象
  • 思路
    • 将元素添加到指定对象的第一个孩子标签之前
    • 即:dom.insertBefore(newNode, firstChild);
    • 通过 each 套 each 进行循环遍历
    • 同样需要进行节点克隆

firstChild(dom)

node.firstChild 用于获取 node 节点的第一个子节点, 包括换行和文本

node.firstElementChild 用于获取 node 节点的第一个子标签节点, IE 低版本不支持

于是需要一个通用的 firstChild 方法

  • 兼容处理:
    • 获取 node 的所有子节点进行循环遍历
    • 通过 nodeType 进行节点类型判断

demo

P('<div>div</div>').prependTo('.box');
// 将 P 中的元素添加到所有的 .box 最前面

P('.div').prependTo('.box');
// 将所有的 .div 元素添加到所有的 .box 最前面
prepend

将指定元素添加到调用对象最前面,返回指定对象 paddy 对象

内部直接调用 prependTo 方法

demo

P('.box').prepend('<div>div</div>');
// 将 prepend 中的指定元素添加到所有的 .box 中

P('.box').prepend('.div');
// 将 prepend 中的所有的 .div 元素添加到所有的 .box 中
next

获取下一个兄弟标签元素 ,无参数, 返回符合要求的标签元素的 paddy 对象

node.nextSibling 获取下一个元素, 包含换行和空格

node.nextElementSibling 获取下一个标签元素, IE 低版本不支持

nextSibling(dom)

  • 兼容处理:
    • 通过 while 循环的同时进行赋值
    • 在赋值的同时再进行判断
    • 当 = 右边为空时跳出循环
    • while(dom = dom.nextSibling){ }

demo

P('div').next( );
// 获取所有的 div 标签的下一个标签元素
nextAll

获取后面的所有的兄弟标签,无参数, 返回所有的符合要求的 paddy 对象

思路和处理方式同上

demo

P('#box').nextAll( );
// 返回 #box 后面的所有兄弟标签

P('div').nextAll( );
// 返回所有 div 标签后面的所有兄弟标签
// 这里会出现重复的标签
each

给实例对象添加一个 each 方法

用于遍历 paddy 对象,传入一个回调函数

回调函数内的 this 指向每个 DOM 对象

内部调用了 paddy 对象的 each 静态方法

demo

P('div').each(function(){ });
// 对 paddy 对象进行循环遍历

事件

Event

给 paddy 对象添加一个 Event 对象

Event 为自定义事件对象

该对象中包含对原始事件对象 e 的修改

实际上是对 e 的属性进行处理

并将 Event 的原型对象的 constructor 设值

on

用于绑定事件

可以同时绑定一个或多个事件

多个事件通过 , 号分隔

实现思路:

遍历当前调用对象,给每个对象绑定由 on 指定的事件

同时将事件通过 split 分开,并进行遍历

用 call 调用回调函数,并将自定义的 Event 对象作参数传进行

demo

P('div').on('click, keydown', fn);
// 给所有的 div 标签添加 click 和 keydown 事件
off

用于移除绑定的事件

需要注意的是:

移除的对应事件中的回调函数要与 on 绑定的一致

即:同一个函数

添加事件

通过 each 遍历添加单独的事件

给每个原型上遍历,动态添加每个单独的事件

hover

鼠标经过和离开时触发

两个参数 fn1 ,fn2

经过执行 fn1 ,离开执行 fn2

demo

P('#box').hover(fn1, fn2);
// 鼠标经过 #box 时执行 fn1 ,离开时执行 fn2
toggle

鼠标点击时触发

可以传一个或多个参数

demo

P('#box').toggle(fn1, fn2, fn3...);
// 鼠标点击 #box 第一次执行 fn1 ,点击第二次执行 fn2 ...
// 点击一圈之后继续从 fn1 开始

样式

css

获取或设置css样式

当一个参数时:用于获取当前对象的样式,这里获取的是第一个对象的样式

当两个参数时:第一个代表样式属性,第二个代表属性的值

当一个 json 格式的样式时,可以设置多个样式

实现思路:

函数有两个形参,先判断第一个形参是否是一个对象

如果第一个参数是一个对象,则直接遍历调用对象,

并参数对象遍历添加到调用对象的样式上

两个参数时:

如果第二个参数不存在则代表获取样式值

这里用的是 window 对象上计算后的样式

window.getComputedStyle(this[0])[cssName];

否则则是对一个样式进行赋值

demo

P('#box').css('width');
// 获取 #box 的 width 样式值
P('#box').css('width', '300px');
// 设置 #box 的width 的值为 300px
P('div').css({
    width: '300px',
    height: '100px'
});
// 给所有的 div 标签设置 width 和 height 样式值
// width 等键可加引号也可不加

class 系列

hasClass

判断调用对象是否含有指定的 class

这里查找的是调用对象的第一个对象

demo

P('div').hasClass('box');
// 查找第一个 div 标签是否含有 box 类名
// 如果存在返回 true ,否则返回 false
addClass

给所有的调用对象添加指定的 class 值

demo

P('div').addClass('box');
// 给所有的 div 标签添加 box 类名
removeClass

用于移除调用对象中的类名

有参数时删除指定的类名

没有参数时删除所有的类名

实现思路:

有参数时:先获取到调用对象的类名,

然后给类名两端添加空格

并给参数两端添加空格

最后进行 replace 匹配替换

无参数时直接设置空

demo

P('div').removeClass('box');
// 移除所有 div 标签中包含的 box 类名
P('div').removeClass();
// 移除所有 div 标签中的所有类名
toggleClass

调用对象有指定的类名则移除,无则添加

实现思路:

对 hasClass ,removeClass 和 addClass 的结合

调用上面封装好的三个方法即可

demo

P('div').toggleClass('box');
// 移除所有所有当前 div 标签中包含的 box 类名
// 并给所有当前 div 标签中没有 box 类名的添加一个 box 类名

属性操作 attr & val

attr

获取、修改或添加属性

当一个参数的时候:获取指定的属性,只获取第一个调用对象的指定属性

当两个参数的时候,修改或添加指定的属性

实现思路:

判断是否存在第二个参数,如果不存在则进行属性获取操作

两种方法:可以以动态获取或添加属性的方法操作

也可以利用 get 或 set 进行操作

demo

P('img').attr('src');
// 获取第一个 img 标签的 src 属性
P('div').attr('title', 'haha');
// 给所有的 div 标签添加一个 title 属性,值为 ‘haha’
val

设置或获取指定标签的 value 值

可传入一个或不传参数

当无参数时:用于获取第一个调用对象的 value 值

当有参数时:用于设置所有调用对象的 value值

demo

P('input').val();
// 获取第一个 input 标签的 value 值
P('input').val('haha');
// 给所有的 input 标签设置 value 值为 ‘haha’

html & text

html

用于获取或设置 innerHTML 内容

当无参数时:用于获取第一个调用对象的 innerHTML 内容

当有参数时:用于设置所有调用对象的 innerHTML 内容

内部调用了 innerHTML 方法

demo

P('div').html();
// 获取第一个 div 标签的 innerHTML 信息
P('div').html('<p>p</p>');
// 给所有的 div 标签 innerHTML 添加一个‘<p>p</p>’
// innerHTML 会将 div 标签内的所有内容替换为 <p> 标签
text

用于获取或设置 innerText

无参数时:用于获取

有参数时:用于设置

兼容性解决:IE低版本不支持 innerText 方法

这里提供一个 getText 和一个 setText 方法

getText :递归获取所有的文本信息

即 nodeType === 3 时的 nodeValue 的值

setText :直接创建一个问题节点 appendChild 里面

createTextNode

demo

P('div').text();
// 获取 第一个 div 标签内个文本信息
P('div').text('<p>p</p>');
// 给所有的 div 标签设置 ‘<p>p</p>’ 字符串

动画

animate

动画函数:在指定时间内,以指定的效果完成指定的样式,最后执行指定的函数

四个参数:

target :样式对象,json 对象的形式

dur :执行时间,毫秒

easingName :动画效果

callback :执行完动画之后的回调函数

实现思路:

样式对象有:top | left | width | height

将其样式值看出一个总路程,然后在指定的时间内走总路程的长度

辅助性方法:

attrs :存放着样式名

getDisctance :路程处理函数

总路程 = 终止点 - 起始点

getLocation :获取初始状态的函数

easings :动画效果出来函数

setStyle :设置动画样式的函数

easing :动画效果对象 liner :匀速 | minusspeed :匀减速

t :当前时间 b :起始位置 c :终点位置 d:总时间

所有的辅助性方法都是返回一个对象

在 animate 函数中是对所有的辅助性方法返回对象的处理

demo

P('div').animate({
    width: '300px',
    top: '50px',
    left: '100px'
}, 1000, 'liner', fn);
// 所有的 div 标签在 1000 毫秒内,
// 以匀速的效果,将宽度变为 300px,top 为50px ,left 为 100px 
// 最后完成之后执行函数 fn
stopAnimating

停止当前的动画

清除当前动画的定时器即可

isAnimating

判断是否有动画在执行

在最外层设置一个 timerId 属性用于记录当前是否有动画在执行

空文件

简介

封装一个小型paddy框架 展开 收起
JavaScript
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
JavaScript
1
https://gitee.com/paddywang/paddy.git
git@gitee.com:paddywang/paddy.git
paddywang
paddy
paddy
master

搜索帮助