前端新手调用随机图片API时遇TypeError: Cannot read property 'src' of null错误求助
搞定"Cannot read property 'src' of null"这个错误
嘿,我来帮你捋清楚这个问题!你碰到的TypeError: Cannot read property 'src' of null,本质上是你的JavaScript代码在页面元素加载完成前就执行了,导致找不到目标图片元素。
为什么会报错?
你的<script>标签放在了<head>里,浏览器是从上到下解析HTML的。当JS执行var img = document.querySelector("#photo");这行代码时,<body>里的<img id="photo">还没被渲染到页面上呢!所以querySelector找不到这个元素,返回了null,之后你尝试访问null.src,自然就抛出错误了。
另外还有个小细节:你给img.src赋值的时候用了双等号==,这是用来比较值是否相等的运算符,不是赋值用的,得改成单等号=才行!
三种修复方案任你选
方案1:把JS代码挪到页面最底部
最简单的办法就是把<script>标签放到</body>标签前面,这样所有DOM元素都加载完成后,JS才会执行:
<html> <head> <link rel="stylesheet" type="text/css" href="Dog app.css"> </head> <body> <div class="container"> <h1>Welcome to dog photo app</h1> <img src="https://images.dog.ceo/breeds/waterdog-spanish/20180723_185544.jpg" id="photo" alt=""><br> <form> <input type="button" id="btn" onclick="c()" value="click me"> </form> </div> <!-- 把JS移到这里 --> <script> var btn = document.querySelector("#btn"); var img = document.querySelector("#photo"); function c(){ var xhr = new XMLHttpRequest(), method = "GET", url = "https://dog.ceo/api/breeds/image/random"; xhr.open(method, url, true); xhr.onreadystatechange = function () { if(xhr.readyState === 4 && xhr.status === 200) { var url = JSON.parse(xhr.responseText).message; img.src = url; // 这里改成单等号赋值 } }; xhr.send(); } </script> </body> </html>
方案2:等DOM加载完成再执行代码
如果你想保留<script>在<head>里,可以监听DOMContentLoaded事件,确保代码只在页面元素都准备好后才运行:
<html> <head> <script> // 监听DOM加载完成事件 document.addEventListener('DOMContentLoaded', function() { var btn = document.querySelector("#btn"); var img = document.querySelector("#photo"); function c(){ var xhr = new XMLHttpRequest(), method = "GET", url = "https://dog.ceo/api/breeds/image/random"; xhr.open(method, url, true); xhr.onreadystatechange = function () { if(xhr.readyState === 4 && xhr.status === 200) { var url = JSON.parse(xhr.responseText).message; img.src = url; // 修复赋值运算符 } }; xhr.send(); } // 这里也可以把按钮点击事件换成更规范的绑定方式 btn.addEventListener('click', c); }); </script> <link rel="stylesheet" type="text/css" href="Dog app.css"> </head> <body> <div class="container"> <h1>Welcome to dog photo app</h1> <img src="https://images.dog.ceo/breeds/waterdog-spanish/20180723_185544.jpg" id="photo" alt=""><br> <form> <input type="button" id="btn" value="click me"> </form> </div> </body> </html>
方案3:给script加defer属性
给<script>标签加上defer属性,浏览器会自动等到DOM加载完成后再执行这个脚本,不用改位置:
<html> <head> <!-- 加上defer属性 --> <script defer> var btn = document.querySelector("#btn"); var img = document.querySelector("#photo"); function c(){ var xhr = new XMLHttpRequest(), method = "GET", url = "https://dog.ceo/api/breeds/image/random"; xhr.open(method, url, true); xhr.onreadystatechange = function () { if(xhr.readyState === 4 && xhr.status === 200) { var url = JSON.parse(xhr.responseText).message; img.src = url; // 修复赋值运算符 } }; xhr.send(); } </script> <link rel="stylesheet" type="text/css" href="Dog app.css"> </head> <body> <div class="container"> <h1>Welcome to dog photo app</h1> <img src="https://images.dog.ceo/breeds/waterdog-spanish/20180723_185544.jpg" id="photo" alt=""><br> <form> <input type="button" id="btn" onclick="c()" value="click me"> </form> </div> </body> </html>
额外小优化:用fetch替代XHR
现在更推荐用fetch API来做网络请求,代码比XMLHttpRequest简洁多了,替换后的c函数是这样的:
function c(){ fetch("https://dog.ceo/api/breeds/image/random") .then(response => response.json()) .then(data => { img.src = data.message; }) .catch(err => console.error('请求出错啦:', err)); }
内容的提问来源于stack exchange,提问作者Viraj
相关产品推荐
相关产品推荐

