经过描述
事情是这样的在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 . 到此就结束了....
下面请上我们今天的主角:有请小趴菜