练习DOM操作调用appendChild报参数非Node类型错误,代码哪里有误?
问题排查与修复
错误原因
你遇到的Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'报错,核心原因是2个逻辑错误:
- appendChild调用逻辑完全颠倒
appendChild是父节点调用,参数为需要插入的子节点,你的代码想把ul容器listContainer插入到按钮里,同时把li插入到按钮里,完全不符合DOM层级要求(正确层级应为:.pokemon-list(ul) > li > button)。 - DOM节点取值异常(触发报错的直接原因)
如果document.querySelector('.pokemon-list')没有查询到对应元素,会返回null,此时你将null作为参数传入appendChild,就会触发参数不是Node类型的报错。
除此之外还有1个逻辑错误会导致功能异常:按钮文本取值错误,你写的pokemonRepository.name是取IIFE返回对象的name属性,该属性不存在,正确应该取当前遍历的宝可梦对象的name属性pokemon.name。
修复后的代码
//IIFE 立即执行函数 let pokemonRepository = (function () { // 宝可梦列表数组 let pokemonList = [ { name: '妙蛙种子', height: 2.4, types: ['草', '毒'] }, { name: '小火龙', height: 2, types: '火' }, { name: '杰尼龟', height: 1.8, types: '水' } ]; // 向宝可梦图鉴添加新宝可梦 function add(pokemon) { pokemonList.push(pokemon); } function getAll() { return pokemonList } return { add: add, getAll: getAll } })(); // 把DOM查询提到循环外,避免每次遍历重复查询DOM let listContainer = document.querySelector('.pokemon-list'); // 确保DOM查询到节点后再执行后续逻辑,避免空值报错 if (listContainer) { // 遍历输出宝可梦列表 pokemonRepository.getAll().forEach(function(pokemon){ let listItem = document.createElement('li'); let button = document.createElement('button'); // 修正宝可梦名称取值 button.innerText = pokemon.name button.classList.add('poke-button'); // 修正appendChild层级:li里插按钮,ul里插li listItem.appendChild(button); listContainer.appendChild(listItem); }); }
额外注意事项
- 确保你的JS代码是在页面DOM加载完成后执行的,建议把JS脚本放在
</body>标签之前,避免querySelector查询不到已定义的ul元素。 - 你HTML里提前定义的class为
list-item的空li元素不会和代码冲突,如果你不需要可以删除,JS代码会动态生成li元素。
内容的提问来源于stack exchange,提问作者ZAKSCH01
相关产品推荐
相关产品推荐

