JavaScript -- 10. 一文了解DOM对象及常用方法

news2024/11/16 22:20:20

文章目录

  • 1. DOM介绍
    • 1.1 什么是DOM
    • 1.2 概念
    • 1.3 关系
    • 1.4 HelloWorld
    • 1.5 document对象
  • 2. DOM节点
    • 2.1 元素节点
      • 2.1.1 获取已有的元素节点
        • 2.1.1 `document.getElementById()`
        • 2.1.2 `document.getElementsByClassName()`
        • 2.1.3 `document.getElementsByTagName()`
        • 2.1.4 `document.getElementsByTagName()`
        • 2.1.5 `document.getElementsByName()`
        • 2.1.6 `document.querySelectorAll()`
        • 2.1.7 `document.querySelector()`
        • 2.1.8 `document.createElement()`
      • 2.1.2 通过某个元素获取其他节点
    • 2.2 文本节点
    • 2.3 属性节点(Attr)
    • 2.4 事件
      • 2.4.1 直接在元素属性中设置
      • 2.4.2 设置回调函数
      • 2.4.3 元素.addActionListener()
    • 2.5 文档的加载
    • 2.6 练习
      • 2.6.1 切换图片
      • 2.6.2 实现按钮之间相互配合
  • 3. DOM的修改
    • 3.1 添加节点
    • 3.2 删除节点
    • 3.3 练习
    • 3.4 复制节点
    • 3.5 修改CSS样式
    • 3.6 读取CSS样式
      • 3.6.1 getComputedStyle()
      • 3.6.2 通过属性读取样式
    • 3.7 修改class
  • 4. 事件
    • 4.1 事件对象简介
    • 4.2 Event对象
    • 4.3 冒泡
    • 4.4 事件的委派
    • 4.5 事件的捕获
  • 5. 其他
    • 5.1 定时器
      • 5.1.1 单次定时器
      • 5.1.2 多次定时器
      • 5.1.3 原理
    • 5.2 事件循环
    • 5.3 消息队列

1. DOM介绍

DOM – 李立超 | lilichao.com

前面在学习JS的时候发现,似乎JS和网页并没有太大的关系。换句话说,我们所编写的JS代码,除了是写在网页中以外,并没有和网页产生任何实质的联系。

而DOM就是一种使用JS来操作网页的技术

1.1 什么是DOM

DOM,全称Document Object Model,中文翻译为文档对象模型。

DOM属于Web API的一部分。Web API中定义了非常多的对象,通过这些对象可以完成对网页的各种操作(添加删除元素、发送请求、操作浏览器等)

  • DOM中的D意为Document,即文档。所谓文档就是指整个网页,换言之,DOM是用来操作网页的。
  • O意为Object,即对象。DOM将网页中的每一部分内容都转换为了对象。
  • M意为Model,即模型。模型用来表示对象之间的关系,也就是父子元素、祖先后代、兄弟元素等,明确关系后我们便可以通过任意一个对象去获取其他的对象。
<!DOCTYPE html>
<html lang="zh">
<head>
    <title>My Title</title>
</head>
<body>
    <h1>A Heading</h1>
    <a href="#">Link Text</a>
</body>
</html>

对于上面的代码,我们可以得到如下DOM树

img

1.2 概念

在DOM标准下,网页中的每一个部分都会转换为对象。这些对象有一个共同的称呼——节点(Node)。

一个页面将会由多个节点构成,虽然都称为节点,但是它们却有着不同的类型:

  1. 文档节点
  2. 元素节点
  3. 文本节点
  4. 属性节点

每一个节点都有其不同的作用,文档节点表示整个网页,元素节点表示某个标签,文本节点表示网页中的文本内容,属性节点表示标签中的各种属性。如果从对象的结构上来讲,这些对象都有一个共同的父类Node。总的来说,都是属于节点,但是具体类型不同。

1.3 关系

  • 祖先 —— 包含后代元素的元素是祖先元素
  • 后代 —— 被祖先元素包含的元素是后代元素
  • 父 —— 直接包含子元素的元素是父元素
  • 子 —— 直接被父元素包含的元素是子元素
  • 兄弟 —— 拥有相同父元素的元素是兄弟元素

1.4 HelloWorld

要使用DOM来操作网页,我们需要浏览器至少得先给我一个对象,才能去完成各种操作

所以浏览器已经为我们提供了一个document对象,它是一个全局变量可以直接使用document代表的是整个的网页

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<button id="btn">点我</button>
<script>
    // 通过 id 获取按钮对象
    const btn = document.getElementById("btn")
    console.log(btn) // 打印按钮对象
    console.dir(btn) // 打印该按钮的所有属性
    btn.innerText = "Hello World" // 修改按钮文字
</script>
</body>
</html>

1.5 document对象

  • document对象表示的是整个网页
  • document对象的原型链:HTMLDocument -> Document -> Node -> EventTarget -> Object.prototype -> null
  • 凡是在原型链上存在的对象的属性和方法都可以通过Document去调用
  • 部分属性:
    • document.documentElement --> html根元素
    • document.head --> head元素
    • document.title --> title元素
    • document.body --> body元素
    • document.links --> 获取页面中所有的超链接

2. DOM节点

2.1 元素节点

  • 元素节点对象(element)
  • 在网页中,每一个标签都是一个元素节点
  • 如何获取元素节点对象?
    • 通过document对象来获取元素节点
    • 通过document对象来创建元素节点

2.1.1 获取已有的元素节点

const btn = document.getElementById("btn")

const spans = document.getElementsByClassName("s1")

const divs = document.getElementsByTagName("div")

const genderInput = document.getElementsByName("gender")

const divs2 = document.querySelectorAll("div")

const div = document.querySelector("div")

const h2 = document.createElement("h2")

console.log(spans)
for(let i=0; i<spans.length; i++){
    alert(spans[i])
    spans[i].innerText = "哈哈哈"+i
}

2.1.1 document.getElementById()

根据id获取一个元素节点对象

2.1.2 document.getElementsByClassName()

  • 根据元素的class属性值获取一组元素节点对象
  • 返回的是一个类数组对象
  • 该方法返回的结果是一个实时更新的集合
  • 当网页中新添加元素时,集合也会实时的刷新

2.1.3 document.getElementsByTagName()

  • 根据标签名获取一组元素节点对象
  • 返回的结果是可以实时更新的集合

2.1.4 document.getElementsByTagName()

获取页面中所有的元素

2.1.5 document.getElementsByName()

  • 根据name属性获取一组元素节点对象
  • 返回一个实时更新的集合
  • 主要用于表单项

2.1.6 document.querySelectorAll()

  • 根据选择器去页面中查询元素
  • 会返回一个类数组(不会实时更新)

2.1.7 document.querySelector()

根据选择器去页面中查询第一个符合条件的元素

2.1.8 document.createElement()

创建一个元素节点

根据标签名创建一个元素节点对象

2.1.2 通过某个元素获取其他节点

div元素的原型链

image-20221206183833372

image-20221206183512969

通过元素节点对象获取其他节点的方法

  • element.childNodes:获取当前元素的子节点(会包含空白的子节点
  • element.children:获取当前元素的子元素,不包含文本节点,使用更多一些
  • element.firstElementChild:获取当前元素的第一个子元素
  • element.lastElementChild:获取当前元素的最后一个子元素
  • element.nextElementSibling:获取当前元素的下一个兄弟元素
  • element.previousElementSibling:获取当前元素的前一个兄弟元素
  • element.parentNode:获取当前元素的父节点
  • element.tagName:获取当前元素的标签名

2.2 文本节点

在DOM中,网页中所有的文本内容都是文本节点对象,可以通过元素来获取其中的文本节点对象,但是我们通常不会这么做

我们可以直接通过元素去修改其中的文本,修改文本的三个属性

  • element.textContent
    • 获取或修改元素中的文本内容
    • 获取的是标签中的内容,不会考虑css样式,所有的原始文本,包括换行和空格
  • element.innerText
    • 获取或修改元素中的文本内容
    • innerText获取内容时,会考虑css样式
      • 例如设置为display: none通过innerText就获取不到文本,通过textContent就可以获取到文本
    • 通过innerText去读取CSS样式,会触发网页的重排(计算CSS样式)
    • 当字符串中有标签时,会自动对标签进行转义:<li> --> &lt;li&gt;,所以在网页上还是会原样显示出来添加的文本
  • element.innerHTML
    • 获取或修改元素中的html代码
    • 可以直接向元素中添加html代码
    • innerHTML插入内容时,有被xss注入的风险

2.3 属性节点(Attr)

  • 在DOM也是一个对象,通常不需要获取对象而是直接通过元素即可完成对其的各种操作
  • 如何操作属性节点:
    • 方式一:

      • 读取:元素.属性名(注意,class属性需要使用className来读取),读取一个布尔值时,会返回true或false
      • 修改:元素.属性名 = 属性值
    • 方式二:

      • 读取:元素.getAttribute(属性名)
      • 修改:元素.setAttribute(属性名, 属性值)
      • 删除:元素.removeAttribute(属性名)
<!DOCTYPE html>
<html lang="zh">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
    </head>
    <body>
        <input class="a" type="text" name="username" value="admin">

        <script>
            const input = document.getElementsByName("username")[0]
            // const input = document.querySelector("[name=username]")
            console.log(input.getAttribute("type"))
            input.setAttribute("value", "孙悟空")
            input.setAttribute("disabled", "disabled")
        </script>
    </body>
</html>

2.4 事件

事件(event)

  • 事件就是用户和页面之间发生的交互行为

    • 比如:点击按钮、鼠标移动、双击按钮、敲击键盘、松开按键…
  • 可以通过为事件绑定响应函数(回调函数),来完成和用户之间的交互

  • 绑定响应函数的方式:

    1. 可以直接在元素的属性中设置

    2. 可以通过为元素的指定属性设置回调函数的形式来绑定事件(一个事件只能绑定一个响应函数)

    3. 可以通过元素addEventListener()方法来绑定事件

2.4.1 直接在元素属性中设置

<button onclick="alert(123)"></button>
<button onclick="btnClick()"></button>

<script>
    function btnClick(){
        console.log("button click")
    }
</script>

2.4.2 设置回调函数

<button id="btn"></button>

<script>
    const btn = document.getElementById("btn")
    // 为按钮对象的事件属性设置响应函数
    btn.onclick = function(){
        console.log("123")
    }
    
    // 一个时间只能绑定一个函数,不能重复绑定,后续会覆盖掉前面的函数
    btn.onclick = function(){
        console.log("1123111")
    }
</script>

2.4.3 元素.addActionListener()

<button id="btn"></button>

<script>
    const btn = document.getElementById("btn")
    // 为按钮对象的事件属性设置响应函数
    btn.addEventListener("click", function () {
        console.log("哈哈哈")
    })
    
    // 可以同时绑定多个函数,先绑定谁就先执行谁
    btn.addEventListener("click", function () {
        console.log("嘻嘻嘻")
    })

    btn.addEventListener("click", function () {
        console.log("呜呜呜")
    })
</script>

2.5 文档的加载

网页是自上向下加载的,如果将js代码编写到网页的上边,js代码在执行时,网页还没有加载完毕,这时会出现无法获取到DOM对象的情况

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script>
        const btn = document.querySelector("#btn")
        console.log(btn)
    </script>
</head>
<body>
<button id="btn">按钮</button>
</body>
</html>

上述代码在打印的时候就会打印出来null,表示无法获取到button元素

如果将script移动到button之后,就可以正常打印出结果

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
	<button id="btn">按钮</button>
    <script>
        const btn = document.querySelector("#btn")
        console.log(btn)
    </script>
</body>
</html>

为了保证在任意位置写的代码均生效我们可以使用下面两个函数

  • window.onload 事件会在窗口中的内容加载完毕之后才触发
  • document的DOMContentLoaded事件会在当前文档加载完毕之后触发

例如引入iframe之后,window.onload会在iframe全部加载完成之后才会执行,document会在当前文档加载完成之后执行,而不会等待另一个iframe加载完成之后才执行

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script>
        window.onload = () => {
            const btn = document.querySelector("#btn")
            console.log(btn)
        }
    </script>
</head>
<body>
<button id="btn">按钮</button>
</body>
</html>

如何解决这个问题:

  1. 将script标签编写到body的最后

  2. 将代码编写到window.onload的回调函数中

  3. 将代码编写到document对象的DOMContentLoaded的回调函数中(执行时机更早)

  4. 将代码编写到外部的js文件中,然后以defer的形式进行引入(执行时机更早,早于DOMContentLoaded)

    <script defer src="./script.js"></script>
    

2.6 练习

2.6.1 切换图片

实现点击切换图片,并实现循环切换

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<img id="image" width="400" height="400"/>
<div id="info"></div>
<div>
    <button id="pre">上一张</button>

    <button id="next">下一张</button>
</div>
<script>
    let imageIdx = 0
    imageName = [
        "./images/1.png",
        "./images/2.png",
        "./images/3.png",
        "./images/4.png",
        "./images/5.png",
    ]
    const img = document.querySelector("#image")
    img.src = imageName[0]

    const infoDiv = document.querySelector("#info")
    infoDiv.innerText = `${imageName.length}张图片,当前第${imageIdx + 1}`

    const preBtn = document.querySelector("#pre")
    const nextBtn = document.querySelector("#next")

    preBtn.addEventListener("click", () => {
        imageIdx = (imageIdx - 1 + imageName.length) % imageName.length
        img.src = imageName[imageIdx]
        infoDiv.innerText = `${imageName.length}张图片,当前第${imageIdx + 1}`
    })

    nextBtn.addEventListener("click", () => {
        imageIdx = (imageIdx + 1) % imageName.length
        img.src = imageName[imageIdx]
        infoDiv.innerText = `${imageName.length}张图片,当前第${imageIdx + 1}`
    })
</script>
</body>
</html>

2.6.2 实现按钮之间相互配合

image-20221206210905757

  • 全选:选中所有按钮
  • 取消:取消选中所有按钮
  • 反选:选中则取消,取消则选中
  • 提交:显示出所有爱好
  • 如果下面所有标签都选中了则全选也需要被选中;如果有一个没有被选中,则全选不能被选中
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div>
    <form action="#">
        <div>
            请选择你的爱好:
            <input type="checkbox" id="check-all"/> 全选
        </div>
        <div>
            <input type="checkbox" name="hobby" value="乒乓球"/> 乒乓球
            <input type="checkbox" name="hobby" value="篮球"/> 篮球
            <input type="checkbox" name="hobby" value="羽毛球"/> 羽毛球
            <input type="checkbox" name="hobby" value="足球"/> 足球
        </div>
        <div>
            <button type="button" id="all">全选</button>
            <button type="button" id="no">取消</button>
            <button type="button" id="reverse">反选</button>
            <button type="button" id="send">提交</button>
        </div>
    </form>
</div>

<script>
    const hobbies = document.querySelectorAll("[name=hobby]")
    const checkAll = document.querySelector("#check-all")

    // 检查是否有没有被选中的标签
    function checkAllSelect() {
        for (let hobby of hobbies) {
            if (!hobby.checked) {
                checkAll.checked = false
                return
            }
        }
        checkAll.checked = true
    }


    hobbies.forEach(item => {
        item.onchange = checkAllSelect
    })

    // 全选
    const selectAllBtn = document.querySelector("#all")
    selectAllBtn.onclick = () => {
        hobbies.forEach(item => {
            item.checked = true
        })
        checkAll.checked = true
    }

    // 取消全选
    const selectNoBtn = document.querySelector("#no")
    selectNoBtn.onclick = () => {
        hobbies.forEach(item => {
            item.checked = false
        })
        checkAll.checked = false
    }

    // 反选
    const reverseBtn = document.querySelector("#reverse")
    reverseBtn.onclick = () => {
        hobbies.forEach(item => {
            item.checked = !item.checked
        })

        checkAllSelect()
    }

    // 提交
    const submitBtn = document.querySelector("#send")
    submitBtn.onclick = () => {
        let res = []
        hobbies.forEach(item => {
            if (item.checked) {
                console.log(item)
                res.push(item.value)
            }
        })
        console.log(res)
        alert("选中的兴趣: " + res.join(", "))
    }
</script>
</body>
</html>

3. DOM的修改

3.1 添加节点

  • document.createElement(tagName):创建一个标签
  • document.appendChild():用于给一个节点添加子节点
  • document.insertAdjacentElement():可以向元素的任意位置添加元素
    • 两个参数:1.要添加的位置 2.要添加的元素
    • beforeend 标签的最后
    • afterbegin 标签的开始
    • beforebegin 在元素的前边插入元素(兄弟元素)
    • afterend 在元素的后边插入元素(兄弟元素)
  • docuemnt.insertAdjacentHTML():向任意位置添加HTML文本
// 创建一个li
const li = document.createElement("li")
// 向li中添加文本
li.textContent = "唐僧"
// 给li添加id属性
li.id = "ts"

const list = document.getElementById("list")

// 下面三种方法插入的位置都是一样的
list.appendChild(li)
// list.insertAdjacentElement("beforeend", li)
// list.insertAdjacentHTML("beforeend", "<li id='ts'>唐僧</li>")

3.2 删除节点

  • document.replaceWith():使用一个元素来替换当前元素
  • document.remove():删除当前元素
const li = document.createElement("li")
li.textContent = "蜘蛛精"
li.id = "zzj"

// 获取swk
const swk = document.getElementById("swk")

// replaceWith() 使用一个元素替换当前元素
swk.replaceWith(li)

// remove()方法用来删除当前元素
// swk.remove()

3.3 练习

实现表格的增删

  • 删除:删除一整行数据
  • 增加:将下方填入信息加入表格中

image-20221207130622822

注意事项

  • a标签的跳转

    • 在a标签的href中设置为#,依然会发生跳转,#表示跳转到页面开头
    • 在a标签的onclick事件最后返回false就可以取消默认的跳转行为,但是这种方式只在 xxx.xxx = function(){}这种方式绑定的事件中才适用
    • 也可设置为javascript:;改为执行这段代码,也可以取消默认跳转
  • form中的button中type设置为button可以取消默认的提交事件

  • 这种写法,容易被xss的攻击,当用户在姓名地方写入<script src="xxx"></srcipt>,然后我们将这个数据存入到数据库中,在下个用户加载页面的时候就会自动执行这个脚本,风险很大,所以,当要渲染用户自己输入的内容的话,使用xxx.innerText = xx修改,这种方法会自动转移其中的字符

    const tbody = document.querySelector("tbody")
    
    tbody.insertAdjacentHTML(
        "beforeend",
        `
        <tr>
            <td>${name}</td>
            <td>${email}</td>
            <td>${salary}</td>
            <td><a href="javascript:;">删除</a></td>
        </tr>
    `
    )
    
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .outer {
            width: 400px;
            margin: 100px auto;
            text-align: center;
        }

        table {
            width: 400px;
            border-collapse: collapse;
            margin-bottom: 20px;
        }

        td,
        th {
            border: 1px black solid;
            padding: 10px 0;
        }

        form div {
            margin: 10px 0;
        }
    </style>
</head>
<body>
    <div class="outer">
        <table>
            <tbody>
            <tr>
                <th>姓名</th>
                <th>邮件</th>
                <th>薪资</th>
                <th>操作</th>
            </tr>
            <tr>
                <td>孙悟空</td>
                <td>swk@hgs.com</td>
                <td>10000</td>
                <td><a href="javascript:;">删除</a></td>
            </tr>
            <tr>
                <td>猪八戒</td>
                <td>zbj@glz.com</td>
                <td>8000</td>
                <td><a href="javascript:;">删除</a></td>
            </tr>
            <tr>
                <td>沙和尚</td>
                <td>shs@lsh.com</td>
                <td>6000</td>
                <td><a href="javascript:;">删除</a></td>
            </tr>
            </tbody>
        </table>

        <form action="#">
            <div>
                <label for="name">姓名</label>
                <input type="text" id="name"/>
            </div>
            <div>
                <label for="email">邮件</label>
                <input type="email" id="email"/>
            </div>
            <div>
                <label for="salary">薪资</label>
                <input type="number" id="salary"/>
            </div>
            <button>添加</button>
        </form>
    </div>

    <script>

        // 删除
        function removeTr() {
            console.log(this)
            console.log(this.parentNode)
            this.parentNode.parentNode.remove()
        }

        const removeLinks = document.querySelectorAll("a")
        removeLinks.forEach(item => {
            item.onclick = removeTr
        })

        // 添加
        const addBtn = document.querySelector("button")
        addBtn.onclick = function () {
            const name = document.querySelector("#name").value
            const email = document.querySelector("#email").value
            const salary = document.querySelector("#salary").value

            const tbody = document.querySelector("tbody")
            const tr = document.createElement("tr")
            const td1 = document.createElement("td")
            td1.innerText = name
            const td2 = document.createElement("td")
            td2.innerText = email
            const td3 = document.createElement("td")
            td3.innerText = salary

            tr.appendChild(td1)
            tr.appendChild(td2)
            tr.appendChild(td3)

            tbody.appendChild(tr)
            tr.insertAdjacentHTML("beforeend", "<td><a href='javascript:;' >删除</a></td>")
            document.links[document.links.length - 1].onclick = removeTr
        }
    </script>
</body>
</html>

3.4 复制节点

  • document.cloneNode():对节点进行复制时,它会复制节点的所有特点包括各种属性
    • 这个方法默认只会复制当前节点,而不会复制节点的子节点
    • 可以传递一个true作为参数,这样该方法也会将元素的子节点一起复制

下面案例演示将一个li节点从一个list复制到另一个list中

如果直接使用appendChild的话则id为l1的标签会在第一个ul中消失

<!DOCTYPE html>
<html lang="zh">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
    </head>
    <body>
        <button id="btn01">点我一下</button>

        <ul id="list1">
            <li id="l1">孙悟空</li>
            <li id="l2">猪八戒</li>
            <li id="l3">沙和尚</li>
        </ul>

        <ul id="list2">
            <li>蜘蛛精</li>
        </ul>

        <script>
            /* 点击按钮后,将id为l1的元素添加list2中 */
            const list2 = document.getElementById("list2")
            const l1 = document.getElementById("l1")
            const btn01 = document.getElementById("btn01")
            btn01.onclick = function () {
                const newL1 = l1.cloneNode(true) // 用来对节点进行复制的
                newL1.id = "newL1"
                list2.appendChild(newL1)
            }
        </script>
    </body>
</html>

3.5 修改CSS样式

  • 通过元素.style.样式名 = 样式值修改element的样式
    • 会直接在元素的内联样式中添加对应样式
    • 如果样式名中含有-,则需要将样式表修改为驼峰命名法
    • background-color --> backgroundColor

案例:点击按钮后,修改box1的宽度

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <title>Document</title>
    <style>
        .box1 {
            width: 200px;
            height: 200px;
            background-color: #bfa;
        }
    </style>
</head>
<body>
    <button id="btn">点我一下</button>
    <hr/>
    <div class="box1"></div>
    <script>
        const btn = document.getElementById("btn")
        const box1 = document.querySelector(".box1")

        btn.onclick = function () {
            // 修改box1的样式
            box1.style.width = "400px"
            box1.style.height = "400px"
            box1.style.backgroundColor = "yellow"
        }
    </script>
</body>
</html>

3.6 读取CSS样式

3.6.1 getComputedStyle()

元素.style.样式名读取到的是内联样式,如果是通过class定义的样式,则这种形式不能获取到样式

正确的方式是使用getComputedStyle()来读取样式

  • 它会返回一个对象,这个对象中包含了当前元素所有的生效的样式

  • 参数:

    1. 要获取样式的对象
    2. 要获取的伪元素
  • 返回值:返回的一个对象,对象中存储了当前元素的样式

  • 注意:样式对象中返回的样式值,不一定能来拿来直接计算,所以使用时,一定要确保值是可以计算的才去计算,如果获取数值的话可以使用parseInt()处理,在处理完之后设置的时候记得再加回去

案例:点击按钮后,获取box的样式

<!DOCTYPE html>
<html lang="zh">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
        <style>
            .box1 {
                height: 200px;
                background-color: #bfa;
            }

            .box1::before {
                content: "hello";
                color: red;
            }
        </style>
    </head>
    <body>
        <button id="btn">点我一下</button>
        <hr />
        <div class="box1"></div>
        <script>
            /*点击按钮后,读取元素的css样式*/
            const btn = document.getElementById("btn")
            const box1 = document.querySelector(".box1")

            btn.onclick = function () {
                const styleObj = getComputedStyle(box1)
                console.log(styleObj.width)
                console.log(styleObj.left)
                console.log(styleObj.backgroundColor)
                
                // 修改样式,记得加单位
                console.log(parseInt(styleObj.width) + 100)
                box1.style.width = parseInt(styleObj.width) + 100 + "px"

                // 获取伪元素样式
                const beforeStyle = getComputedStyle(box1, "::before")
                console.log(beforeStyle.color)
            }
        </script>
    </body>
</html>

3.6.2 通过属性读取样式

  • 获取元素内部的宽度和高度(包括内容区和内边距),返回的是数值
    • 元素.clientHeight:height + 2*padding
    • 元素.clientWidth:width + 2*padding
  • 获取元素的可见框的大小(包括内容区、内边距和边框
    • 元素.offsetHeight:height + 2*padding + border
    • 元素.offsetWidth:width + 2*padding + border
  • 获取元素滚动区域的大小(包括可见和不可见的总大小)
    • 元素.scrollHeight:内容区最大高度 + 内边距
    • 元素.scrollWidth:内容区最大宽度 + 内边距
  • 获取元素的定位父元素
    • 元素.offsetParent
    • 定位父元素:离当前元素最近的开启了定位的祖先元素,如果所有的元素都没有开启定位则返回body
  • 获取元素相对于其定位父元素的偏移,所有父元素都没有开启定位的话则是相对于body
    • 元素.offsetTop
    • 元素.offsetLeft
  • 获取或设置元素滚动条的偏移量(可以修改的)
    • 元素.scrollTop
    • 元素.scrollLeft
<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #box1{
            width: 200px;
            height: 200px;
            padding: 50px;
            margin: 50px;
            border: 10px red solid;
            background-color: #bfa;
            overflow: auto;
        }

        #box2{
            width: 100px;
            height: 500px;
            background-color: orange;
        }

    </style>
</head>
<body>
    <button id="btn">点我一下</button>
    <hr>
    <div>
        <div id="box1">
            <div id="box2"></div>
        </div>
    </div>

    <script>

        const btn = document.getElementById("btn")
        const box1 = document.getElementById("box1")

        btn.onclick = function(){
            console.log(box1.clientHeight)	// 300
            console.log(box1.clientWidth)	// 283(还有一部分被滚动条占了)
            
            console.log(box1.offsetHeight)	// 320
            console.log(box1.offsetWidth)	// 320
            
            console.log(box1.scrollHeight)	// 600
            console.log(box1.scrollWidth)	// 283

            console.log(box1.offsetParent)	// body

            console.log(box1.offsetLeft) // 58
            console.log(box1.offsetTop)	 // 92

            console.log(box1.scrollTop)  // 0
            box1.scrollTop = 100
            console.log(box1.scrollTop)  // 100
        }
    </script>
</body>
</html>

3.7 修改class

如果直接通过js代码中修改某个样式,会造成代码耦合太高,我们可以通过修改class属性来间接的修改样式

通过class修改样式的好处:

  1. 可以一次性修改多个样式
  2. 对JS和CSS进行解耦
const box1 = document.querySelector(".box1")

box1.className += " box2"

元素.classList 是一个对象,对象中提供了对当前元素的类的各种操作方法

  • 元素.classList.add() 向元素中添加一个或多个class,如果有的话则不会做任何操作
  • 元素.classList.remove() 移除元素中的一个或多个class
  • 元素.classList.toggle() 切换元素中的class
  • 元素.classList.replace() 替换class
  • 元素.classList.contains() 检查class

案例:点击按钮后,修改box1的宽度

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <title>Document</title>
    <style>
        .box1 {
            width: 200px;
            height: 200px;
            background-color: #bfa;
        }


        .box2 {
            background-color: yellow;
            width: 300px;
            height: 500px;
            border: 10px greenyellow solid;
        }
    </style>
</head>
<body>
    <button id="btn1">add</button>
    <button id="btn2">toggle</button>
    
    <hr/>

    <div class="box1 box3 box4"></div>

    <script>
        const btn1 = document.getElementById("btn1")
        const btn2 = document.getElementById("btn2")
        const box1 = document.querySelector(".box1")

        btn1.onclick = function () {
            box1.classList.add("box2", "box3")
            let result = box1.classList.contains("box2")
            console.log(result)
        }
        
        btn2.onclick = function () {
            box1.classList.toggle("box2")
        }
    </script>
</body>
</html>

4. 事件

4.1 事件对象简介

  • 事件对象是由浏览器在事件触发时所创建的对象,这个对象中封装了事件相关的各种信息
  • 通过事件对象可以获取到事件的详细信息比如:鼠标的坐标、键盘的按键…
  • 浏览器在创建事件对象后,会将事件对象作为响应函数的参数传递,所以我们可以在事件的回调函数中定义一个形参来接收事件对象

案例:获取鼠标的坐标

const box1 = document.getElementById("box1")

// 下面两种方式都可以拿到事件对象
// box1.onmousemove = event => {
//     console.log(event)
// }

box1.addEventListener("mousemove", event => {
    console.log(event.clientX, event.clientY)

    box1.textContent = event.clientX + "," + event.clientY
})

4.2 Event对象

Event - Web API 接口参考

  • 在DOM中存在着多种不同类型的事件对象,多种事件对象有一个共同的祖先 Event
    • event.target 触发事件的对象
    • event.currentTarget 绑定事件的对象(同this)
    • event.stopPropagation() 停止事件的传导
    • event.preventDefault() 取消默认行为
  • 事件的冒泡(bubble)
    • 事件的冒泡就是指事件的向上传导
    • 当元素上的某个事件被触发后,其祖先元素上的相同事件也会同时被触发
    • 冒泡的存在大大的简化了代码的编写,但是在一些场景下我们并不希望冒泡存在不希望事件冒泡时,可以通过事件对象来取消冒泡

案例:阻止事件冒泡

  • 点击最小的div不会向外冒泡,点击中间的div会向外冒泡

image-20221207145636903

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <title>Document</title>
    <style>
        #box1 {
            width: 300px;
            height: 300px;
            background-color: greenyellow;
        }

        #box2 {
            width: 250px;
            height: 250px;
            background-color: #ff0;
        }

        #box3 {
            width: 200px;
            height: 200px;
            background-color: orange;
        }
    </style>
</head>
<body>
    <div id="box1">
        <div id="box2">
            <div id="box3"></div>
        </div>
    </div>

    <script>
        const box1 = document.getElementById("box1")
        const box2 = document.getElementById("box2")
        const box3 = document.getElementById("box3")

        box1.addEventListener("click", function (event) {
            alert("Hello 我是box1")
        })

        box2.addEventListener("click", function (event) {
            alert("我是box2")
        })

        box3.addEventListener("click", function (event) {
            event.stopPropagation() // 取消事件的传到
            alert("我是box3")
        })
    </script>
</body>
</html>

案例:取消超链接的默认跳转行为

const link = document.querySelector("a")

link.addEventListener("click", (event) => {

    event.preventDefault() // 取消默认行为

    alert("被点了~~~")

})

4.3 冒泡

  • 取消冒泡:event.stopPropagation()

案例:图标跟随鼠标

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        #box {
            width: 20px;
            height: 20px;
            border-radius: 50%;
            background-color: #8cdb69;
            position: absolute;
        }
    </style>
</head>
<body>
    <div id="box"></div>
    <script>
        const box = document.querySelector("#box")

        document.addEventListener("mousemove", (event) => {
            box.style.top = event.y - 10 + 'px'
            box.style.left = event.x - 10 + 'px'
        })
    </script>
</body>
</html>

案例:在一片区域中图标不跟随鼠标(使用阻止冒泡事件实现效果)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        #box {
            width: 20px;
            height: 20px;
            border-radius: 50%;
            background-color: #8cdb69;
            position: absolute;
        }

        #box2 {
            width: 400px;
            height: 400px;
            background-color: black;
        }
    </style>
</head>
<body>
    <div id="box"></div>
    <div id="box2"></div>
    <script>
        const box = document.querySelector("#box")
        const box2 = document.querySelector("#box2")

        document.addEventListener("mousemove", (event) => {
            box.style.top = event.y + 'px'
            box.style.left = event.x + 'px'
        })

        box2.addEventListener("mousemove", (event) => {
            event.stopPropagation()
        })
    </script>
</body>
</html>

4.4 事件的委派

委派就是将本该绑定给多个元素的事件,统一绑定给父级元素,这样可以降低代码复杂度方便维护

案例:点击li标签,打印出其中的内容

思路:原来是通过在每一个li上都绑定一个点击事件,然后对新加的li也再添加事件,但是现在可以使用事件的委派来实现这个操作,也就是直接绑定在父级元素上

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        ul {
            background-color: orange;
            width: 100px;
        }
    </style>
</head>
<body>
    <ul>
        <li>链接1</li>
        <li>链接2</li>
        <li>链接3</li>
        <li>链接4</li>
    </ul>
    <script>
        const ul = document.querySelector("ul")
        ul.addEventListener("click", event => {
            alert(event.target.innerText)
        })
    </script>
</body>
</html>

4.5 事件的捕获

事件的传播机制

  • 在DOM中,事件的传播可以分为三个阶段:
    1. 捕获阶段 (由祖先元素向目标元素进行事件的捕获)(默认情况下,事件不会在捕获阶段触发
    2. 目标阶段 (触发事件的对象)
    3. 冒泡阶段 (由目标元素向祖先元素进行事件的冒泡)
  • 事件的捕获,指事件从外向内的传导,当前元素触发事件以后,会先从当前元素最大的祖先元素开始向当前元素进行事件的捕获
  • 如果希望在捕获阶段触发事件,可以将addEventListener的第三个参数设置为true
    • 一般情况下我们不希望事件在捕获阶段触发,所有通常都不需要设置第三个参数

通过event.eventPhase可以获得事件触发的阶段

1 捕获阶段 2 目标阶段 3 冒泡阶段
  • 捕获:由外向里传播
  • 冒泡:由里向外传播
  • 使用stopPropagation()可以停止捕获或者冒泡,在执行到的函数停止
<!DOCTYPE html>
<html lang="zh">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
        <style>
            #box1 {
                width: 300px;
                height: 300px;
                background-color: greenyellow;
            }

            #box2 {
                width: 200px;
                height: 200px;
                background-color: orange;
            }

            #box3 {
                width: 100px;
                height: 100px;
                background-color: tomato;
            }
        </style>
    </head>
    <body>
        <div id="box1">
            <div id="box2">
                <div id="box3"></div>
            </div>
        </div>

        <script>
            const box1 = document.getElementById("box1")
            const box2 = document.getElementById("box2")
            const box3 = document.getElementById("box3")

            box1.addEventListener("click", event => {
                alert("1" + event.eventPhase) // eventPhase 表示事件触发的阶段
                //1 捕获阶段 2 目标阶段 3 冒泡阶段
            })

            box2.addEventListener("click", event => {

                alert("2" + event.eventPhase)
            })

            box3.addEventListener("click", event => {
                alert("3" + event.eventPhase)
            })
        </script>
    </body>
</html>

5. 其他

5.1 定时器

通过定时器,可以使代码在指定时间后执行

5.1.1 单次定时器

setTimeout()

  • 参数:
    1. 回调函数(要执行的代码)
    2. 间隔的时间(毫秒)
  • 关闭定时器:clearTimeout(标识)
const timer = setTimeout(()=>{
    alert("我是定时器中的代码")
}, 3000)

clearTimeout(timer)

5.1.2 多次定时器

setInterval() (每间隔一段时间代码就会执行一次)

  • 参数:
    1. 回调函数(要执行的代码)
    2. 间隔的时间(毫秒)
  • 关闭定时器:clearInterval()
let num = 0

const timer = setInterval(() => {
    num++
    numH1.textContent = num

    if(num === 200){
        clearInterval(timer)
    }
}, 30)

5.1.3 原理

定时器的原理是在到时之后将定时器的回调函数放到消息队列中,等调用栈中的函数执行完成之后才去执行

通过以下代码就可以看到,定时器并不是3000ms倒计时结束就立即执行的

console.time()
setTimeout(function(){
    console.timeEnd()
    console.log("定时器执行了~")
}, 3000)

使程序卡6s
const begin = Date.now()
while (Date.now() - begin < 6000) {}

image-20221207223252289

setInterval()是每隔固定时间将函数放到消息队列汇总,如果函数的执行速度比较慢,则无法确保每一次的执行间隔是一样的,通过下面这种方式可以确保每次执行都有相同的间隔

console.time("间隔")
setTimeout(function fn() {
    console.timeEnd("间隔")
    alert("哈哈")

    console.time("间隔")
    // 在setTimeout的回调函数的最后,在调用一个setTimeout
    setTimeout(fn, 3000)
}, 3000)

5.2 事件循环

事件循环(event loop)

  • 函数在每次执行时,都会产生一个执行环境
  • 执行环境负责存储函数执行时产生的一切数据
  • 问题:函数的执行环境要存储到哪里呢?
    • 函数的执行环境存储到了一个叫做调用栈的地方
    • 栈,是一种数据结构,特点 后进先出
  • 调用栈(call stack)
    • 调用栈负责存储函数的执行环境
    • 当一个函数被调用时,它的执行环境会作为一个栈帧,插入到调用栈的栈顶,函数执行完毕其栈帧会自动从栈中弹出

对于下列代码,执行到fn2()函数内部时调用栈如图,当执行玩fn2()之后会将fn2对应栈帧从调用栈中弹出,直到执行完所有代码

image-20221207221447471

5.3 消息队列

  • 消息队列负责存储将要执行的函数
  • 当我们触发一个事件时,其响应函数并不是直接就添加到调用栈中的,因为调用栈中有可能会存在一些还没有执行完的代码
  • 事件触发后,JS引擎是将事件响应函数插入到消息队列中排队

当我们点击页面中的按钮的时候,对应的点击事件会先加入到消息队列中,等待调用栈中的所有代码全部执行完了之后,再从消息队列中取出第一个事件到调用栈中执行,直到消息队列为空,然后后面会定期扫描消息队列,如果消息队列中有新消息,则会继续执行

image-20221207222200446

调用栈先于消息队列执行的证据:

下面这段代码,setTimeout() 0ms后就应该执行,说明就是立即执行的,但是实际运行结果却是2222先打印

setTimeout(() => {
    console.log(11111)
}, 0)

console.log(222222)

image-20221207224146590

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/73207.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

设计模式之简单工厂模式

simple factory design pattern 简单工厂模式的概念、简单工厂模式的结构、简单工厂模式优缺点、简单工厂模式的使用场景、简单工厂模式的实现示例 注&#xff1a;简单工厂模式没有被收录在 GoF 的二十三种设计模式中。 1、简单工厂的概念 简单工厂模式&#xff0c;与其说是设…

32位PCI转CPCI转接板

功能型号 32位PCI转CPCI转接板&#xff0c;调试卡 支持PICMG 2.0 D3.0规范&#xff1b; 支持33MHz速率&#xff1b; 支持32bit总线&#xff1b; 功能描述 1、沉金工艺&#xff0c;接触更好&#xff1b; 2、四层板设计&#xff0c;抗干扰更好&#xff1b; 3、信号线等长处理&…

【论文精读9】MVSNet系列论文详解-AA-RMVSNet

AA-RMVSNet&#xff0c;论文名为&#xff1a;AA-RMVSNet: Adaptive Aggregation Recurrent Multi-view Stereo Network&#xff0c;CVPR2021&#xff08;CCF A&#xff09; 本文是MVSNet系列的第9篇&#xff0c;建议看过【论文精读1】MVSNet系列论文详解-MVSNet之后再看便于理解…

【Java 快速复习】 Java 内存模型 并发问题本质

【Java 快速复习】 Java 内存模型 & 并发问题本质 在 Java 领域&#xff0c;我们经常会说两个名词大家要有所区分&#xff1a; JVM 内存模型&#xff1a;这个所说的是 JVM 内存的划分规则&#xff0c;如 堆、栈、元空间等Java 内存模型&#xff1a;这个所说的是线程和主内…

【计算机网络】应用层

应用层的许多协议都是基于客户服务器方式。 客户和服务器指通信中所涉及的两个应用进程。客户服务器方式描述的是进程之间服务和被服务的关系。客户是服务请求方&#xff0c;服务器是服务提供方。 P2P模式&#xff1a;整个网络中的传输内容不再被保存在中心服务器中&#xff…

怎么裁剪视频?手把手教你裁剪

这两年&#xff0c;随着网课的不断发展&#xff0c;我们可以很轻松的就在网上找到各种课程视频。可是有时候&#xff0c;一些视频里面的重点内容往往只有那几分钟&#xff0c;当我们回顾的时候&#xff0c;需要不断跳转&#xff0c;这就显得有些麻烦。其实我们可以将重点内容裁…

【代码随想录】二刷-回溯算法

回溯算法 《代码随想录》 什么是回溯算法&#xff1f; 回溯算法也可以叫做回溯搜索法&#xff0c;它是一种搜索方式。回溯是递归的副产品&#xff0c;只要有递归就会有回溯。 回溯法的效率: 回溯法的本质是穷举&#xff0c;穷举所有可能&#xff0c;然后选出我们想要的答案。(n…

如何使用virtualenv实现python环境的隔离?

有关更多的Python 开发内容,可访问:《 Python Flask开发指南》​​​​​​​ virtualenv可以帮助我们来创建一个Python的虚拟环境,虚拟环境可以独立并隔离外部的python环境,方便我们对于不同项目使用不同的python依赖,已经依赖版本的不同而导致的错误。本篇文章主要来了解…

2022全年度冰箱十大热门品牌销量榜单

自2022年年初以来&#xff0c;各地纷纷部署支持包括冰箱在内的家电大宗消费政策措施&#xff0c;其中家电补贴政策是刺激家电消费的主旋律。宏观经济政策环境改善&#xff0c;利好冰箱行业的长期发展。 根据鲸参谋数据统计&#xff0c;今年京东平台冰箱的年度累计销量达到1400多…

论文阅读笔记《Learning Combinatorial Solver for Graph Matching》

核心思想 本文提出一种基于学习的组合求解器来实现图匹配。之前基于学习的图匹配方法都是利用神经网络提取特征构建关联矩阵&#xff0c;然后再利用可微分的Sinkhorn算法求解匹配矩阵。但本文提出的方法没有显式的构建关联矩阵和求解匹配矩阵的过程&#xff0c;而是将其转化成关…

SpringBoot:核心模块盘点

spring-boot-project 是 spring-boot 核心技术包&#xff0c;其中包含了 spring-boot 所有基础源码&#xff0c;其中很多模块都是我们了解 spring-boot 的重点。 &#xff5e; 本篇内容包括&#xff1a;spring-boot-project 包介绍、Spring Boot 核心模块 文章目录一、spring-b…

SpringCloud-Geteway之限流,熔断(超详细篇)

目录 一&#xff0c;Sentinel--服务容错 1.1 高并发带来的问题 1. 使用压测工具,对请求进行压力测试 2.修改配置文件中tomcat的并发数 1.2 服务雪崩效应 1.3 常见容错方案 1.4 Sentinel入门 什么是Sentinel 微服务集成Sentinel 安装Sentinel控制台 实现一个接口的限…

QTextLine、QGlyphRun、QTextLayout

QGlyphRun 一、描述 此类提供对字体中内部字形的直接访问。在某些情况下&#xff0c;开发人员可以对特定字体中的字形绘制到屏幕上进行更低级的控制。 当Qt显示以Unicode编码的文本字符串时&#xff0c;它会将Unicode点转换为基于字体的字形索引列表和位置列表。QGlyphRun 提…

企业对于源代码加密需求分析

需求 随着企业信息化发展的日益增长&#xff0c;软件行业厂商之间的竞争也愈加白热化&#xff0c;加上国内对知识产权的不够重视、山寨模仿产品的横行。保护源代码、保证企业的核心竞争力&#xff0c;成为众多软件研发企业的第一要务。那么企业应该如何保证源代码的安全呢&…

[附源码]计算机毕业设计常见Web漏洞对应PC应用系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

HTTP缓存机制(Cache-Control)

文章目录HTTP缓存机制HTTP缓存机制 HTTP 协议通常应用于分布式信息系统&#xff0c;所谓分布式信息系统&#xff0c;是指以计算机网络为基础&#xff0c;将系统的数据与功能分别布置在不同的地方&#xff0c;然后再通过网络将数据与功能连接的信息系统。由于系统需要处理大量的…

世界杯期间我使用Python生成二维码“为中国队辟谣”

二维码介绍 二维码本质上&#xff0c;就是一段字符串&#xff0c;我们可以把任意字符串&#xff0c;制作成一个二维码图片。在生活中&#xff0c;使用二维码更多的是一个URL&#xff08;网址&#xff09;。 引入 qrcode库 qrocde库网址&#xff1a;qrcode PyPI 进入网址之后…

[附源码]计算机毕业设计贷款申请审核管理系统论文Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

本地字节序与网络字节序的相互转换(IP地址、端口号)

一般数据在内存中是按照字节存储的&#xff0c;存储的方式分为大端和小端。在不知道对方主机的存储方式的情况下&#xff0c;我们不知道是否需要转换数据的存储方式。因此&#xff0c;TCP/IP协议规定&#xff1a;发送到网络的数据流应采用大端字节序&#xff01; 如果当前主机…

年产3000吨原味奶糖生产车间工艺设计

目 录 摘 要 I Abstract II 1绪论 1 1.1原味奶糖的概念及其功能特性 1 1.2国外原味奶糖的现状 3 1.3我国的原味奶糖现状及开发前景 4 1.4原味奶糖原料的生产情况 4 2工艺流程设计 6 2.1 原味奶糖的生产工艺 6 2.1.1 溶糖与混合 7 2.1.2 连续真空薄膜熬糖 7 2.1.3 混合 8 2.1.4 …