Ajax 板


LINE

JavaScript 在经过这几年的进化之後, 原本大家习惯使用第三方函示库(例如 jQuery)包装的 DOM 操作方法, 现在都能够使用原生的 JavaScript 来达成了。 参考:https://www.sitepoint.com/dom-manipulation-vanilla-javascript-no-jquery/ 【一、查询和取得 DOM】 我们有很方便的 querySelector() 和 querySelectorAll() 方式来取得 DOM。 // 取得单一元素 const oneElement = document.querySelector('#foo > div.bar') // 取得所有符合的元素 const allElements = document.querySelectorAll('.bar') 可以透过 matches() 方式检查元素是否符合指定的选择器。 oneElement.matches('div.bar') === true 也可以在特定的元素底下继续查询。 const button = allElements.querySelector('button[type="submit"]') 那以前惯用的 getElementById()、getElementsByTagName() 呢? 当然也可以使用,但是 querySelector 不能动态更新查询到的元素。 const elementsNew = document.querySelectorAll('div') const elementsOld = document.getElementsByTagName('div') // 动态插入一个新的 div const newDiv = document.createElement('div') document.body.appendChild(newDiv) // elementsOld 会拿到 newDiv;elementsNew 则否。 elementsNew.length !== elementsOld.length 把 querySelectorAll() 回传的 NodeList 转成 Array 之後, 就能用 forEach() 方式走访每个元素。 Array.from(allElements).forEach(element => { // do something... }) // IE 还不支援 Array.from(),可以用: Array.prototype.forEach.call(allElements, element => { // do something... }) // 更短的写法: [].forEach.call(allElements, element => { // do something... }) 【二、修改 class 和属性】 要修改元素的 class,可以用方便的 classList 操作。 oneElement.classList.add('baz') oneElement.classList.remove('baz') oneElement.classList.toggle('baz') // 检查是否有指定的 class oneElement.classList.contains('baz') 要修改元素的属性(attribute),直接指定给该元素即可。 // 取得属性 const oneValue = oneElement.value // 设定属性 oneElement.value = 'hello' // 一口气设定好多种属性,用 Object.assign() Object.assign(oneElement. { value: 'hello', id: 'world' }) // 要删除属性,设定成 null 就好 oneElement.value = null 等等,那为何不用 getAttribute()、setAttribute() 和 removeAttribute () 呢? 因为这些方式是直接修改 HTML 的属性,会导致浏览器进行重绘(redraw), 对效能来说是很大的影响(换句话说就是很慢)。 但如果你要修改的属性真的需要重绘画面(例如表格的 colspan 属性等等)时例外。 要修改元素的 CSS 样式,可以存取 style 物件。 oneElement.style.paddingTop = '2rem' 要取得元素的 CSS 值,可以像上面一样透过 style 物件, 也可以透过 window.getComputedStyle() 取得实际的值。 window.getComputedStyle(oneElement).getPropertyValue('padding-top') 【三、修改 DOM】 // 在 element1 里插入一个 element2 element1.appendChild(element2) // 在 element1 里的 element3 之前插入一个 element2 element1.insertBefore(element2, element3) 世界上有 insertBefore() 却没有 insertAfter(),所以必须绕个圈。 // 在 element1 里的 element3 「之後」插入一个 element2 element1.insertBefore(element2, element3.nextSibling) // 不能写成: // element1.insertAfter(element2, element3) // 复制 DOM const newElement = oneElement.cloneNode() element1.appendChild(newElement) // 建立新的 DOM const newElement = document.createElement('div') const newTextNode = document.createTextNode('hello world') // 移除 DOM,需要参照到亲元素 parentElement.removeChild(element1) // 自己移除自己 element1.parentNode.removeChild(element1) 要修改元素的内容,传统的做法可以用 innerHTML: oneElement.innerHTML = '<div> <h1>hello world</h1> </div>' 更好的做法是使用 DocumentFragment: const text = document.createTextNode('continue reading...') const hr = document.createElement('hr') const fragment = document.createDocumentFragment() fragment.appendChild(text) fragment.appendChild(hr) oneElement.appendChild(fragment) 【四、监听事件】 JavaScript 最重要的就是监听(listen)各种事件来触发程式码。 我们使用 addEventListener 来监听事件处理。 oneElement.addEventListener('click', function (event) { // do something... }) 同时监听许多元素时,透过 event.target 来取得是哪个元素触发的。 Array.from(allElements).forEach(element => { element.addEventListener('change', function (event) { console.log(event.target.value) }) }) 只想让事件触发一次(jQuery 的 once): oneElement.addEventListener('change', function listener(event) { console.log(event.type + ' got triggered on ' + this) this.removeEventListener('change', listener) }) 【五、动画】 以前习惯用 window.setTimeout() 来做动画, 现在我们有更好更快的 window.requestAnimationFrame() 了。 const start = window.performance.now() const duration = 2000 window.requestAnimationFrame(function fadeIn (now) { const progress = now - start oneElement.style.opacity = progress / duration if (progress < duration) { window.requestAnimationFrame(fadeIn) } } 【六、包装】 最後我们可以把这些方式全部包在一个 function 里。 就像 jQuery 一样,还可以链式呼叫(chainable) (例如: $('foo').css({color: 'red'}).on('click', () => {}) const $ = function $(selector, context = document) { const elements = Array.from(context.querySelectorAll(selector)) return { elements, html (newHtml) { this.elements.forEach(element => { element.innerHTML = newHtml }) return this }, css (newCss) { this.elements.forEach(element => { Object.assign(element.style, newCss) }) return this }, on (event, handler, options) { this.elements.forEach(element => { element.addEventListener(event, handler, options) }) return this } // etc. } } 或者用 ES6 的 Class 来包装: class DOM { constructor(selector) { const elements = document.querySelectorAll(selector) this.length = elements.length Object.assign(this, elements) } each(callback) { for (let el of Array.from(this)) { callback.call(el) } return this } addClass(className) { return this.each(function () { this.classList.add(className) }) } removeClass(className) { return this.each(function () { this.classList.remove(className) }) } hasClass(className) { return this[0].classList.contains(className) } on(event, callback) { return this.each(function () { this.addEventListener(event, callback, false) }) } // etc. } --



※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 36.224.11.65
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/Ajax/M.1491563311.A.1F2.html ※ 编辑: jmlntw (36.224.11.65), 04/07/2017 19:14:00 jmlntw:转录至看板 Web_Design 04/07 19:15 ※ 编辑: jmlntw (36.224.11.65), 04/07/2017 19:30:14
1F:推 xdraculax: 尸口巾 04/07 19:31
2F:推 hijkxyzuw: 上色好认真… 04/07 23:40
3F:→ hijkxyzuw: 还有你最後都包成 $ 了,那直接引用 jQuery 不就好了? 04/07 23:41
4F:→ hijkxyzuw: 还帮你处理了兼容问题 04/07 23:41
5F:推 Kenqr: 因为要多载入一个library 相容性问题现在也越来越少了 04/08 00:43
6F:→ Kenqr: http://youmightnotneedjquery.com/ 04/08 00:43
8F:推 a42006310: 用心推 超赞 04/08 11:57
9F:推 Sunal: 推 但是客户死不转换至IE11..继续用$$$$$ 04/08 12:49
10F:推 hoyunxian: 看来也得等所有旧的浏览器都被淘汰了才能直接用...... 04/08 13:35
11F:推 ian90911: 推 04/08 13:50
12F:→ jmlntw: 在不用 ES6 的情况下,现在官方主流支援中的浏览器几乎都 04/08 14:37
13F:→ jmlntw: 能使用。如果是特定环境(例如浏览器扩充功能或 Electron 04/08 14:37
14F:→ jmlntw: 等)那就更不是问题了。 04/08 14:37
15F:→ jmlntw: 当然和用 jQuery 比起来像是在重复造轮子,不过当作熟悉原 04/08 14:44
16F:→ jmlntw: 生 JS 的学习也不是不行。 04/08 14:44
17F:推 jiaming: 推一个~太用心了 04/08 14:45
18F:推 kurtisgod: 好文推!!!! 04/08 15:34
19F:推 lucky1lk: 好文推 原生的相当重要 04/09 11:02
20F:推 shadowjohn: 客户还在ie8,连es6都并进来用了 04/09 12:08
21F:→ shadowjohn: 已眼神死,不在乎在几十k的js... 04/09 12:08
22F:推 KNightING: 推用心 04/09 23:59
23F:推 tamsky: 推用心, 请问有网页版吗 04/10 10:00
24F:推 Neisseria: 想到 IE,还是回头乖乖用 jQuery (烟) 04/10 11:39
25F:→ Neisseria: 不过大大写得不错,建议可以弄个网页,造福人群 04/10 11:40
26F:→ jmlntw: PTT 有网页版啊。 04/10 22:07
27F:推 kiki1503: 推 04/14 00:21
28F:推 a0960330: 推~VanillaJS 04/16 22:52
29F:推 tonylioa: 推用心 05/04 08:02
30F:推 baronmax: 推 12/05 12:05







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:Tech_Job站内搜寻

TOP