浏览器和DOM编程

139 阅读3分钟

浏览器

  • window
    window对象不但充当全局作用域,而且还表示为浏览器窗口。
    window对象有 innerWidthinnerHeight属性,能够获取浏览器窗口的内部宽度和高度。

  • navigator
    navigator表示浏览器的信息,常用属性:

    navigator.appName;//浏览器名称 navigator.appVersion;//浏览器版本 nabigator.language;//浏览器设置语言 navigator.platform;//操作系统类型

  • screen
    screen对象标识屏幕的信息,常用属性有:
    screen.width:屏幕宽度,以像素为单位
    screen.height:屏幕高度
    screen.colorDepth:返回颜色位数

  • location
    location对象标识当前页面的URL信息。
    可以通过location.href获取一个完整的URL信息:[https://cn.bing.com/?mkt=zh-CN](https://cn.bing.com/?mkt=zh-CN)

    location.protocol;//https: location.host;//"cn.bing.com" location.port;//"" location.pathname;//"/" location.search;//"?mkt=zh-CN" location.hash;//""

可以用location.assign()来加载一个新的页面;用location.reload()来重新加载页面。

  • document
    document对象表示当前页面,由于HTML在浏览器中以DOM形式表示为树形结构, document对象就是整个DOM树的根节点。
    documenttitle属性就是从HTML文档中的<title>xxx<title>读取的,但是是可以动态改变。
    document对象还有一个 cookie属性,可以通过document.cookie;获取当前页面的Cookie,由于JavaScript可以读取页面的Cookie,并且由于用户的登录信息通常也存在Cookie中,这就造成了很大的安全隐患,为解决这个问题,服务器在设置Cookie时可以使用 httpOnly,设定了httpOnly的Cookie不能被JavaScript读取
  • history
    history对象保存了浏览器的历史记录,可以调用 back()forward()方法,相当于点击浏览器的后退或者前进按钮。history这个对象没什么用了,不要用。

操作DOM

HTML文档被解析后就是一颗DOM树,要改变HTML结构,需要通过JavaScript来操作DOM,操作一个DOM节点实际上就一下几个操作:

  • 更新:更新DOM节点的内容

  • 遍历:遍历该DOM节点下的子节点,一遍进行进一步操作

  • 添加:在DOM节点下新增一个子节点,相当于动态增加了一个HTML节点;

  • 删除:将该节点从HTML中删除,相当于删除了该DOM节点的内容以及它包含的所有的子节点
    在操作一个DOM节点之前,首先要获取到这个DOM节点,最常用的方法是document.getElementById()document.getElementsByTagName(),以及CSS选择器document.getElementsByClassName().由于ID是唯一的,可以直接定位唯一的DOM节点。

    //返回ID为test的节点 let test = document.getElementById('test'); //定位ID为‘table_test'的节点,再返回其内部所有的tr节点 let trs = document.getElementById('table_test').getElementsByTagName('tr'); //先定位ID为'test-div'的节点,再返回其内部所有class包含red的节点: let reds = document.getElementById(test-div).getElementsByClassName('red'); //获取test下的所有直属节点: let tests = test.childre; //获取test下第一个和最后一个节点 let first = test.firstElementChild; let last = test.lastElementChild;

另外一种方法是使用querySelector()querySlectorAll();

let q1 = document.querySelector('#q1');

实际当中一般都用​​querySelector​和​​querySelectorAll()

直接使用​window.idxxx​和​​idxxxx​可以直接获取

nodeType

nodeType属性可以用来区分不同类型的节点,比如元素,文本和注释等等

var type = node.nodeType;

返回一个整数,代表节点类型

  • Node.ELEMENT_NODE 1 一个元素节点,如

    ,

  • Node.TEXT_NODE 3 Element 或者 Attr 中实际的 文字
  • Node.COMMENT_NODE 8 一个 Comment 节点
  • Node.DOCUMENT_NODE 11 一个DOcument节点

更新DOM

  • 第一种方法是直接修改 innerHTML属性,这个方式非常强大,不仅可以修改一个DOM节点的文本内容还可以直接通过HTML片段修改DOM节点内部的子树。

    //获取

    ...

    let p = document.getElementById('p_id'); //将p的文本设置为 'abcde' p.innerHTML = 'abcde'; //设置HTML p.innerHTML = 'ABCREDXYZ'; //p的内部结构已经被修改

注意,在使用 innerHTML 的时候是否需要写入HTML,如果写入的字符是通过网络拿到的,注意对字符编码来避免XSS攻击。

  • 第二种方法是修改innerTexttextContent属性,这样可以自动对字符串进行HTML编码,保证无法设置任何HTML标签。

    //获取

    ...

    let p = document.getElementById('p_id'); //设置文本 p.innerText = ''; //HTML被自动编码,无法设置一个

两者的区别在于读取属性时,innerTEXT不返回隐藏元素的文本,而textContent返回所有文本

修改CSS也是经常需要的操作,DOM节点的style属性对应所有的CSS,可以直接获取或设置

let p = document.getElementById('p1');
p.style.color = 'blue';
p.style.fontSize = '20px';
p.style.paddingTop = '2em';

插入DOM

如果这个DOM节点是空的,例如<div></div>,直接使用innerHTML = '<span>child</span>就可以修改DOM节点的内用,相当于插入了一个新的DOM节点。

如果这个DOM节点不为空就不能这么做,因为 innerHTML会直接覆盖原有的所有子节点。有两个方法可以插入新的子节点。

  • 使用appendChild把一个子节点添加到父节点的最后一个子节点。

    JavaScript

    Java

    Python

    Scheme

    JavaScript

    添加到
    的最后一项: let js = document.getElementById('js') list = document.getElementById('list'); list.appendChild(js);

更多情况下我们会创建一个新的节点,然后插入到指定位置

let list = document.getElementById('list')
        haskell = document.createElement('p');
haskell.id = 'haskell';
haskell.innerText = 'HasKell';
list.appendChild(haskell);

这样我们就动态创建一个新的节点,动态创建一个节点然后添加到DOM树中,可以实现很多功能。

下面的代码动态创建了一个<style>节点,然后把它添加到节点末尾,这样就动态给文档添加了新的CSS样式

let d = documeng.creatElement('style');
d.setAttribute('type','text/css');
d.innerHTML = 'p{color:red}';
document.getElementByTagName('head'[0].appednChild(d));
  • 第二种方法使用insertBefore使用parentElement.insertBefore(newElement,referenceElement);,子节点就会插入到referenceElement之前。

例把Haskell插入到Python之前

<!-- HTML结构 -->
<div id="list">
    <p id="java">Java</p>
    <p id="python">Python</p>
    <p id="scheme">Scheme</p>
</div>
----------------------------------------
let list = document.getElementById('list')
        ref = document.getElementById('python')
        haskell = document.createElement('p');
haskell.id = 'haskell';
haskell.innerText = 'HasKell';
list.insertBefore(haskell,ref);

使用insertBefore的重点是拿到自己点,很多时候我们都需要循环一个父节点所有的子节点,可通过迭代children来实现:

let i,c,
    list = document.getElementById('list');
for (i = 0; i<list.chidren.length,i++) {
  c = list.childre[i];
}

总结:

创建一个标签节点:

  • let div = document.createElement('div')
  • document.createElement('style')

创建一个文本节点:

  • text = document.createTextNode('你好')

标签里面插入文本

  • div.appendChild(text)
  • div.innerText = '你好' ​或者 ​div.textContent = '你好'
  • 不能用​div.appendChild('你好')

删除DOM

要删除一个DOM首先要获得该节点本身以及它的父节点,然后调用父节点的removeChild删除。//​​childNode.remove()

//获取待删除的节点
let self = docuemnt.getElementById('removed');
//获取父节点
let parent=self.parentElement;
//删除
parent.removeChild(self);
//

删除后的节点虽然不在文档树当中了,但其实它还在内存中,可以随时再次被添加到其他位置。此外需要注意children属性在删除多个节点时会产生变化。

总结:

写标准属性:

  • 改class: div.className = 'red blue'
  • 改class:div.classList.add('red')
  • style:div.style = 'width:100px;color:blue;'
  • 改style的一部分:div.style.width = '200px';
  • 改data-*属性:div.dataset.x = 'Nick';

读标准属性

  • div.classList/a.href
  • div.getAttribute('class')/a.getAttribute('href')

改内容

  • 改文本内容:​​div.innerText = 'xxx'///div.textContext = 'xxx';
  • ​改HTML内容:​​div.innerHTML = '<strong>hihihi<strong>';
  • 改 标签:​​div.innerHTML = ''//先清空

div.appendChild(div1)//再添加内容

遍历一个div里面的所有元素

travel = (node,fn) => {
  fn(node)
  if(node.childre){
    for(let i=0; i<node.children.lenth;i++) {
      travel(node.children[i],fn)
    }
  }
}
travel(div1,(node) => console.log(node))

操作表单

表单操作和DOM操作类似,因为表单本身也是DOM树,不过表单的输入框、下拉框可以直接接受用户输入,所以通过JavaScript操作表单,可以获取用户输入的内容跟,或者对一个输入框设置新的内容。

HTML表单的输入控件有一下几种:

  • 文本框:<input type="text">
  • 密码框:<input type="password">
  • 单选框:<input type="radio">
  • 复选框:<input type="checkbox">
  • 下拉框:<select>
  • 隐藏文本:<input type="hidden">

获取值

如果获得一个<input>节点的引用,就可以直接调用value获得对应的用户输入值

//<input type="text" id="email">
let input = document.getElementById('email');
input.value;

设置值

// <input type="text" id="email">
var input = document.getElementById('email');
input.value = 'test@example.com'; // 文本框的内容已更新

*HTML5控件*

HTML5新增大量标准控件,常用的有date,datetime,datetime-local,color等等,他们都是用input标签

<input type="date" value="2020-01-01">

提交表单

一种方式是通过<form>元素的submit()方法提交表单,例如响应一个<button><click>事件

//HTML页面
<form id='test-from'>
  <input type='text' name='test'>
    <button type='button' onclick='doSubmitForm()>Submit</button>
</form>

<script>
      function doSubmitForm() {
      let form = document.getElementById('test-form');
      form.submit();
    }
</script>