请自行脑补我现在的表情……/生无可恋/
新手一枚,所以探访知识的道路总会是弯弯曲曲的~
能认识到的问题是逐渐增多的,只是通过各种路径找到的解决办法不一定能时刻记住,怕自己还会栽在同样的问题上,所以记录下来供参考咯
被自己的惯有思维坑到了。
之前经常听说在html文档里写JavaScript脚本(JS)的时候要注意几点:
- 为了加快html文档的加载速度,所以JS脚本尽量放于</body>结束标签前;
- 为了防止使用过多document.getElementByXX();所以要尽量把这个获取DOM元素的过程放在编写的函数外;
首先,放在head标签内的JS脚本是在文档树建立起来之前,也就是浏览器窗口的内容还没有显示出来之前就已经被加载了的,可以被执行的JS函数都已经被执行了,剩下的都是响应事件的函数了。
所以……我犯得第一个错就是把获取DOM元素的代码放在了这个head里的script脚本内。
是这样:(这是我精简化的测试例子,实际代码量比这多很多,所以杂乱更不好找出错误)
<head>
<script type="text/javascript">
var aa=document.getElementById("cj_name");
alert(aa.value);
</script>
</head>
name<input type="text" id="cj_name">
我想,就算没有值,但这样至少能弹出个框来吧。。。
结果我还真是想多了。。。
什么反应都没有。。。
我在name的input框里写了很多字,但是也还是什么都没有。。。
我试着直接把alert(aa.value)换成alert(aa);,啊!弹出了个null对话框!
可是……上面那行代码照理来说应该得到的是那个元素节点啊,应该是个对象啊……
还是不对,所以我又将alert(aa)换成了alert(typeof aa);,想看看获取到的aa是什么类型……
结果是object!
我傻了……
明明就是个真实存在的对象节点,可是为什么直接输出就是null,输出对象里的内容又不行呢……
我突然想起浏览器还有个F12查看源码的调试页面,于是又把上面的试了一下……
结果确实是有错误的,因为这个元素节点没有被定义。这么一看!我就想会不会是这两行代码是在body里的内容加载(也就是文档树对象建立)出来之前就已经被执行了,所以获取不到那个对象节点啊。。。
然后我想还真是……
所以我把script整个移到body后</body>结束标签前,发现运行正常了……而且要是放在这个元素节点之前也是不行的。。。是的,在树建立之前,都是无法获取到这个节点的。。。因为html文档是自上而下顺序流出的……
<body>
name:<input type="text" id="cj_name">
<script type="text/javascript">
var aa=document.getElementById("cj_name");
alert(aa.value);
</script>
</body>
所以也就是说,只要文档树没有完全建立起来,我们就没办法读取到已建成的文档树之外的元素节点。
然后我又继续探索了一下……然后就发现getElementById和getElementsByTagName好像还是有差别的……
刚刚说到,getElementById如果放在head里的脚本中,而且单独成句,不放在事件函数里时,它是不被识别到的,也就是说getElementById在文档流输出之前被执行,得到的是空的未被定义的对象节点,所以,当执行如下代码时:
<head>
<script type="text/javascript">
var aa=document.getElementById("cj_name");
function check()
{
alert(aa.value);
}
</script>
</head>
<body>
name:<input type="text" id="cj_name" onblur="check()">
sex:<input type="text" id="cj_sex">
age:<input type="text">
haha:<input type="text">
<input type="submit" value="submit" >
</body>
在name行的input里输入内容再让其失去焦点后,页面是没有任何反应的。
但是把script里的内容换成以下:
var aa=document.getElementsByTagName("input");
function check()
{
alert(aa[0].value);
}
这样,按上面的操作让其失去焦点后输出的是刚刚输入的name行的input里的内容。
所以我猜想getElementById和getElementsByTagName的运行机制是不一样的。前者是当即就在页面找id值为该字符串的元素节点,没找到就返回为空,不管html文档流失输出了还是未输出,文档树建立还是未建立;后者却是必须要在文档树建立之后执行,查询整棵树之后才返回结果。
再来验证一下:
var aa=document.getElementsByTagName("input");
alert(aa[0].value);
仍是将其放在head里的JS中。
我先试图获取所有的input标签,然后将第一个input标签内的内容输出(alert(aa[0].value);),但是结果报错,因为这时候树还没建立,getElementsByTagName函数的还没返回结果,直接执行alert,可是aa里面是空的啊
我用循环去读取
var aa=document.getElementsByTagName("input");
for(var i=0;i<aa.length;i++)
{
alert(aa[i].value);
}
没有报错,刚好就证明了获取的aa数组里并没有东西(本质原因还是因为文档树没建立起来啦~)
var aa=document.getElementsByTagName("input");
function check()
{
for(var i=0;i<aa.length-1;i++)
{
alert(aa[i].value);
}
}
这样就可以输出所有input里的东西咯~嗯呐~应该就是这样。所以顺理推测getElementsByClassName应该跟getElementsByTagName一样。
总结一下:
文档树建立完全后才能获取元素节点对象并对其进行操作,否则就是耍流氓,人家不会鸟你;
JS代码能放body里就放body里,要养成好习惯,当然最好封装在外部JS文件里;
通过id起作用的东西都要注意使用,注意它的特殊性;
小问题容易引起大恐慌,谨慎再谨慎!
其实这些真的是很简单的问题……可是这些问题要是都不知道,那还真是要命啊……心都被伤透了……
哎,感觉自己有点啰嗦呢……这么简单的问题难道不是一看就知道了么……入门级前端的小心翼翼
反正没人看,当自己写日记咯,练思维,练习说废话调节自己心情……
哇嚯,继续fighting!