背景
节点类型
var NODE_TYPE_ELEMENT = 1; // element
var NODE_TYPE_ATTRIBUTE = 2; // attribute
var NODE_TYPE_TEXT = 3; // text
var NODE_TYPE_COMMENT = 8; // comment
var NODE_TYPE_DOCUMENT = 9; // document
var NODE_TYPE_DOCUMENT_FRAGMENT = 11; // document fragment
对于 jqLite主要实现以下方法
addClass
实现原理:主要是判断 setAttribute是否存在,借助 setAttribute 和getAttribute 方法实现
具体实现:主要是借助 getAttribute 查找该元素原始的css 内容,然后查找这个css 内容中是否拥有新的class,如果没有就添加进去,然后把更新之后的css 内容 使用setAttribute 更新css 内容。
function jqLiteAddClass(element,cssClasses){
if(element && element.setAttribute){
// 获取原来的css
var exisingClass = ('' + (element.getAttribute('class') || '') + '').replace(/[\n\t]/g.' ');
forEach(classClasses.split(' '),function(cssClass){
cssClass = trim(cssClass);
// 如果存在的class 中不存在你需要添加的对象
if(existingClasses.indexOf('' + cssClass + '') === -1){
// 添加进去
existingClasses += cssClass + ' ';
}
})
// 更新元素的css 结果
element.setAttribute('class',trim(exisingClass ));
}
}
after
实现原理:主要是借助 parentNode 和 insertBefore 实现
具体实现:主要是查找到 element.nextSibling 将 newElement 插入到 nextSibling之前。
after:function(element,newElement){
var index = element,parent = element.parentNode;
newElement = new JQLite(newElement);
for(var i = 0,ii = newElement.length;i<ii;i++){
var node = newElement[i];
// 主要借助于 insertBefore 方法
parent.insertBefore(node,index.NextSibling);
index = node;
}
}
append
实现原理:主要是先利用nodeType 节点的类型,只有符合条件的节点类型才能被append ,然后利用appendChild方法实现append 功能
具体实现:获取节点类型(nodeType),如果不满足条件的节点类型则不做处理,否则就将新要插入的节点插入到节点中去(appendChild)
append:function(element,node){
var nodeType = element.nodeType;
if(nodeType !== 1 && nodeType !== 11){
return;
}
node = new JQLite(node);
for(var i = 0,ii = node.length;i<ii;i++){
var child = node[i];
// 主要通过appendChild 方法实现
element.appendChild(child);
}
}
attr
实现原理:setAttribute,getAttribute,removeAttribute
主要实现:先获取节点类型,如果节点类型不满足条件,则直接返回,如果满足则再判断名称是否是boolean 类型(multiple,selected,checked,disabled,readyOnly,required,open),则赋值true 或者 false。再者去判断是否存在value 如果存在就调用setAttribute 方法设置属性,如果不存在,则调用getAttribute 方法获取属性。
var BOOLEAN_ATTR = {};
forEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','),function(value){
BOOLEAN_ATTR[lowercase(value)] = value;
})
attr:function(element,key,value){
var nodeType = element.nodeType;
if(nodeType === 3 || element === 2 || element === 8){
return;
}
var lowercasedName = lowercase(name);
// 是否满足boolean 类型 的参数
if(BOOLEAN_ATTR[lowercasedName]){
if(isDefined(value)){
if(!!value){
element[name] = true;
element.setAttribute(name,lowercasedName);
}
else{
element[name] = false;
element.removeAttribute(name);
}
}
else{
// element.attribute.getNamedItem(name) 是 xml dom 的方法
return (element[name] || (element.attribute.getNamedItem(name) || noop).specified) ? lowercasedName: undefined;
}
}
// value 是否存在
else if(isDedined(value)){
element.setAttribute(name,value);
}
// 查看是否存在getAttribute 方法
else if(element.getAttribute){
// the extra argument '2' is to get the right thing for a.href in ie,see jquery code
// some element (eg:Document) don't have get attribute, so return undefined;
var ret = element.getAttribute(name,2);
return ret === null ? undefined : ret;
}
}
bind
比较复杂 待定
children
实现原理: childNodes
主要实现:主要遍历element 对象的 childNodes,然后判断 子节点类型是否是 NODE_TYPE_ELEMENT类型,如果是就返回
children:function(element){
var children = [];
forEach(element.childNodes,function(ele){
// 符合条件的 节点类型
if(ele.nodeType === 2){
children.push(ele);
}
})
return children;
}
clone
实现原理:cloneNode
主要实现:主要利用cloneNode 方法实现的
function jqLiteClone(element){
return element.cloneNode(true);
}
contents
实现原理:contentDocument childNodes
主要实现:首先获取元素的contentDocument 对象,如果获取不到就获取他的childNodes 再获取不到 返回 [ ]
content:function(element){
return element.contentDocument || element.childNodes || [];
}
css
实现原理: element.style
主要实现:主要根据 element.style 然后继续获取所需要的name ,也可以给name 赋值。
css:function(element,name,value){
name = camelCase(name);
// 如果定义了value 的值
if(isDefined(value)){
element.style[name] = value;
}
else{
return element.style[name];
}
}
data
detach
empty
eq
实现原理: this[index]
主要实现: 如果 index 是正数的话,则取其中的第N个元素,否则取 this.length + index 个元素
eq:function(index){
return index >=0 ? jqLite(this[index]) : jqLite(this[this.length + index]);
}
find
实现原理:getElementByTagName
主要实现:主要根据getElementByTagName实现
find:function(element,selector){
if(element.getElementByTagName){
return element.getElementByTagName(selector);
}
else {
return [];
}
}
hasClass
实现原理:getAttribute
主要实现:先判断要选择的元素是否拥有getAttribute方法,然后利用 getAttribute 搜索出class 实现
function jqLiteHasClass(element,selector){
if(!element.getAttribute){
return false;
}
var exitClasses = ' ' + (element.getAttribute('class') || ' ') + ' ';
exitClasses = exitClasses.replace(/\n\t/g,' ');
return exitClasses.indexOf(' ' + selector + ' ') > -1;
}
html
实现原理:innerHTML
主要实现:如果是获取某个元素的html 利用的是 innerHTML属性,如果是给某个属性赋值的话,
html:function(element,value){
// 如果 value 为空的话,则表示需要获取element 对象的 html 值,也就是innerHTML的内容
if(isUndefined(value)){
return element.innerHTML;
}
// 如果value 存在的话,则表示赋值操作
}
hasClass
实现原理: getAttribute('class') , indexOf()
主要实现: 主要通过 getAttribute('class') 获取到所有的 class 内容,然后通过indexOf 查看class 是否存在里面
function hasClass(element,selector){
if(!element.getAttribute) return false;
return (element.getAtribute('class')).replace(/[\n\t]/g, '' ).indexOf( selector ) > -1;
}
next
实现原理:nextElementSibling
主要实现:直接返回对象的 nextElementSibling
next:function(element){
return element.nextElementSibling;
}
on
off
one
parent
实现原理:parentNode, nodeType
主要实现:获取element 的 parentNode 对象 ,然后判断parent 对象类型是否合法,合法就返回,不合法就返回null
parent:function(element){
var parent = element.parentNode;
return parent && parent.nodeType !== 11 ? parent : null;
}
prepend
实现原理: nodeType fristChild insertBefore
主要实现:先判断类型,如果符合类型,则先获取元素的firstChild,然后遍历需要插入的节点,调用insertBefore插入进去就可以了
prepend:function(element,node){
if(element.nodeType === 1){
var index = element.firstChild;
forEach(new JQLite(node),function(child){
element.insertBefore(child,index);
});
}
}
prop
实现原理:很是霸气的直接取对象的属性
主要实现:
prop:function(element,name,value){
if(isDefined(value)){
element[name] = value;
}
else {
return element[name];
}
}
ready
实现原理: DOMContentLoaded, load ,document.readyState
主要实现:
ready:function(fn){
var fired = false;
function trigger(){
if(fired) return;
tired = true;
fn();
}
if(document.readyState === 'complete'){
setTimeout(trigger,1);
}
else{
this.on('DOMContentLoaded',trigger);
JQLite(window).on('load',trigger);
}
}
remove
实现原理:parentNode,removeChild
主要实现:
function jqLiteRemove(element,keepData){
if(!keepData){
// 待定。。。
}
var parent = element.parentNode;
if(parent){
parent.removeChild(element);
}
}
removeAttr
实现原理: removeAttribute
具体实现:
removeAttr:function(element,name){
element.removeAttribute(name);
}
removeClass
实现原理: setAttribute ,getAttribute('class'), replace(cssClass',' ')
具体实现: 主要利用getAttribute 获取class 内容,然后利用replace替换掉需要移除的属性 .
function jqLiteRemoveClass(element,cssClasses){
if(cssClasses && element.setAttribute){
forEach(classClasses.split(' '),function(cssClass){
element.setAttribute('class',trim(
('' + (element.getAttribute('class')) + '')
// 移除无效符号
.replace(/[\n\t]/g, ' ')
// 移除 需要移除的属性
.replace('' + trim(cssClass) + '', '');
))
})
}
}
removeData
replaceWith
实现原理:
具体实现:还是需要通过查找到需要替换元素的parentNode 节点,然后利用 replaceChild实现
replaceWith:function(element,replaceNode){
var index,parent = element.parentNode;
// 移除element 绑定的数据
forEach(new JQLite(replaceNode),function(node){
if(index){
parent.insertBefore(node,index.nextSibling);
}
else{
parent.replaceChild(node,element);
}
index = node;
})
}
text
实现原理:textContent
具体实现:
text: (function(){
getText.$dv = '';
return getText;
function getText(element,value){
if(isUndefined(value)){
var nodeType = element.nodeType;
// 必须满足条件才行。
return (nodeType === 1|| nodeType === 3) ? element.textContent :'';
}
element.textContent = value;
}
})()
toggleClass
实现原理:
主要实现:首先判断是否存在第三个参数,如果存在的话,则根据参数是否为true 则调用addClass 否则调用 removeClass,如果不存在的话,则调用hasClass函数,是否存在这个class ,根据是否存在设置第三个参数。
toggleClass:function(element,selector,condition){
if(selector){
forEach(selector.split(' '),function(className){
var classCondition = condition;
if(isUndefined(classCondition)){
classCondition = !hasClass(element,className);
}
(classCondition) ? addClass(element,className) : removeClass(element,className);
})
}
}
triggerHandler
unBind
val
实现原理: value , text , nodeName
主要实现: 主要区分select 对象, 因为可以multiple 多选,所以需要判断nodeName 是否是 select
val:function(element,value){
if(isUndefined(value)){
if(element.multiple && nodeName_(element) === 'select'){
var result = [];
forEach(element.options,function(option){
if(option.selected){
result.push(option.value || option.text);
}
});
return result.length === 0 ? null: result;
}
return element.value;
}
// 否则就是赋值操作
element.value = value;
}
wrap
实现原理:
主要实现: 找到element 元的父亲,将自身缓存下,然后将wrapNode替换掉原本直接所在的element 对方,然后将element 插入到wrapNode中去。
wrap:function(element,wrapNode){
// 克隆一个对象
wrapNode = jqLite(wrapNode).eq(0).clone()[0];
// 获取父亲
var parent = element.parentNode;
if(parent){
// 如果存在父亲,就将element替换成wrapNode 对象
parent.replaceChild(wrapNode,element);
}
// wrapNode节点插入 child 节点。
wrapNode.appendChild(element);
}
来源:oschina
链接:https://my.oschina.net/u/1037170/blog/548932