jQuery的设计模式

206 阅读1分钟

1.输入“选择器”,输出可以操作网页元素的api对象

  • jQuery的基本设计思想和主要用法,就是"选择某个网页元素,然后对其进行某种操作"。
  • jQuery(选择器)用于获取对应的元素,但它不返回这些元素,相反,它返回一个对象,称为api, 这个对象可以直接操作对应的元素
  • 下面,我们手写一个简单window.jQuery
window.jQuery = function(selectorOrArrayOrTemplate) {
    let elements
    if(typeof selectorOrArray === 'string'){
        // 传进来的是HTML标签
        elements = document.querySelectorAll(selectorOrArray)
    }else if(selectorOrArray instanceof Array){
        // 传进来的是数组
        elements = selectorOrArray
    }

    //elements就是要操作的元素或者节点

    let api = {
        // 下面这些函数可以操作 elements
        find(selector){
            let array = []
            for(let i =0;i<elements.length;i++){
                const elements2 = Array.from(elements[i].querySelectorAll(selector))
                array.push(...elements2)
            }
            array.oldApi = this // this 就是 旧 api
            return jQuery(array)
        },
        appendTo(selector) {

        },
        addClass(className) {
            
        },
        end(className){
            
        }

    }

    return api    
}

2.链式调用

  • jQuery的黑魔法之一就是支持链式调用,即
$('div')
  .find('h3')
  .addClass('red')
  .text('hi 我是新加的内容');
// 找到所有的div元素,在所有的div元素里找到h3标签,给h3标签增加'red'类,并且替换文本内容
  • 这一点能实现就是因为jQuery(selector)返回的是一个可以操作被选中元素的api
  • jQuery还提供end方法,使得结果集可以后退一步: 
$('div')
   .find('h3')
   .eq(2)
   .html('Hello')
   .end() //退回到选中所有的h3元素的那一步
   .eq(0) //选中第一个h3元素
   .html('World'); //将它的内容改为World

3.getter, setter设计模式

  • jQuery的设计思想之三就是使用同一个函数,来完成取值(getter)和赋值(setter)。
  • 到底是取值还是赋值,由函数的参数决定,这也是函数的重载。
$('h1').html(); //html()没有参数,表示取出h1的值

$('h1').html('Hello'); //html()有参数Hello,表示对h1进行赋值

4.运用函数重载

  • 运用函数重载,一个函数可以同时处理多种不同的参数
  • 举例,$()的参数不仅可以是选择器,还可以是html标签
$('.red')
$('<div><span>哈哈哈哈<span></div>')
$(元素数组)
  • 这是怎么实现的?
  • 答案是通过函数重载,写不同的if else判断情况
window.jQuery = function(selectorOrArrayOrTemplate){
  let elements
  if(typeof selectorOrArrayOrTemplate === 'string'){
    if(selectorOrArrayOrTemplate.trim().indexOf('<') === 0){
      // 传进来的字符串是HTML标签,例如$('<div><span>哈哈哈哈<span></div>'),
      // 所以我们需要创建对应的HTML标签,然后返回
      elements=[createElement(selectorOrArrayOrTemplate)]
    }else{
      // 查找 div 例如 $('.red')
      elements = document.querySelectorAll(selectorOrArrayOrTemplate)
    }
  }else if(selectorOrArrayOrTemplate instanceof Array){
    // 传进来的是节点数组,那么就赋值给elements, 开始下面的处理
    elements = selectorOrArrayOrTemplate
  }

  function createElement(string){
    const container = document.createElement("template");
    container.innerHTML = string.trim();
    return container.content.firstChild;
  }
  
  // api可以操作elements, this就是api, api就是this
  let api = {
    addClass(className){},
    find(selector){},
    each(){}  
  }
  
  return api

5.常用API

-$('div').append(选择器/ jQuery对象) 在div的子元素里,在最后一个位置添加元素,通俗来说就是加一个小儿子

  • $('<h2>哈哈哈</h2>').appendTo(选择器/ jQuery对象) 在选择器选中的元素的子元素里,从尾部添加“哈哈哈”
  • $('div').prepend('h2') 在div的所有子元素里,从头插入h2,通俗来说就是加一个大儿子
  • 类似的还有$('h2').prependTo($('div'))
  • $('#test').after($div) 加一个弟弟
  • $('#test').before($div) 加一个哥哥

  • $div.remove()
  • $div.empty()

改和查

  • $div.text(?) 读写文本内容 -$div.html(?)读写HTML内容
  • $div.css({'color': 'red'}) 读写css
  • $div.on('click', fn) - $div.off('click', fn)

6.实现一个简单的jQuery

  • 目标:
<div id=test>
  <div class=child>1</div>
  <div class=child>2</div>
  <div class=child>3</div>
</div>
window.jQuery = function(请补全){
  请补全
  return {
    addClass(){
        请补全
    },
    find(){
        请补全
    }
  }
}

window.$ = window.jQuery

$('#test').find('.child').addClass('red') // 请确保这句话成功执行
  • 补全以上的jQuery代码,使得$('#test').find('.child').addClass('red')这句话成功执行
window.jQuery = function(selectorOrArray) {
    let elements
    if(typeof selectorOrArray === 'string'){
        elements = document.querySelectorAll(selectorOrArray)
    }else if(selectorOrArray instanceof Array){
        elements = selectorOrArray
    }

    //elements就是要操作的元素或者节点

    let api = {
        // 下面这些函数可以操作 elements
        // $('#test').find('.child').addClass('red') // 请确保这句话成功执行
        
        find(selector){
           let resultArr = []
            for (let i = 0; i < elements.length; i++) {
                let childElements = elements[i].querySelectorAll(selector)
                resultArr.push(...childElements)
            }
            return jQuery(resultArr)
        },
        addClass(className) {
            this.each.call(this, (n)=>n.classList.add(className))
            return this
        },
        each(fn){
            for (let i = 0; i < elements.length; i++) {               
                fn(elements[i])
            }
            return this
        }
    }

    return api
}

window.$ = window.jQuery

$('#test').find('.child').addClass('red') // 请确保这句话成功执行

7.参考资料

www.ruanyifeng.com/blog/2011/0… www.jquery123.com/