mini jquery

mini-jquery

无new构建思路

jQuery 官方采用IIFE(立即执行函数)以及对原型链 的操作完成了对于无new构建 的实现,那么无new构建是怎么实现的呢?

  1. 由上图可得,jQuery 既是函数也是对象,因此我们可以在对象上面添加属性fn,同时函数上面都有一个属性prototypeprototype是一个对象 ,我们让我们自己添加的属性fnprototype 指向同一个内存空间,然后在这个内存空间添加一个函数命名为init ,因为每一个函数都有一个属性prototype ,因此我们可以改变prototype 的指向,让其指向fn
  2. 由图上代码,我们可以知道new Result(selector, context)返回一个对象,每一个对象都有__proto__属性,__proto__属性指向其构造函数的prototype
  3. 最终执行jQuery函数会返回一个对象,this指向jQuery.fn.init这个函数,除此以外,我们在jQuery.fn上添加的属性最终也会因为原型链的关系可以拿到。

获取DOM元素的实现

实现了无new构建 以后,获取DOM元素就很简单了。jQuery早期获取DOM元素采用的是getElementById等,而随着技术的发展,querySelectorAll方法已经可以取代获取元素的一系列方法了,一个方法就实现通过id、class、标签获取DOM元素,早期还要通过各种判断来执行不同的方法

javascript 复制代码
 const jQuery = function (selector, context = document) {
    const Result = jQuery.fn.init
    const result = new Result(selector, context)
    return result
}
jQuery.fn = jQuery.prototype
jQuery.fn.init = function (selector, context) {
    if (!selector) return this
    this.dom = context.querySelectorAll(selector)
    return this
}
jQuery.fn.init.prototype = jQuery.fn

jquery各类方法的实现

javascript 复制代码
jQuery.fn.text = function (text) {
   if (text === undefined) {
        return Array.from(this.dom).map(node => node.textContent)
    }
    Array.from(this.dom).forEach(node => node.textContent = text)
    return this       
}
// css
jQuery.fn.css = function (key, value) {
    this.dom.forEach(el => el.style[key] = value)
    return this
}
// parent
jQuery.fn.parent = function () {
    return this.dom[0].parentElement
}
// 相邻下一个的元素
jQuery.fn.next = function () {
    return this.dom[0].nextElementSibling
}
// 相邻上一个的元素
jQuery.fn.prev = function () {
    return this.dom[0].previousElementSibling
}
// 所有兄弟元素
jQuery.fn.siblings = function () {
    const parent = this.parent()
    const children = parent.children
    return Array.from(children).filter(child => child !== this.dom[0])
}

jquery动画的实现

  1. 记录原始状态
  2. 记录要变化的状态
  3. 计算增量
  4. 计算帧率60fpsprogress(进度)
javascript 复制代码
 /**
  * 
  * @param {*} properties 要变化的状态
  * @param {*} duration 总耗时
  * @param {*} callback 额外执行的操作
  */
jQuery.fn.animate = function (properties, duration, easing = 'linear', callback) {
    // 1. 记录原始状态
    // 2. 记录要变化的状态
    // 3. 计算增量
    // 4. 计算帧率60fps progress进度
    const startStyle = {}
    // 获取dom元素
    const currentDom = this.dom[0]
    // 记录从页面加载到此刻所经历的时间(微秒)
    const startTime = performance.now()
    for (const key in properties) {
        startStyle[key] = parseFloat(getComputedStyle(currentDom)[key])
    }
    const animateStep = (currentTime) => {
        //currentTime 表示上一帧的渲染结束时间
        const elapsed = currentTime - startTime // 持续时间
        const progress = Math.min(elapsed / duration, 1) // 进度
        const cssNumberProperties = ['opacity', 'zIndex', 'fontWeight', 'lineHeight', 'zoom']
        for (const key in properties) {
            const startValue = startStyle[key] // 原始值
            const endValue = parseFloat(properties[key]) // 目标值
            const currentValue = startValue + (endValue - startValue) * progress
            currentDom.style[key] = cssNumberProperties.includes(key) ? currentValue : currentValue + 'px'
        }
        if (progress < 1) {
            requestAnimationFrame(animateStep)
        } else {
            callback && callback()
        }
    }
    // 返回当前60fps所需要的时间(微秒)
    requestAnimationFrame(animateStep)
}

requestAnimationFrame的回调函数会在每一次浏览器重绘前执行,这个回调函数的参数表示表示上一帧的渲染结束时间

我们使用performance.now()来记录从页面加载到此刻所经历的时间(微秒),因为其返回的值与requestAnimationFrame回调函数参数的值都是微秒级别的

动画曲线的实现

javascript 复制代码
const animateStep = (currentTime) => {
  const easingFunctions = {
      linear: t => t,
      easeIn: t => t * t,
      easeOut: t => t * (2 - t),
      easeInOut: t => t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t
  }
  const easingFunction = easingFunctions[easing] || easingFunctions.linear
  //currentTime 表示上一帧的渲染结束时间
  const elapsed = currentTime - startTime // 持续时间
  const progress = Math.min(elapsed / duration, 1) // 进度
  const easedProgress = easingFunction(progress)
  const cssNumberProperties = ['opacity', 'zIndex', 'fontWeight', 'lineHeight', 'zoom']
  for (const key in properties) {
      const startValue = startStyle[key] // 原始值
      const endValue = parseFloat(properties[key]) // 目标值
      const currentValue = startValue + (endValue - startValue) * easedProgress
      currentDom.style[key] = cssNumberProperties.includes(key) ? currentValue : currentValue + 'px'
  }
  if (progress < 1) {
      requestAnimationFrame(animateStep)
  } else {
      callback && callback()
  }            
}

jquery支持插件

javascript 复制代码
// 支持插件
jQuery.fn.$extend = function (obj) {
    for (const key in obj) {
        this[key] = obj[key]
    }
    return this
}

这里的this指向jQuery.fn

jquery支持ajax

javascript 复制代码
jQuery.ajax = function (url, options) {
  return new Promise((resolve, reject) => {
      const xhr = new XMLHttpRequest()
      xhr.open(options.method || 'GET', url, true)
      xhr.send(options.data || null)

      xhr.onreadystatechange = function () {
          if (xhr.readyState === 4) {
              if (xhr.status === 200) {
                  resolve(xhr.responseText)
              } else {
                  reject(xhr.statusText)
              }

          }
      }
  })
}

jquery当DOM渲染完毕执行的函数

javascript 复制代码
jQuery.ready = function (callback) {
    if (document.readyState === 'complete') {
        callback()
    } else {
        document.addEventListener('DOMContentLoaded', callback)
    }
}

DOMContentLoaded事件会在DOM渲染完毕之后立即执行callback函数

不监听load事件的原因?

load事件在DOM渲染完毕之后,还会等css、图片等资源加载完成才执行回调,单纯只是操作DOM的话没有必要等待css、图片等资源加载完毕

相关推荐
程序视点1 天前
【无标题】
jquery·jquery ajax·ajax请求方法·ajax全局事件
付朝鲜1 天前
用自写的jQuery库+Ajax实现了省市联动
java·前端·javascript·ajax·jquery
帆张芳显4 天前
前端EXCEL插件,智表ZCELL产品V3.0 版本发布,底层采用canvas全部重构,功能大幅扩展,性能极致提升,满足千万级单元格加载
前端·重构·excel·jquery·插件·智表
Enti7c6 天前
利用jQuery 实现多选标签下拉框,提升表单交互体验
前端·交互·jquery
梁云亮6 天前
Jquery ajax 提交序列化或JSON数据到后台
json·jquery·序列化
姜太小白17 天前
【前端】jQuery 对数据进行正序排列
前端·javascript·jquery
前端熊猫19 天前
jQuery AJAX、Axios与Fetch
ajax·okhttp·jquery
二月垂耳兔7981 个月前
jQueryHTML与插件
前端·jquery
Enti7c1 个月前
用 HTML、CSS 和 jQuery 打造多页输入框验证功能
css·html·jquery
ElasticPDF-新国产PDF编辑器1 个月前
HTML && jQuery PDF Annotation plugin library free online API examples
pdf·html·jquery