记一次 填 Array.concat 的坑

311 阅读2分钟

经过描述

事情是这样的在vue的组件库开发过程中,有一个需求需要使用到自己渲染HTML内容及样式;涉及到dom的操作,然后报错 el.cloneNode is not a function ....

下面那段段平平无奇的代码在 引入scr/index.js 是可以正常运行的

但是 使用 rollup.js build 之后引入 lib\index.js 之后就报错,不能正常运行

废话不多说直接上代码片段


....


const pageList = [... virtualBox.querySelectorAll('div')]
    .map((el)=>{
        const cloneEl = el.cloneNode(true)
        const div = document.createElement('div')
        div.appendChild(cloneEl)
        return div.innerHTML
    })
console.log('pageList',pageList)
// 
.....


具体报错信息就是:


Uncaught TypeError: el.cloneNode is not a function
    at <anonymous>:3:28
    at Array.map (<anonymous>)
    at <anonymous>:2:6


发现问题

根据上述的错误信息已经指示的非常明显了 el.cloneNode is not a function

那既然使用src/index.js 就没有问题;那就说明这代码本身可能没什么毛病; 那咋们就直接丢进控制台跑一下,结果如预期没有什么问题正常运行,打印了 pageList 日志;

继续....

使用 lib/index.js 就报错,那可能就是代码在压缩转化的时候出了问题;

那么 根据关键词 cloneNode 进行查找 压缩后的 index.js

发现

代码被转化了如下格式的代码:


    ....
       const pageList = [].concat(virtualBox.querySelectorAll('div'))
            .map((el)=>{
                const cloneEl = el.cloneNode(true)
                const div = document.createElement('div')
                div.appendChild(cloneEl)
                return div.innerHTML
            })
        console.log('pageList',pageList)
    ....

直接运行压缩转化后的代码,发现就报 el.cloneNode is not a function ...

那么问题显而易见数组转化的时候出了问题;

virtualBox.querySelectorAll('div') 返回的是类数组

那么如何判断是数组还是类数组呢?

方式有很多常见的有 Array.isArray()


Array.isArray([]) // true

Array.isArray(document.querySelectorAll('div')) // false

Array.isArray([].concat(document.querySelectorAll('div'))) // true

看到这也许就更加怪异了,不是我们分析的那样吗 ? Array.isArray([].concat(document.querySelectorAll('div'))) 返回的是一个数组,并非类数组啊

别着急 继续往下看:


const result = [].concat(document.querySelectorAll('div')) 返回
console.log(result)  // [NodeList(221)]

因为 Array 上面肯定 没有 cloneNode 这个API, 所以就抛错了

返回的是期望的数组吗? 答案是 NO

到此

我们已经非常清楚的了解了整个过程.

解决方案

分析清楚了问题的发生过程,解决的方案就显得非常简单了

使用 Array.from 转换


    ....
       const pageList = Array.from(virtualBox.querySelectorAll('div'))
            .map((el)=>{
                const cloneEl = el.cloneNode(true)
                const div = document.createElement('div')
                div.appendChild(cloneEl)
                return div.innerHTML
            })
        console.log('pageList',pageList)
    ....

so . 到此就结束了....

下面请上我们今天的主角:有请小趴菜

小趴菜.jpeg