亚洲 国产精品 日韩-亚洲 激情-亚洲 欧美 91-亚洲 欧美 成人日韩-青青青草视频在线观看-青青青草影院

千鋒教育-做有情懷、有良心、有品質(zhì)的職業(yè)教育機(jī)構(gòu)

手機(jī)站
千鋒教育

千鋒學(xué)習(xí)站 | 隨時(shí)隨地免費(fèi)學(xué)

千鋒教育

掃一掃進(jìn)入千鋒手機(jī)站

領(lǐng)取全套視頻
千鋒教育

關(guān)注千鋒學(xué)習(xí)站小程序
隨時(shí)隨地免費(fèi)學(xué)習(xí)課程

當(dāng)前位置:首頁  >  技術(shù)干貨  > 如何實(shí)現(xiàn)拖拽排序

如何實(shí)現(xiàn)拖拽排序

來源:千鋒教育
發(fā)布人:wjy
時(shí)間: 2022-06-02 13:54:00 1654149240

可拖拽排序的菜單效果大家想必都很熟悉,本次我們通過一個(gè)可拖拽排序的九宮格案例來演示其實(shí)現(xiàn)原理。 

如何實(shí)現(xiàn)拖拽排序

## 實(shí)現(xiàn)原理概述

**拖拽原理**

- 當(dāng)鼠標(biāo)在【可拖拽小方塊】(以下簡(jiǎn)稱磚頭)身上按下時(shí),開始監(jiān)聽鼠標(biāo)移動(dòng)事件
- 鼠標(biāo)事件移動(dòng)到什么位置,磚頭就跟到什么位置
- 鼠標(biāo)抬起時(shí),取消鼠標(biāo)移動(dòng)事件的監(jiān)聽

**排序原理**

- 提前定義好9大坑位的位置(相對(duì)外層盒子的left和top)
- 將9大磚頭丟入一個(gè)數(shù)組,以便后期通過splice方法隨意安插和更改磚頭的位置
- 當(dāng)拖動(dòng)某塊磚頭時(shí),先將其從數(shù)組中移除(剩余的磚頭在邏輯上重新排序)
- 拖動(dòng)結(jié)束時(shí),將該磚頭重新插回?cái)?shù)組的目標(biāo)位置(此時(shí)實(shí)現(xiàn)數(shù)據(jù)上的重排)
- 數(shù)組中的9塊磚頭根據(jù)新的序號(hào),對(duì)號(hào)入座到9大坑位,完成重新渲染

## 代碼實(shí)現(xiàn)

**頁面布局**

9塊磚頭(li元素)相對(duì)于外層盒子(ul元素)做絕對(duì)定位

```html
<ul id="box">
        <li style="background-color:black;top: 10px; left: 10px">1</li>
        <li style="background-color:black;top: 10px; left: 220px">2</li>
        <li style="background-color:black;top: 10px; left: 430px">3</li>
        <li style="background-color:black;top: 220px; left: 10px">4</li>
        <li style="background-color:black;top: 220px; left: 220px">5</li>
        <li style="background-color:black;top: 220px; left: 430px">6</li>
        <li style="background-color:black;top: 430px; left: 10px">7</li>
        <li style="background-color:black;top: 430px; left: 220px">8</li>
        <li style="background-color:black;top: 430px; left: 430px">9</li>
    </ul>
```

樣式如下

```css
<style>
        * {
            margin: 0;
            padding: 0;
        }

        html,
        body {
            width: 100%;
            height: 100%;
        }

        ul,
        li {
            list-style: none;
        }

        ul {
            width: 640px;
            height: 640px;
            border: 10px solid pink;
            border-radius: 10px;
            margin: 50px auto;
            position: relative;
        }

        li {
            width: 200px;
            height: 200px;
            border-radius: 10px;
            display: flex;
            justify-content: center;
            align-items: center;
            color: white;
            font-size: 100px;
            position: absolute;
        }
    </style>
```

**定義磚頭的背景色和9大坑位位置**

```js
// 定義9大li的預(yù)設(shè)背景色
    var colorArr = [
        "red",
        "orange",
        "yellow",
        "green",
        "blue",
        "cyan",
        "purple",
        "pink",
        "gray",
    ];

    /* 定義9大坑位 */
    const positions = [
        [10, 10], [220, 10], [430, 10],
        [10, 220], [220, 220], [430, 220],
        [10, 430], [220, 430], [430, 430],
    ]
```

**找出磚頭并丟入一個(gè)數(shù)組**

```js
var ulBox = document.querySelector("#box")
    var lis = document.querySelectorAll("#box>li")
    /* 將lis轉(zhuǎn)化為真數(shù)組 */
    lis = toArray(lis)
```

這里我使用了一個(gè)將NodeList偽數(shù)組轉(zhuǎn)化為真數(shù)組的輪子:

```js
/* 偽數(shù)組轉(zhuǎn)真數(shù)組 pseudo array */
    function toArray(pArr){
        var arr = []
        for(var i=0;i<pArr.length;i++){
            arr.push(pArr[i])
        }
        return arr
    }
```

**給所有磚頭內(nèi)置一個(gè)position屬性**

```js
/* 給每塊磚內(nèi)置一個(gè)position屬性 */
    lis.forEach(
        (item, index) => item.setAttribute("position", index)
    )
```

**定義正在拖動(dòng)的磚頭**

```js
/* 正在拖動(dòng)的Li(磚頭) */
        var draggingLi = null;

        // 正在拖動(dòng)的磚頭的zindex不斷加加,保持在最上層
        var maxZindex = 9
```

**在身上按下 誰就是【正在拖動(dòng)的磚頭】**

```js
/* 在身上按下 誰就是【正在拖動(dòng)的磚頭】 */
        lis.forEach(
            function (li, index) {
                li.style.backgroundColor = colorArr[index]

                /* li中的文字不可選(禁止selectstart事件的默認(rèn)行為) */
                li.addEventListener(
                    "selectstart",
                    function (e) {
                        // 阻止掉拖選文本的默認(rèn)行為
                        e.preventDefault()
                    }
                )

                /* 在任意li身上按下鼠標(biāo)=我想拖動(dòng)它 */
                li.addEventListener(
                    "mousedown",
                    function (e) {
                        draggingLi = this
                        draggingLi.style.zIndex = maxZindex++
                    }
                )
            }
        )
```

**在任意位置松開鼠標(biāo)則停止拖拽**

```js
/* 在頁面的任意位置松開鼠標(biāo)=不再拖拽任何對(duì)象 */
        document.addEventListener(
            "mouseup",
            function (e) {
                // 當(dāng)前磚頭自己進(jìn)入位置躺好
                const p = draggingLi.getAttribute("position") * 1
                // draggingLi.style.left = positions[p][0] + "px"
                // draggingLi.style.top = positions[p][1] + "px"
                move(
                    draggingLi,
                    {
                        left:positions[p][0] + "px",
                        top:positions[p][1] + "px"
                    },
                    200
                    // callback
                )

                // 正在拖拽的磚頭置空
                draggingLi = null;
            }
        )
```

當(dāng)前磚頭從鼠標(biāo)事件位置回歸其坑位時(shí)用到動(dòng)畫效果,以下是動(dòng)畫輪子

```js
/**
 * 多屬性動(dòng)畫
 * @param {Element} element 要做動(dòng)畫的元素
 * @param {Object} targetObj 屬性目標(biāo)值的對(duì)象 封裝了所有要做動(dòng)畫的屬性及其目標(biāo)值
 * @param {number} timeCost 動(dòng)畫耗時(shí),單位毫秒
 * @param {Function} callback 動(dòng)畫結(jié)束的回調(diào)函數(shù)
 */
const move = (element, targetObj, timeCost = 1000, callback) => {
    const frameTimeCost = 40;

    // 500.00px 提取單位的正則
    const regUnit = /[\d\.]+([a-z]*)/;

    // 計(jì)算動(dòng)畫總幀數(shù)
    const totalFrames = Math.round(timeCost / frameTimeCost);

    // 動(dòng)態(tài)數(shù)一數(shù)當(dāng)前動(dòng)畫到了第幾幀
    let frameCount = 0;

    /* 查詢特定屬性的速度(湯鵬飛的辣雞) */
    // const getAttrSpeed = (attr) => (parseFloat(targetObj[attr]) - parseFloat(getComputedStyle(element)[attr]))/totalFrames

    // 存儲(chǔ)各個(gè)屬性的初始值和動(dòng)畫速度
    const ssObj = {};

    /* 遍歷targetObj的所有屬性 */
    for (let attr in targetObj) {
        // 拿到元素屬性的初始值
        const attrStart = parseFloat(getComputedStyle(element)[attr]);

        // 動(dòng)畫速度 = (目標(biāo)值 - 當(dāng)前值)/幀數(shù)
        const attrSpeed =
            (parseFloat(targetObj[attr]) - attrStart) / totalFrames;

        // 將【屬性初始值】和【屬性幀速度】存在obj中 以后obj[left]同時(shí)拿到這兩個(gè)貨
        // obj{ left:[0px初始值,50px每幀] }
        ssObj[attr] = [attrStart, attrSpeed];
    }

    /* 開始動(dòng)畫 */
    const timer = setInterval(
        () => {
            // element.style.left = parseFloat(getComputedStyle(element).left)+"px"
            // element.style.top = parseFloat(getComputedStyle(element).top)+"px"
            // element.style.opacity = getComputedStyle(element).opacity

            // 幀數(shù)+1
            frameCount++;

            /* 每個(gè)屬性的值都+=動(dòng)畫速度 */
            for (let attr in targetObj) {
                // console.log(attr, ssObj[attr], totalFrames, frameCount);

                // 用正則分離出單位
                // console.log(regUnit.exec("500px"));
                // console.log(regUnit.exec(0));
                const unit = regUnit.exec(targetObj[attr])[1];

                // 計(jì)算出當(dāng)前幀應(yīng)該去到的屬性值
                const thisFrameValue =
                    ssObj[attr][0] + frameCount * ssObj[attr][1];

                // 將元素的屬性掰到當(dāng)前幀應(yīng)該去到的目標(biāo)值
                element.style[attr] = thisFrameValue + unit;
            }

            /* 當(dāng)前幀 多個(gè)屬性動(dòng)畫完成 判斷是否應(yīng)該終止動(dòng)畫  */
            if (frameCount >= totalFrames) {
                // console.log(frameCount, totalFrames);
                clearInterval(timer);

                /* 強(qiáng)制矯正(反正用戶又看不出來 V) */
                // for (let attr in targetObj) {
                //     element.style[attr] = targetObj[attr];
                //     console.log(attr, getComputedStyle(element)[attr]);
                // }

                // 如果有callback就調(diào)用callback
                // if(callback){
                //     callback()
                // }
                callback && callback();
            }
        },

        frameTimeCost
    );

    /* 動(dòng)畫結(jié)束后再過一幀 執(zhí)行暴力校正 */
    setTimeout(() => {
        /* 強(qiáng)制矯正(反正用戶又看不出來 V) */
        for (let attr in targetObj) {
            element.style[attr] = targetObj[attr];
            // console.log(attr, getComputedStyle(element)[attr]);
        }
    }, timeCost + frameTimeCost);

    // 返回正在運(yùn)行的定時(shí)器
    return timer;
};
```

**移動(dòng)鼠標(biāo)時(shí) 磚頭跟隨 所有磚頭實(shí)時(shí)洗牌**

```js
/* 在ul內(nèi)移動(dòng)鼠標(biāo) draggingLi跟隨鼠標(biāo) */
        ulBox.addEventListener(
            "mousemove",
            function (e) {
                /* 如果draggingLi為空 什么也不做 直接返回 */
                if (draggingLi === null) {
                    return
                }

                // 拿到事件相對(duì)于ulBox的位置  
                var offsetX = e.pageX - ulBox.offsetLeft - 100
                var offsetY = e.pageY - ulBox.offsetTop - 100

                /* 校正磚頭的偏移量 */
                offsetX = offsetX < 10 ? 10 : offsetX
                offsetY = offsetY < 10 ? 10 : offsetY
                offsetX = offsetX > 430 ? 430 : offsetX
                offsetY = offsetY > 430 ? 430 : offsetY

                // 將該位置設(shè)置給draggingLi
                draggingLi.style.left = offsetX + "px"
                draggingLi.style.top = offsetY + "px"

                /* 實(shí)時(shí)檢測(cè)實(shí)時(shí)【坑位】 */
                const newPosition = checkPosition([offsetX, offsetY]);

                // 如果當(dāng)前磚頭的position發(fā)生變化 則數(shù)據(jù)重排
                const oldPosition = draggingLi.getAttribute("position") * 1
                if (newPosition != -1 && newPosition != oldPosition) {
                    console.log(oldPosition, newPosition);

                    /* 數(shù)據(jù)重排 */
                    // 先將當(dāng)前磚頭拽出數(shù)組(剩余的磚頭位置自動(dòng)重排)
                    lis.splice(oldPosition, 1)
                    // 再將當(dāng)前磚頭插回newPosition
                    lis.splice(newPosition, 0, draggingLi)

                    // 打印新數(shù)據(jù)
                    // logArr(lis,"innerText")

                    // 磚頭洗牌
                    shuffle()
                }

            }
        )
```

**坑位檢測(cè)方法**

```js
/* 實(shí)時(shí)檢測(cè)坑位:檢測(cè)ep與9大坑位的距離是否小于100 */
        const checkPosition = (ep) => {
            for (let i = 0; i < positions.length; i++) {
                const [x, y] = positions[i]//[10,10]
                const [ex, ey] = ep//[offsetX,offsetY]

                const distance = Math.sqrt(Math.pow(x - ex, 2) + Math.pow(y - ey, 2))
                if (distance < 100) {
                    return i
                }
            }

            // 沒有進(jìn)入任何坑位
            return -1
        }
```

**磚頭洗牌方法**

```js
/* 磚頭洗牌:lis中的每塊磚去到對(duì)應(yīng)的位置 */
        const shuffle = () => {
            for (var i = 0; i < lis.length; i++) {
                lis[i].style.left = positions[i][0] + "px"
                lis[i].style.top = positions[i][1] + "px"

                // 更新自己的位置
                lis[i].setAttribute("position", i)
            }
        }
```

## 完整代碼實(shí)現(xiàn)

**主程序**

```js
<!DOCTYPE html>
<html lang="en">

<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>九宮格拖拽排序</title>

    <style>
        * {
            margin: 0;
            padding: 0;
        }

        html,
        body {
            width: 100%;
            height: 100%;
        }

        ul,
        li {
            list-style: none;
        }

        ul {
            width: 640px;
            height: 640px;
            border: 10px solid pink;
            border-radius: 10px;
            margin: 50px auto;
            position: relative;
        }

        li {
            width: 200px;
            height: 200px;
            border-radius: 10px;
            display: flex;
            justify-content: center;
            align-items: center;
            color: white;
            font-size: 100px;
            position: absolute;
        }
    </style>
</head>

<body>
    <ul id="box">
        <li style="background-color:black;top: 10px; left: 10px">1</li>
        <li style="background-color:black;top: 10px; left: 220px">2</li>
        <li style="background-color:black;top: 10px; left: 430px">3</li>
        <li style="background-color:black;top: 220px; left: 10px">4</li>
        <li style="background-color:black;top: 220px; left: 220px">5</li>
        <li style="background-color:black;top: 220px; left: 430px">6</li>
        <li style="background-color:black;top: 430px; left: 10px">7</li>
        <li style="background-color:black;top: 430px; left: 220px">8</li>
        <li style="background-color:black;top: 430px; left: 430px">9</li>
    </ul>

    <!--
    position 位置
     -->
    <script src="../../../tools/arr_obj_tool.js"></script>
    <script src="../../../tools/animtool.js"></script>

    <script>
        // 定義9大li的預(yù)設(shè)背景色
        var colorArr = [
            "red",
            "orange",
            "yellow",
            "green",
            "blue",
            "cyan",
            "purple",
            "pink",
            "gray",
        ];

        /* 定義9大坑位 */
        const positions = [
            [10, 10], [220, 10], [430, 10],
            [10, 220], [220, 220], [430, 220],
            [10, 430], [220, 430], [430, 430],
        ]

        var ulBox = document.querySelector("#box")
        var lis = document.querySelectorAll("#box>li")
        /* 將lis轉(zhuǎn)化為真數(shù)組 */
        lis = toArray(lis)

        /* 給每塊磚內(nèi)置一個(gè)position屬性 */
        lis.forEach(
            (item, index) => item.setAttribute("position", index)
        )

        /* 正在拖動(dòng)的Li(磚頭) */
        var draggingLi = null;

        // 正在拖動(dòng)的磚頭的zindex不斷加加,保持在最上層
        var maxZindex = 9

        /* 在身上按下 誰就是【正在拖動(dòng)的磚頭】 */
        lis.forEach(
            function (li, index) {
                li.style.backgroundColor = colorArr[index]

                /* li中的文字不可選(禁止selectstart事件的默認(rèn)行為) */
                li.addEventListener(
                    "selectstart",
                    function (e) {
                        // 阻止掉拖選文本的默認(rèn)行為
                        e.preventDefault()
                    }
                )

                /* 在任意li身上按下鼠標(biāo)=我想拖動(dòng)它 */
                li.addEventListener(
                    "mousedown",
                    function (e) {
                        draggingLi = this
                        draggingLi.style.zIndex = maxZindex++
                    }
                )
            }
        )

        /* 在頁面的任意位置松開鼠標(biāo)=不再拖拽任何對(duì)象 */
        document.addEventListener(
            "mouseup",
            function (e) {
                // 當(dāng)前磚頭自己進(jìn)入位置躺好
                const p = draggingLi.getAttribute("position") * 1
                // draggingLi.style.left = positions[p][0] + "px"
                // draggingLi.style.top = positions[p][1] + "px"
                move(
                    draggingLi,
                    {
                        left: positions[p][0] + "px",
                        top: positions[p][1] + "px"
                    },
                    200
                    // callback
                )

                // 正在拖拽的磚頭置空
                draggingLi = null;
            }
        )

        /* 在ul內(nèi)移動(dòng)鼠標(biāo) draggingLi跟隨鼠標(biāo) */
        ulBox.addEventListener(
            "mousemove",
            function (e) {
                /* 如果draggingLi為空 什么也不做 直接返回 */
                if (draggingLi === null) {
                    return
                }

                // 拿到事件相對(duì)于ulBox的位置  
                var offsetX = e.pageX - ulBox.offsetLeft - 100
                var offsetY = e.pageY - ulBox.offsetTop - 100

                /* 校正磚頭的偏移量 */
                offsetX = offsetX < 10 ? 10 : offsetX
                offsetY = offsetY < 10 ? 10 : offsetY
                offsetX = offsetX > 430 ? 430 : offsetX
                offsetY = offsetY > 430 ? 430 : offsetY

                // 將該位置設(shè)置給draggingLi
                draggingLi.style.left = offsetX + "px"
                draggingLi.style.top = offsetY + "px"

                /* 實(shí)時(shí)檢測(cè)實(shí)時(shí)【坑位】 */
                const newPosition = checkPosition([offsetX, offsetY]);

                // 如果當(dāng)前磚頭的position發(fā)生變化 則數(shù)據(jù)重排
                const oldPosition = draggingLi.getAttribute("position") * 1
                if (newPosition != -1 && newPosition != oldPosition) {
                    console.log(oldPosition, newPosition);

                    /* 數(shù)據(jù)重排 */
                    // 先將當(dāng)前磚頭拽出數(shù)組(剩余的磚頭位置自動(dòng)重排)
                    lis.splice(oldPosition, 1)
                    // 再將當(dāng)前磚頭插回newPosition
                    lis.splice(newPosition, 0, draggingLi)

                    // 打印新數(shù)據(jù)
                    // logArr(lis,"innerText")

                    // 磚頭洗牌
                    shuffle()
                }

            }
        )

        /* 實(shí)時(shí)檢測(cè)坑位:檢測(cè)ep與9大坑位的距離是否小于100 */
        const checkPosition = (ep) => {
            for (let i = 0; i < positions.length; i++) {
                const [x, y] = positions[i]//[10,10]
                const [ex, ey] = ep//[offsetX,offsetY]

                const distance = Math.sqrt(Math.pow(x - ex, 2) + Math.pow(y - ey, 2))
                if (distance < 100) {
                    return i
                }
            }

            // 沒有進(jìn)入任何坑位
            return -1
        }

        /* 磚頭洗牌:lis中的每塊磚去到對(duì)應(yīng)的位置 */
        const shuffle = () => {
            for (var i = 0; i < lis.length; i++) {
                lis[i].style.left = positions[i][0] + "px"
                lis[i].style.top = positions[i][1] + "px"

                // 更新自己的位置
                lis[i].setAttribute("position", i)
            }
        }

    </script>
</body>

</html>
```

**動(dòng)畫輪子**

```js
function moveWithTransition(element, targetObj, duration) {
    element.style.transition = `all ${duration / 1000 + "s"} linear`;
    for (var attr in targetObj) {
        element.style[attr] = targetObj[attr];
    }
    setTimeout(() => {
        element.style.transition = "none";
    }, duration);
}

/**
 * 多屬性動(dòng)畫
 * @param {Element} element 要做動(dòng)畫的元素
 * @param {Object} targetObj 屬性目標(biāo)值的對(duì)象 封裝了所有要做動(dòng)畫的屬性及其目標(biāo)值
 * @param {number} timeCost 動(dòng)畫耗時(shí),單位毫秒
 * @param {Function} callback 動(dòng)畫結(jié)束的回調(diào)函數(shù)
 */
const move = (element, targetObj, timeCost = 1000, callback) => {
    const frameTimeCost = 40;

    // 500.00px 提取單位的正則
    const regUnit = /[\d\.]+([a-z]*)/;

    // 計(jì)算動(dòng)畫總幀數(shù)
    const totalFrames = Math.round(timeCost / frameTimeCost);

    // 動(dòng)態(tài)數(shù)一數(shù)當(dāng)前動(dòng)畫到了第幾幀
    let frameCount = 0;

    /* 查詢特定屬性的速度(湯鵬飛的辣雞) */
    // const getAttrSpeed = (attr) => (parseFloat(targetObj[attr]) - parseFloat(getComputedStyle(element)[attr]))/totalFrames

    // 存儲(chǔ)各個(gè)屬性的初始值和動(dòng)畫速度
    const ssObj = {};

    /* 遍歷targetObj的所有屬性 */
    for (let attr in targetObj) {
        // 拿到元素屬性的初始值
        const attrStart = parseFloat(getComputedStyle(element)[attr]);

        // 動(dòng)畫速度 = (目標(biāo)值 - 當(dāng)前值)/幀數(shù)
        const attrSpeed =
            (parseFloat(targetObj[attr]) - attrStart) / totalFrames;

        // 將【屬性初始值】和【屬性幀速度】存在obj中 以后obj[left]同時(shí)拿到這兩個(gè)貨
        // obj{ left:[0px初始值,50px每幀] }
        ssObj[attr] = [attrStart, attrSpeed];
    }

    /* 開始動(dòng)畫 */
    const timer = setInterval(
        () => {
            // element.style.left = parseFloat(getComputedStyle(element).left)+"px"
            // element.style.top = parseFloat(getComputedStyle(element).top)+"px"
            // element.style.opacity = getComputedStyle(element).opacity

            // 幀數(shù)+1
            frameCount++;

            /* 每個(gè)屬性的值都+=動(dòng)畫速度 */
            for (let attr in targetObj) {
                // console.log(attr, ssObj[attr], totalFrames, frameCount);

                // 用正則分離出單位
                // console.log(regUnit.exec("500px"));
                // console.log(regUnit.exec(0));
                const unit = regUnit.exec(targetObj[attr])[1];

                // 計(jì)算出當(dāng)前幀應(yīng)該去到的屬性值
                const thisFrameValue =
                    ssObj[attr][0] + frameCount * ssObj[attr][1];

                // 將元素的屬性掰到當(dāng)前幀應(yīng)該去到的目標(biāo)值
                element.style[attr] = thisFrameValue + unit;
            }

            /* 當(dāng)前幀 多個(gè)屬性動(dòng)畫完成 判斷是否應(yīng)該終止動(dòng)畫  */
            if (frameCount >= totalFrames) {
                // console.log(frameCount, totalFrames);
                clearInterval(timer);

                /* 強(qiáng)制矯正(反正用戶又看不出來 V) */
                // for (let attr in targetObj) {
                //     element.style[attr] = targetObj[attr];
                //     console.log(attr, getComputedStyle(element)[attr]);
                // }

                // 如果有callback就調(diào)用callback
                // if(callback){
                //     callback()
                // }
                callback && callback();
            }
        },

        frameTimeCost
    );

    /* 動(dòng)畫結(jié)束后再過一幀 執(zhí)行暴力校正 */
    setTimeout(() => {
        /* 強(qiáng)制矯正(反正用戶又看不出來 V) */
        for (let attr in targetObj) {
            element.style[attr] = targetObj[attr];
            // console.log(attr, getComputedStyle(element)[attr]);
        }
    }, timeCost + frameTimeCost);

    // 返回正在運(yùn)行的定時(shí)器
    return timer;
};
```

**偽數(shù)組轉(zhuǎn)真數(shù)組輪子**

```js
/* 偽數(shù)組轉(zhuǎn)真數(shù)組 pseudo array */
function toArray(pArr){
    var arr = []
    for(var i=0;i<pArr.length;i++){
        arr.push(pArr[i])
    }
    return arr
}
```

這里大家也可以簡(jiǎn)單地

```js
const arr = [...pArr]
```

祝大家擼碼愉快,身心健康!更多關(guān)于“web前端培訓(xùn)”的問題,歡迎咨詢千鋒教育在線名師。千鋒已有十余年的培訓(xùn)經(jīng)驗(yàn),課程大綱更科學(xué)更專業(yè),有針對(duì)零基礎(chǔ)的就業(yè)班,有針對(duì)想提升技術(shù)的提升班,高品質(zhì)課程助理你實(shí)現(xiàn)夢(mèng)想。

tags:
聲明:本站稿件版權(quán)均屬千鋒教育所有,未經(jīng)許可不得擅自轉(zhuǎn)載。
10年以上業(yè)內(nèi)強(qiáng)師集結(jié),手把手帶你蛻變精英
請(qǐng)您保持通訊暢通,專屬學(xué)習(xí)老師24小時(shí)內(nèi)將與您1V1溝通
免費(fèi)領(lǐng)取
今日已有369人領(lǐng)取成功
劉同學(xué) 138****2860 剛剛成功領(lǐng)取
王同學(xué) 131****2015 剛剛成功領(lǐng)取
張同學(xué) 133****4652 剛剛成功領(lǐng)取
李同學(xué) 135****8607 剛剛成功領(lǐng)取
楊同學(xué) 132****5667 剛剛成功領(lǐng)取
岳同學(xué) 134****6652 剛剛成功領(lǐng)取
梁同學(xué) 157****2950 剛剛成功領(lǐng)取
劉同學(xué) 189****1015 剛剛成功領(lǐng)取
張同學(xué) 155****4678 剛剛成功領(lǐng)取
鄒同學(xué) 139****2907 剛剛成功領(lǐng)取
董同學(xué) 138****2867 剛剛成功領(lǐng)取
周同學(xué) 136****3602 剛剛成功領(lǐng)取
相關(guān)推薦HOT
抖音小店運(yùn)營(yíng)做什么的

在當(dāng)前的電商市場(chǎng)中,抖音小店已經(jīng)逐漸成為一種新的電商模式,它集成了社交化、音視頻分享、直播銷售等多種功能,使得消費(fèi)者更加便捷地進(jìn)行商品...詳情>>

2023-10-08 16:36:41
抖音小店照片要求尺寸多大

在抖音平臺(tái)開設(shè)小店已經(jīng)成為了越來越多人的選擇,相信大家已經(jīng)在各大社交平臺(tái)上看到有不少小店的推廣。在抖音上,照片是展示產(chǎn)品的重要手段,因...詳情>>

2023-10-08 16:14:25
抖音招商團(tuán)長(zhǎng)托管服務(wù)費(fèi)怎么退回來

抖音招商團(tuán)長(zhǎng)托管服務(wù)是抖音為有意愿創(chuàng)作內(nèi)容并帶動(dòng)其他創(chuàng)作者成為團(tuán)隊(duì)成員的用戶提供的一種服務(wù)。通過該服務(wù),招商團(tuán)長(zhǎng)可以自主組建團(tuán)隊(duì)并得到...詳情>>

2023-10-08 16:08:53
抖音小店怎么做代銷

抖音已經(jīng)成為了一個(gè)非常受歡迎的短視頻應(yīng)用程序,在其中許多用戶都精心打造了自己的小店,用于銷售各種各樣的商品,獲取額外的收入。然而,要想...詳情>>

2023-10-08 15:28:41
怎樣開抖音小店帶貨賺錢

隨著直播帶貨的火熱,越來越多的人開始嘗試通過抖音小店來開展帶貨業(yè)務(wù)。抖音小店是抖音直播帶貨的配套,可以讓用戶在購(gòu)買直播中產(chǎn)品時(shí)就實(shí)現(xiàn)購(gòu)...詳情>>

2023-10-08 15:06:36
厨房人妻HD中文字幕69XX| 超碰97人人射妻| 被男狂揉吃奶胸高潮视频在线观看 | 国内少妇毛片视频| 久久久久久国产精品无码超碰| 欧美午夜性春猛交ⅩXXX男| 少女たちよ在线观看完整版动漫 | 国产乱码精品一品二品| 久久久久精品无码一区二区三区| 欧美乱强伦XXXXXXXXXX| 挽起裙子迈开腿坐上去C黄| 亚洲熟妇AV一区二区三区宅男| 2021av在线播放| 国产成人免费无码AV在线播放| 精品欧美H无遮挡在线看中文| 欧美极品少妇XXXXⅩ另类| 挺进邻居人妻雪白的身体韩国电影 | CHINESEXXXXHD麻豆| 国产裸体美女永久免费无遮挡 | CHINESE熟妇与小伙子MA| 国产成人亚洲精品另类动态图| 久久精品国产精品亚洲| 人人爽人人片人人片AV| 亚洲国产成人精品无码一区二区 | 欧美性操大鸡狠狠| 亚洲AV日韩AⅤ无码色老头| 51无码人妻精品1国产| 国产精品久久久天天影视香蕉| 老人玩小处雌女HD另类| 天堂いっしょにしよ在线| 一对浑圆的胸乳被揉捏动态图| 高清成人爽A毛片免费| 久久婷婷五月综合97色一本一本| 日韩免费一区二区三区高清| 亚洲无人区一码二码三码区别| 成人无码H动漫在线网站樱花| 久久GOGO国模啪啪人体| 色欲天天天综合网| 岳女二人名器共侍一夫的出处| 国产成人精品一区二区三区无码| 军人边走边吮她的花蒂| 天天摸夜夜添夜夜无码| 18禁免费无码无遮挡不卡网站| 国产精品无码免费视频二三区| 欧美成人精品 一区二区三区| 亚洲AV成人片无码色欲AV自慰 | 射精情感曰妓女色视频| 伊人久久大香线蕉AV不变影院| 国产高清在线精品一本大道| 男人边吃奶边挵进去呻吟动态图| 亚洲AV成人一区二区三区不卡| 啊灬啊灬啊灬快灬高潮了I| 久久99热这里只有精品国产| 视频视频APP在线看| 最新日本一道免费一区二区| 国产免费无码一区二区| 热爆料-热门吃瓜-黑料不打烊 | 丰满人妻熟妇乱又伦精品APP| 六十路七十路熟女乱码| 亚洲AV无码片一区二区三区 | 99久久精品费精品国产一区二| 国语自产第1国语自产第10页| 日韩人妻中文字幕| 18禁无遮挡无码国产免费网站| 娇妻被黑人调教成公厕| 天天躁日日躁狠狠躁退| 阿娇13分钟视频无删减MP4| 久久亚洲精品无码AⅤ电影 | 好爽好湿好硬好大免费视频| 色偷偷888欧美精品久久久| 97人妻无码一区二区精品免费| 精品水蜜桃久久久久久久| 无码国产孕妇一区二区免费AV| 宝宝又大了1V1| 男人吃奶摸下挵进去好爽在线观看| 亚洲人成色77777在线观看| 国产美足白丝榨精在线观看sm| 日本免费一区二区三区四区五六区| 中文字幕无码人妻丝袜| 久久99国产精品久久99| 香港三香港日本三级在线理论| 吃奶呻吟打开双腿做受在线视频 | 久亚洲一线产区二线产区三线产区| 亚洲AV日韩AV永久无码色欲 | А√天堂8在线官网| 没有被爱过的女人| 亚洲中文字幕A∨| 激情综合五月丁香五月激情 | 国内少妇BBWBBW黑森林| 无人区码一码二码三码区别在哪里| 成人无码无遮挡很H在线播放| 欧美一卡二卡三卡四卡视| 最新国产AⅤ精品无码| 久久婷婷五月综合尤物色国产| 亚洲精品高清国产一线久久| 国产亚洲色欲色一色WWW| 无码国产精品久久一区免费| 抖抈探探APP入口免费| 日本WWW一道久久久免费榴莲| APPSTORE美区免费| 男生把自己的手放到女生的QQ里 | 亚洲HAIRY多毛PICS大全| 国产欧美精品区一区二区三区| 为什么放进去女的就老实了| 国产23在线 | 传媒麻豆| 三级做A全过程在线观看| 成人H动漫无码网站| 人妻办公室出轨上司HD院线| XXXXXL日本17上线| 全黄H全肉边做边吃奶| JK制服白丝自慰出水| 欧美性猛交内射兽交老熟妇| CHINAGARY武警体育飞机| 欧美日韩精品一区二区在线播放 | 林静公交车被做到高C的原因| 艳妇乳肉豪妇荡乳| 久久伊人少妇熟女大香线蕉| 伊人依成久久人综合网| 老太性开放BBWBBWBBW| 在线播放五十路熟妇| 免费热播女人毛片| AV人摸人人人澡人人超碰小说| 破外女第一次出血毛片免费| WWW国产精品内射熟女| 日本丰满少妇XXXX| 敌伦交换第21部分剧情介绍| 色婷婷六月亚洲综合香蕉| 国产边做饭边被躁在线小说| 无码人妻一区二区三区精品视频年 | 欧美熟女一区二区三区| 不卡无在一区二区三区四区| 色婷婷六月亚洲综合香蕉| 国产精品SP调教打屁股| 亚瑟国产精品久久| 精品久久久久久无码人妻热| 野花日本视频免费观看3| 免费无码成人AV在线播放| JK浴室自慰到不停喷水尿失禁| 日韩人妻无码一区二区三区综合部 | 男生把手放进我内裤揉摸好爽| 锕锕锕锕锕锕~好痛APP下载| 入戏太深动漫未删减在线观看| 国产ww又大又粗又刺激孕妇| 亚洲AV日韩AV蜜桃在线播放| 久久久久琪琪去精品色一到本 | 中文国产成人精品久久APP| 欧美成人精品激情在线观看| 成年无码AV片在线| 无码色AV一二区在线播放| 极品教师高清免费观看| 在线涩涩免费观看国产精品| 秋霞鲁丝片AⅤ无码入口| 国产98涩在线 | 欧洲| 亚洲AV无码一区二区一二区| 久久久久久久久久久精品尤物| 377人体粉嫩噜噜噜| 日韩人妻无码精品-专区| 国产偷国产偷亚洲清高APP| 亚洲夜夜性无码国产盗摄| 欧美激情000ⅩXX同性| 公园小树中老年交易图片| 亚洲爆乳成AV人在线视菜奈实| 里面也请好好疼爱第三季| 波多野结衣系列18部无码观看A | 色婷婷五月综合亚洲小说| 黑人大荫道BBWBBB高潮潮喷 | 美区APPSTORE精品| 成色好的Y31S标准版| 亚洲AV中文无码乱人伦下载| 免费观看男女AV入口网站| 反差婊吃瓜爆料黑料免费| 亚洲国产一卡2卡3卡4卡5公司| 拗女稀缺资源一区二区| 国产AV无码专区亚洲精品| 亚洲熟妇AV不卡一区二区三区 | 房中之术御女之功秘术| 亚洲精品456在线播放| 欧美丰满熟妇XXXX| 国产精品久久一区二区三区 | 乱妇乱女熟妇熟女网站| 成人影院YY111111在线| 亚洲精品国产一区二区三区在线观| 男女无遮挡猛进猛出免费观看视频| 国产AⅤ无码专区亚洲AV麻豆| 亚洲日韩精品无码专区加勒比| 人人爽人人爽人人片AV东京热| 国内美女推油按摩在线播放| C交人Z000Z000XXⅩ| 性生大片免费观看网站| 内射到高潮的H小说| 国产精品无码一区二区三区免费| 在线天堂中文最新版| 天天躁夜夜躁天干天干2020 | 天天爽狠狠噜天天噜日日噜| 久久人妻无码中文字幕| 公和我做好爽添厨房| 一二三四免费中文在线| 铜铜铜铜铜铜铜好多水| 末发育女AV片一区二区| 国产色欲AV一区二区三区|