iT邦幫忙

1

You Might Not Need JQUERY 閱讀整理

前言

看一波 You Might Not Need JQUERY
整理一些常用的 順便同時複習 JS 和 JQ

大綱

  • 通用選擇器
  • DOM選擇器
  • 取得 HTML, 屬性, Style, Text
  • CSS Class操作
  • CSS 位置、大小 (取得/設定)
  • Effect (show/fade/fadeIn)
  • DOM 操作 (判斷)
  • DOM 操作 (刪除/改變/複製)
  • DOM 操作 (建立/插入/順序)
  • insertAdjacentHTML (DOM插入萬金油)
  • DOM 操作 (迴圈執行)
  • Events (事件監聽、ready、自定義事件)
  • Array 陣列相關 (each, map, inArray, isArray)
  • Utils 功能型 (Date(), ParseJSON, trim())
  • AJAX (JSON, POST, Request)

通用選擇器

  • JQ 選擇器才可使用 JQ方法,勿混用
  • JQ 可一次多選多個子元素並作處理
  • JS 使用doqsAll 需要迴圈去套用樣式、設置監聽或事件代理處理
  // JS
  document.querySelector('.')
  document.querySelectorAll('.')

  //JQ
  $('.test') 

DOM選擇器

  • JQ限定 找首 $(el).first()
  • 找父
  • 找子
  • 找兄弟
  // 找父
  $(el).parent();
  el.parentNode

  // JQ 找子,只找下一層
  $(el).children()
  // 回傳 NodeList 可先 Array.From() 轉成陣列
  el.children

  // 找子/後代
  $(el).find('li');
  el.querySelectorAll('li');
  
  // JQ 限定
  $(el).first()

  // 找兄弟
  $(el).siblings();
  Array.prototype.filter.call(el.parentNode.children, function(child){
    return child !== el;
  });

  // 找上、下個兄弟節點
  $(el).prev();
  $(el).next();
  el.nextElementSibling
  el.previousElementSibling

取得 HTML, 屬性, Style, Text

HTML, 屬性, Style, Text

  // 設定 DOM 內容
  $(el).html(string)
  el.innerHTML = string

  // 取得 HTML
  $(el).html()
  el.innerHTML

  // 取得 Outer HTML (包含自己)
  $('<div>').append($(el).clone()).html();
  el.outerHTML
  
  // 取得屬性
  $(el).attr('color');
  el.getAttribute('color');

  // 設定屬性
  $(el).attr('tabindex', 3);
  el.setAttribute('tabindex', 3);


  // 取得Style 用-而非駝峰
  $(el).css('background-color')
  getComputedStyle(el)['background-color'];

  // 設定Style
  $(el).css('border-width', '20px');
  // 最好使用Class
  el.style.borderWidth = '20px';


  // 取得文字
  $(el).text();
  el.textContent

  // 設定文字
  $(el).text(string);
  el.textContent = string;

CSS Class操作

  • IE9- 無法使用ClassList,相容寫法整理在下
  // JS
  el.classList.add('show')
  el.classList.remove('show')
  el.classList.toggle('show')
  el.classList.contains('show')

  $(el).addClass('show')
  $(el).removeClass('show')
  $(el).toggleClass('show')
  $(el).hasClass('show')
  // JS Add Class (IE8 寫法)
  if(el.classList) {
    el.classList.add(className)
  } else {
    el.className += ' ' + className
  }

  // Has Class  (IE8 寫法)
  $(el).hasClass(className);
  if (el.classList) {
    el.classList.contains(className);
  } else {
    new RegExp('(^| )' + className + '( |$)', 'gi').test(el.className)
  }

  // Remove Class (IE8 寫法)
  if (el.classList) {
    el.classList.remove(className);
  } else {
    el.className = el.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
  }

  // Toggle Class (IE9+ 寫法)
  if (el.classList) {
    el.classList.toggle(className);
  } else {
    var classes = el.className.split(' ');
    var existingIndex = classes.indexOf(className);
    if (existingIndex >= 0)
      classes.splice(existingIndex, 1);
    else
      classes.push(className);
    el.className = classes.join(' ');
  }

CSS 位置、大小 (取得/設定)

  • scrollTop [元素頂端和ViewPort最頂端之間的距離]
  • getBoundingClientRect() [Viewport 的 相對位置]
  • getComputedStyle() [計算運算後的元素各Style]

上面幾個有空會寫一篇文整理一波

  // 取得位置
  $(el).position();
  {left: el.offsetLeft, top: el.offsetTop}

  // Viewport 的 相對位置
  var offset = el.offset();
  {
    top: offset.top - document.body.scrollTop,
    left: offset.left - document.body.scrollLeft
  }
  // JS
  el.getBoundingClientRect()


  // Outer Height
  $(el).outerHeight();
  el.offsetHeight

  // Outer Height + Margin
  $(el).outerHeight(true);
  function outerHeight(el) {
    var height = el.offsetHeight;
    var style = getComputedStyle(el);
    height += parseInt(style.marginTop) + parseInt(style.marginBottom);
    return height;
  }
  outerHeight(el);

  // Outer Width
  $(el).outerWidth()
  el.offsetWidth

  // Outer Width + Margin 可與 上面的合併用帶入參數判斷
  $(el).outerWidth(true);
  function outerWidth(el) {
    var width = el.offsetWidth;
    var style = getComputedStyle(el);
    width += parseInt(style.marginLeft) + parseInt(style.marginRight);
    return width;
  }
  outerWidth(el);

  // Offset
  $(el).offset();
  var rect = el.getBoundingClientRect();
  {
    top: rect.top + document.body.scrollTop,
    left: rect.left + document.body.scrollLeft
  }

  // Offset Parent
  $(el).offsetParent();
  el.offsetParent || el

Effect (show/fade/fadeIn)

  • show / fade
  • fadeIn 原生寫法不是很懂
  • 動畫可用 animate.css + js 去給 Class 實現
  $(el).show()
  $(el).hide()
  el.style.display = ''
  el.style.display = 'none'
  
  $(el).fadeIn()
  
  function fadeIn(el) {
    el.style.opacity = 0
    var last = +new Date()
    var tick = function() {
      el.style.opacity = +el.style.opacity + (new Date() - last) / 400
      last = +new Date()
      if (+el.style.opacity < 1) {
        (window.requestAnimationFrame && requestAnimationFrame(tick)) || setTimeout(tick, 16)
      }
    }
    tick()
  }
  fadeIn(el)

DOM 操作 (刪除/改變/複製)

  • cloneNode 參數 true:深拷貝(含子) false:淺拷貝 (僅複製自身)
  • 複製後 還是要做插入的動作
  • 使用 clone 要注意是否會造成 一樣的ID 切記!!
  // 刪除子元素
  $(el).remove();
  // JS Old
  el.parentNode.removeChild(el);
  // JS IE 不支援
  el.remove()

  // 用 OO 取代自身
  $(el).replaceWith(string);
  el.outerHTML = string;

  // 複製節點
  $(el).clone();
  el.cloneNode(true);

  // 清空父元素之下
  $(el).empty()
  el.innerHTML = ''

DOM 操作 (判斷)

  • 判斷節點是否符合
  • 判斷節點是否符合選擇器
  • 判斷子是否存在
  • 判斷子是否為其子元素
  // 判斷節點是否符合
  $(el).is($(otherEl));
  
  el === otherEl
  if (e.target.classList.contains('')) { }
  if (e.target.tagName.toLowerCase() === 'a') {}

  // 判斷節點是否符合選擇器
  $(el).is('.my-class');
  
  var matches = function(el, selector) {
    return (el.matches || el.matchesSelector || el.msMatchesSelector || el.mozMatchesSelector || el.webkitMatchesSelector || el.oMatchesSelector).call(el, selector);
  };
  matches(el, '.my-class');
  
  // 判斷子是否存在
  $(el).find(selector).length;
  el.querySelector(selector) !== null

  // 判斷子是否為其子元素
  $.contains(el, child);
  if((el !== child) && el.contains(child))

DOM 操作 (建立/插入/順序)

  • insertAdjacentHTML DOM插入萬金油
  • JS creatElement('p')
  • JS prepend / append (同JQ寫法,但IE不支援)
  • prepend / append 若元素存在,會進行移動
  • JS appendChild / insertBefore (IE支援版)
  // JS 建立元素
  document.creatElement('p')
  
  // 插入前
  $(parent).prepend(el);
  // JS OLD
  parent.insertBefore(el, parent.firstChild);
  // JS IE不支援
  el.prepend()

  // 插入父元素下
  $(parent).append(el);
  // JS OLD
  parent.appendChild(el);
  // JS IE不支援
  el.append()

  // 插入其前、後
  $(el).after(htmlString)
  $(el).before(htmlString)

insertAdjacentHTML (DOM插入萬金油)

  • 動作有四種(設定position參數)
  1. beforebegin: 加在 elem 之前
  2. afterbegin: 加在 elem 裡面,首個子元素之前
  3. beforeend: 加在 elem 裡面,末個子元素之後
  4. afterend: 加在 elem 之後
  el.insertAdjacentHTML( position , htmlString)

DOM 操作 (迴圈執行)

  // 迴圈執行
  $(selector).each(function(i, el){ });
  const elements = document.querySelectorAll(selector);
  Array.prototype.forEach.call(elements, function(el, i){  });

  // 符合的元素才執行
  $(selector).filter(filterFn)
  Array.prototype.filter.call(document.querySelectorAll(selector), filterFn)

Events

  • on off 事件監聽 掛載 & 移除
  • 自定義事件 沒用過 (求放過...)

關鍵字搜尋 Trigger Custom / Trigger Native

  // on off 事件監聽
  $(el).on('click', Func)
  el.addEventListener('click', Func)
  $(el).off('click', Func)
  el.removeEventListener('click', Func)

  // Ready
  $(document).ready(function(){ })
  
  // 作者 ready
  function ready(fn) {
    if (document.attachEvent ? document.readyState === "complete" : document.readyState !== "loading"){
      fn()
    } else {
      document.addEventListener('DOMContentLoaded', fn)
    }
  }
  
  // 個人寫法
  ;(function () {
    document.addEventListener('DOMContentLoaded', () => {})
  }())

Array 陣列相關

  • forEach / filter / map
  • $.grep 等同 ES6 Filter
  • inArray 找 Array 內的內容
  • isArray 判斷是否為陣列
  • LearnMore 可以看看我撰寫的其他篇陣列整理
  // 判斷是否為陣列
  $.isArray(arr)
  Array.isArray(arr)
  
  $.each(arr, function(i, item){ })
  arr.forEach(function(item, i){ })
  
  $.map(arr, function(value, index){ })
  arr.map(function(value, index){ })

  // 找項目
  $.inArray(item, arr)
  // indexOf 回傳-1表找不到
  arr.indexOf(item)

Utils 功能型

  • 時間 Now
  • Parse JSON
  • trim 字串去除前後的空白

P.S. 其他看不是很懂 待補.....
Bind, Deep Extend, Extend, Parse Html, Type

  // 時間 Now
  $.now()
  Date.now()
  
  // Parse JSON
  $.parseJSON(string)
  JSON.parse(string)
  
  // Trim
  $.trim(string)
  string.trim()

AJAX

  • 原生 JS 用 XMLHttpRequest 支援度最高
  • 推薦使用 axios
    // JS XHR 範例
    getData('https://jsonplaceholder.typicode.com/users')
    function getData(url) {
      const xhr = new XMLHttpRequest()
      xhr.open('GET', url, true)
      
      // onreadystatechange & onload 則一即可
      xhr.onload = function () {
        if (xhr.status === 200) {
          console.log(this.responseText)
        }
      }
      
      xhr.onreadystatechange = function () {
        if (this.readyState === 4 && this.status === 200) {
          console.table(JSON.parse(this.responseText))
        } else if (this.status === 404) {
          console.log('Not Found')
        }
      }
      xhr.onerror = function () {
        console.log('Request Error...')
      }
      xhr.send()
    }
  // JSON
  $.getJSON('/my/url', function(data) { })
  // JS 使用 XHR

  // POST
  $.ajax({
    type: 'POST',
    url: '/my/url',
    data: data
  })
  
  // JS XHR
  const request = new XMLHttpRequest()
  request.open('POST', '/my/url', true)
  request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded charset=UTF-8')
  request.send(data)

  // Request
  $.ajax({
    type: 'GET',
    url: '/my/url',
    success: function(resp) { },
    error: function() { }
  });
  // JS 使用 XHR

參考資料

YOU MIGHT NOT NEED JQUERY
jQuery Cheat Sheet


1 則留言

0
小魚
iT邦大師 1 級 ‧ 2019-06-02 23:03:19

標題是 You Might Not Need JQUERY

為什麼裡面介紹了很多jQuery,
所以到底是推薦用還是不推薦用?

看更多先前的回應...收起先前的回應...
RocMark iT邦新手 5 級 ‧ 2019-06-03 08:40:55 檢舉

只是整理對比而已,你可以看一下參考資料的原文,用不用是看你專案和團隊而訂,我只是作為學習有對比跟看過一遍,之後真用的上jQuery上手會快的多。

小魚 iT邦大師 1 級 ‧ 2019-06-03 09:55:15 檢舉

喔喔,
不過如果是用現在流行的框架像React, Vue之類的,
應該是不適合用jQuery..

dragonH iT邦超人 5 級 ‧ 2019-06-03 11:05:43 檢舉

不適合也不必要我覺得

因為vue那些框架是以操作data為主

跟jquery操作dom為主不太一樣

如果真要在 vue 操作 dom

也有 $ref 可以用

另外就是 jquery 太肥了

jquery 就有 1w+ 行程式碼

vue也才不過 1w 出頭(忘記在哪看到的

小魚 iT邦大師 1 級 ‧ 2019-06-03 14:31:38 檢舉

其實在Vue, React這些框架出現之前,
jQuery是還蠻好用的,
不過Vue, React這些基本上是需要前後端分離,
但是jQuery不需要,
這就看需求了.
肥不肥我倒覺得還好,
放本機占用的是磁碟空間,
其實也沒差多少,
如果是用連結基本上就沒什麼差了...

我要留言

立即登入留言