js dom参数(【JavaScript】JS实用案例分享:DOM节点转JSON数据 | 标签输入框)
🖥️ NodeJS专栏:Node.js从入门到精通
🖥️ 博主的前端之路(源创征文一等奖作品):前端之行 ,任重道远(来自大三学长的万字自述)
🖥️ TypeScript知识总结:TypeScript从入门到精通(十万字超详细知识点总结)
🧑💼个人简介:大三学生 ,一个不甘平庸的平凡人🍬
👉 你的一键三连是我更新的最大动力❤️!
🏆分享博主自用牛客网🏆:一个非常全面的面试刷题求职网站 ,点击跳转🍬前言
最近博主一直在牛客网刷题巩固基础知识 ,牛客网不仅具有公司真题 、专项练习 、面试题库 、在线编程等功能 ,还具有非常强大的AI模拟面试功能 ,简直是求职者的福音!
牛客网里的题库非常全面的 ,无论你是前端还是后端 ,是想要备考还是准备面试又或者是想要提高自己 ,你都能在牛客网上找到适合自己的题,赶快点击链接去注册登录吧:点我进入牛客网
牛客网 牛客网本篇文章所有示例来自于牛客网题库/在线编程/JS篇 ,这些都是前端开发中常用的功能 ,借此记录一下刷题过程,巩固基础!
1 、DOM节点转JSON数据
效果演示
有以下HTML和CSS:
HTML结构
<div id="jsContainer"> <ul class="js-test" id="jsParent"> <li data-index="0">1</li> <li data-index="1">2</li> </ul> <span style="font-weight: bold;">3</span> 4 </div>案例需求
页面上存在id=jsContainer的节点A ,按照如下需求实现 dom2json 函数
dom2json需要分析整个节点A的dom结构 ,并将其结构转换为对应的json对象 。 需要获取dom结构的标签名称(tag),所有属性(attributes) ,子节点(children) 。 文档片段中的属性形式均为 name="value" ,解析之后的格式为{name: value}, 属性值为String类型 ,不需要做解析。 随机生成的文档片段中 ,只包含 nodeType 为1(element)和3(text)的节点 ,不需要考虑其他节点类型 。 纯文本也视为一个节点, json格式为 {tag: text, content: 文本内容} ,content为文本内容执行trim后的结果 ,如果该结果为空 ,则忽略当前节点 。 返回结果中的标签名称不区分大小写 。 如果节点不包含属性值或者子节点 ,其对应的结果中需要保留attributes以及children字段,例如 {tag: div, attributes: {}, children: []} 。 上面的HTML结构执行dom2json之后的结果如上面的效果演示 。JavaScript实现
function dom2json() { const root = document.getElementById(jsContainer) return JSON.stringify(getDomJson(root)) } function getDomJson(dom) { let domObj; if (dom.nodeType === 1) { // 如果是element节点 domObj = { tag: dom.localName, attributes: {}, children: [] } // 属性列表 let attlist = dom.attributes; for (let i = 0, l = attlist.length; i < l; i++) { // .name获取属性名 ,.value获取属性值 domObj.attributes[attlist[i].name] = attlist[i].value } // 子元素列表 let childList = dom.childNodes for (let i = 0, l = childList.length; i < l; i++) { // 递归 const childJson = getDomJson(childList[i]) if (childJson) { domObj.children.push(childJson) } } } else if (dom.nodeType === 3) { // 如果是text节点 const ctn = dom.textContent.trim() if (ctn) { domObj = { tag: text, content: ctn } } } return domObj } console.log(测试, dom2json());这个案例中主要就是对DOM操作以及递归算法的应用 。
知识点:
Node.nodeType 表示的是该节点的类型 。
Element.localName 、Node.nodeName 、Element.tagName都能获取节点的标签名 。
元素节点有tagName 、nodeName 、localName属性;其中tagName 、nodeName相同 ,都是大写,localName是小写 。 其他节点只有nodeName 、localName属性 ,无tagName属性 ,其中: 属性节点localName和nodeName相同。 文本节点localName为null,nodeName为#text(带有#) 。从DOM层次来看 ,nodeName是node接口上的property ,而tagName是element接口上的property ,所有的节点(元素节点 ,属性节点 ,文本节点等12种)都继承了node接口 ,而只有元素节点才继承了element节点 ,因此nodeName比tagName具有更大的使用范围 。
Element.attributes 属性返回该元素所有属性节点的一个实时集合。
Node.childNodes 返回包含指定节点的子节点的集合 ,该集合为即时更新的集合 。
Node.textContent 属性表示一个节点及其后代的文本内容 。
trim() 方法会从一个字符串的两端删除空白字符。
2 、标签输入框
效果演示
有以下HTML和CSS:
HTML结构
<div class="tag-input"> <span class="tag">前端</span> <span class="tag">编程题</span> <span class="tag">示例</span> <span class="tag">标签</span> <input type="text" class="js-input" maxlength="6" placeholder="请输入标签"> </div>CSS样式
.tag-input{ position: relative; border: 1px solid #cccccc; padding: 0 5px; display: flex; flex-flow: row wrap; } .js-input{ width: 450px; height: 22px; line-height: 22px; font-size: 16px; padding: 0; margin: 5px 0; outline: none; border: none; width: 6.5em; height: 24px; line-height: 24px; } .tag{ padding: 0 10px; margin: 5px 5px 5px 0; background: #25bb9b; color: #ffffff; height: 24px; line-height: 24px; border-radius: 12px; font-size: 13px; }案例需求
上面展示了一个简化版的标签输入框 ,功能如下:
当用户输入内容并敲回车键时,将输入框的内容在输入框前显示成标签 ,并清空输入框内容 。 当用户敲删除键时 ,如果输入框当前没有内容,则删除前一个标签 。 标签需要去掉字符串两端的多余的空格 。 标签不能为空字符串 。 标签不能重复 ,如果输入已存在的内容相同的标签 ,则不添加,并清空输入框 。 相关键码值 ,回车键=13 ,删除键=8 。JavaScript实现
var tagInput = { // isInited表示是否已初始化 isInited: false, // 初始化方法 init: init, // 绑定事件处理函数的方法 bindEvent: bindEvent, // 添加标签的方法 addTag: addTag, // 移除标签的方法 removeTag: removeTag }; // 初始化 tagInput.init(); // 初始化函数 function init() { var that = this; if (that.isInited) return; that.isInited = true; // 保存class为js-input的输入框的dom元素引用 that.input = document.getElementsByClassName("js-input")[0]; that.bindEvent(); } // 注册事件 function bindEvent() { var that = this; var input = that.input; if (!input) return; // 给input绑定按键按下事件 input.addEventListener(keydown, function (event) { // 判断用户是否按了回车键 var isEnter = (event.keyCode === 13); // 判断用户是否按了删除键 var isDelete = (event.keyCode === 8); // 阻止默认行为 (isEnter || isDelete) && event.preventDefault(); isEnter && that.addTag(); isDelete && that.removeTag(); }); // 给input的父元素绑定点击事件 input.parentNode.addEventListener(click, function () { // 使用input获得焦点 input.focus(); }); } // 添加标签的函数 function addTag() { var that = this, input = that.input, val = input.value.trim(), tagList = document.getElementsByClassName(tag), isAdd = true; // 遍历存在的tag ,输入的内容在tag中已经存在时不进行添加span元素操作(isAdd=false) for (var i = 0, l = tagList.length; i < l; i++) { if (tagList[i].innerHTML === val) { isAdd = false break } } // 如果val不为空 ,isAdd为true则添加新的span元素 if (isAdd && val) { var newSpan = document.createElement(span) newSpan.className = tag newSpan.innerHTML = val // 在input的父节点中的input节点之前插入newSpan节点 input.parentNode.insertBefore(newSpan, input) } input.value = } // 删除标签的函数 function removeTag() { var that = this, input = that.input, val = input.value, tagList = document.getElementsByClassName(tag); if (val) { // 如果val不为空时 ,应该删除值的最后一位 input.value = val.slice(0, -1) } else if (tagList.length > 0) { // 如果val为空时 ,tagList中存在span标签 ,则删除最后一个标签 tagList[tagList.length - 1].remove() } }这个案例的实现并不难 ,主要就是在于它的逻辑思想 ,只要动脑去想,动手去写 ,一般都能实现它 。
知识点:
Node.insertBefore() 方法在参考节点之前插入一个拥有指定父节点的子节点 。 slice(begin, end) 提取某个字符串的一部分 ,并返回一个新的字符串,且不会改动原字符串 。从下标begin提取到end(包含begin ,不包含end) ,如果end<0,表示从末尾开始算 ,例如end是 -3 ,则end相当于是strLength - 3(strLength 表示字符串长度)结语
这篇文章的所有内容都出自于牛客网的JS篇题库:
牛客网的JS题库非常贴合实际的 ,在写的过程中自己查漏补缺 ,收获了很多 ,强烈将牛客网推荐给大家!
如果本篇文章对你有所帮助 ,还请客官一件四连!❤️
基础不牢 ,地动山摇! 快来和博主一起来牛客网刷题巩固基础知识吧!
创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!