双引号
在js代码中
在js中单、双引号引起来的是字符串,如果我们要在字符串中使用单、双引号,需要反斜杠进行转义
let str='user\'s name'; // or let str=" user's name"; // or let str="she said:\"...\".";
如果在字符串中输出反斜杠,仍然是用反斜杠转义,即2个反斜杠输出1个反斜杠
在html代码中
html标签中,属性值通常用双引号引起来,也可以使用单引号或不用引号。
<input name=user /> <input name="user" /> <input name='user' />
这3种写法都正确,不过通常我们是选择用双引号引起来。
如果我们要在属性值中使用单、双绰号,我们不能直接写成下面这样
<input name=user'name /> <input name="user"name" /> <input name='user'name' />
这些全部是错误的。我们要像在js中对单、双引号转义一样,对属性中的单、双引号转义
在html中输出预留符号,可以使用字符实体转义的形式,这里有简单介绍:http://www.w3school.com.cn/html/html_entities.asp。即想输出一个双引号可以使用"的形式,
<input name="user"name" />
除此之外,html还支持十进制与十六进制编码的形式输出字符,如我们知道字符a的ascii码的十进制是97 十六进制是61
所以我们在页面body中输出一个字符a,有以下3种形式
<body> a<!--直接输出--> a<!--十进制输出--> a<!--十六进制输出--> </body>
同样,单双引号也有十进制(单:39,双:34)与十六进制(单:27,双:22),所以我们在属性中输出一个单引号有2种选择,十进制与十六进制
<input name='user'name' /><!--十进制--> <input name='user'name' /><!--十六进制-->
而输出一个双引号则有3种选择
<input name="user"name" /><!--实体--> <input name="user"name" /><!--十进制--> <input name="user"name" /><!--十六进制-->
当js代码遇上实体编码
我们可以通过dom节点提供的事件写上调用js的代码,如点击body弹出hello这个字符串,我们可以写成
<body onclick="alert('hello')"> click here </body>
如果我们的需求是就弹出一个双引号呢?
根据前述规则,我们要写成:
<body onclick="alert('"')"><!--这里用十进制或十六进制都可以--> click here </body>
当然,alert里的单引号也可以使用十进制或十六进制编码
<body onclick="alert("'")"><!--"单引号 '双引号--> click here </body>
这样也是可以的。
是不是有点xss的感觉?
如果我们把弹双引号的需求改成单引号呢?
<body onclick="alert(''')"><!--这样html中是合法的,但js中并不合法,因为在js中,中间的单引号并没有转义--> click here </body>
如果我们用十进制或十六进制编码呢?
<body onclick="alert('"')"><!--这样可以吗--> click here </body>
这样仍然是不可以的
我们要对js字符串中的单引号进行转义,如
<body onclick="alert('\'')"><!--转义后可正确弹出--> click here </body>
或
<body onclick="alert('\"')"><!--转义后可正确弹出--> click here </body>
前面的onclick="alert('\'')"看起来还正常,后面的这个onclick="alert('\"')"就有点不直观了。因为后面这个看上去反斜杠像在转义&这1个字符,而&在js的字符串中并不需要转义的。
动态输出
如前述的alert弹出的消息,如果是一个变量控制,动态输出呢?
<body onclick="alert('${msg}')"> click here </body>
那我们这个msg字符串就得注意了,从这个示例来看,这个动态的msg即出现在属性onclick中,也出现在alert的单引号开始的字符串中。
我们要对msg中的双引号转成"或"或",并对msg中单引号的前面加上一个反斜杠\ ?
题外话:对msg中的反斜杠需要做double处理,因为反斜杠在html属性中并不是特殊的,但在js的字符串中是特殊的。因此正确的做法是对反斜杠及单引号前面各加上一个反斜杠
然而,你并不能保证属性是用双引号,alert中的字符串用的是单引号,因为可以写成下面这样
<body onclick='alert("${msg}")'> click here </body>
?
这种情况我们要对msg中的单引号转成'或',并对msg中双引号前面加上一个反斜杠\
题外话:同上
看上去要根据不同的情况做不同的处理,其实也不需要
我们只需要对单、双引号前面加上一个反斜杠\然后再对单、双引号实体编码即可。
在js中如果反斜杠后面跟的不需要反斜杠转义的字符,那么这个反斜杠是被丢弃的,因此像
var str="user\'s name";
单引号前面多加一个反斜杠也不要紧的。
自动化处理与识别提醒
在magix项目中,由于magix-combine的支持,可识别出属性中js代码的部分,并自动化处理,如
<button mx-click="showName({name:'<%=name%>'})">click here</button>
name这个变量可包含任意的单、双引号及反斜杠。工具自动识别并处理,开发者不需要做任何事情。
而对于这样的写法:
<button mx-click="showName({name:'"'})">click here</button> <!-- or--> <button mx-click="showName({name:'\"'})">click here</button>
第一种写法其实并不正确,但第二种情况看上去又怪怪的。magix-combine工具能识别出来是否需要添加反斜杠,并自动添加处理。
第一种需要添加反斜杠,工具会自动加上,并提醒开发者这里的写法是不正确的。
第二种说明开发者意识到了问题所在,自己处理了,工具就不再处理也不再提醒开发者。
内容是《Web前端开发之Javascript视频》的课件,请配合大师哥《Javascript》视频课程学习。
文本节点用Text类型表示,包含的是可以按字面解释的纯文本内容;纯文本内容可以包含转义后的HTML字符,但不能包含HTML代码;
Text类和Comment类都是CharacterData类的子类型;
CharacterData是一个抽象类(接口),代表 Node 对象包含的字符,它是在其他接口中被实现的,如Text、Comment 或 ProcessingInstruction具体的类;
CharacterData类继承自Node类,其拥有data、length、nextElementSibling、previousElementSibling等属性;
拥有的方法:appendData()、deleteData()、insertData()、replaceData()、substringData()。
特征:
data属性:
可以通过nodeValue属性或data属性访问或设置Text节点包含的文本;
var h2 = document.getElementsByTagName("h2")[0];
console.log(h2.childNodes); // NodeList [text]
var text = h2.childNodes[0];
// var text = h2.firstChild; // 也可以
console.log(text); // 零点程序员
console.log(text.nodeType); // 3
console.log(text.nodeName); // #text
console.log(text.nodeValue); // 零点程序员
console.log(text.data); // 零点程序员
text.nodeValue = "zeronetwork";
console.log(text.nodeValue); // zeronetwork
console.log(text.parentNode); // <h2>零点程序员</h2>
length属性:
保存节点中字符的数目,而且nodeValue.length和data.length中也保存着相同的值;
console.log(text.length);
console.log(text.nodeValue.length);
console.log(text.data.length);
在默认情况下,每个可以包含内容的元素最多只能有一个文本节点,而且必须确实有内容存在;
var h4 = document.getElementsByTagName("h4")[0];
// <h4></h4> 返回null
// <h4> </h4> 返回空白,也是文本节点
// <h4>zeronetwork</h4> 返回文本节点
var text = h4.firstChild;
console.log(text);
在修改文本字符串时,字符串会经过HTML编码,即小于号大于号或引号都会被转义;也就是说,在向DOM文档中插入文本之前,会先对其进行HTML编码;
text.nodeValue = "零点程序员<strong>王唯</strong>";
// 会转义为<strong>
console.log(text.nodeValue);
document.write(text.nodeValue);
注:浏览器已自动修正;如果使用document.write()方法,会解析为html代码;
后面我们会学到Element类型的innerHTML和innerText等方法,它们就是获取或设置元素内的HTML字符串或纯文本内容的;如:
var mydiv = document.getElementById("mydiv");
console.log(mydiv.innerHTML)
console.log(mydiv.innerText);
其中,innerText就是把div内的所有后代的元素的纯文本提取,并拼接起来;但我们不使用这个属性也可以达到这种效果;
// 返回元素的纯文本内容,递归进入其子元素
function textContent(e){
var child, type, s = ""; // s保存所有子节点的文本
for(child = e.firstChild; child != null; child = child.nextSibling){
type = child.nodeType;
if(type == 3 || type == 4) // Text和CDATASection节点
s += child.nodeValue;
else if(type == 1) // Element
s += textContent(child);
}
return s;
}
var mydiv = document.getElementById("mydiv");
console.log(mydiv.innerText);
console.log(textContent(mydiv));
将Text节点中的内容转换成大写形式:
// 递归把e的后代节点中的所有Text节点内容转换成大写
function upcase(e){
if(e.nodeType == 3 || e.nodeType == 4)
e.data = e.data.toUpperCase();
else
for(var i=0,len=e.childNodes.length;i<len; i++)
upcase(e.childNodes[i]);
}
var mydiv = document.getElementById("mydiv");
upcase(mydiv);
创建文本节点:
document.createTextNode(data)方法:
创建一个新的文本节点;该方法接受一个文本参数;该文本也将按照HTML或XML的格式进行编码;在创建的同时,也会为其设置ownerDocument属性;也需要添加到文件树中;
注:不能直接为文本节点添加其他特性;
var textNode = document.createTextNode("零点程序员");
document.body.appendChild(textNode);
var div = document.createElement("div");
div.className = "newsdiv";
var textNode = document.createTextNode("zeronetwork");
// textNode.setAttribute("style","color:red"); // 异常
div.appendChild(textNode);
var textNode = document.createTextNode("<strong>零点</strong>zeronetwork");
var mydiv = document.getElementById("mydiv");
mydiv.appendChild(textNode);
console.log(mydiv.lastChild); // <strong>零点</strong>zeronetwork,因为被编码了
console.log(mydiv.lastChild.nodeType); // 3,依然是Text_node
操作文本节点的方法:
normalize()方法:规范化文本节点;
默认情况下,每个元素只有一个文本节点,但如果该元素appendChild多个文本节点后,该元素就可能包含多个文本子节点;
var mydiv = document.getElementById("mydiv");
mydiv.appendChild(document.createTextNode("零点程序员"));
mydiv.appendChild(document.createTextNode("王唯"));
mydiv.appendChild(document.createTextNode("Web前端开发"));
// 此时查看渲染结果为:"零点程序员" "王唯" "Web前端开发"
console.log(mydiv.childNodes.length); // 3
console.log(mydiv.childNodes); // NodeList(3)
for(var i=0,len=mydiv.childNodes.length; i<len; i++)
console.log(mydiv.childNodes[i].nodeValue); // 零点程序员 王唯 Web前端开发
而这种在DOM中,存在相邻的同胞文本节点很容易导致混乱,因为分不清哪个文本节点表示哪个字符串,而在实际开发中,出现这种情况还比较多,于是出现了一个能够将相邻文本节点合并的方法normalize();
该方法Node类型定义的,由父节点调用;
mydiv.normalize();
console.log(mydiv.childNodes.length); // 1
for(var i=0,len=mydiv.childNodes.length; i<len; i++)
console.log(mydiv.childNodes[i].nodeValue); // 零点程序员王唯Web前端开发
normalize()方法规范里说:在一个"规范化"后的DOM树中,不存在一个空的文本节点,或者两个相邻的文本节点;这里的“空的文本节点”并不包括空白字符(空格,换行等)构成的文本节点;
splitText(offset):
分割文本节点;Text类型提供了一个作用与normalize()相反的方法:splitText();
该方法会将一个文本节点分成两个兄弟文本节点,即按照指定的offset位置分割nodeValue值;原来的文本节点将包含从开始到指定offset位置之前的内容,新文本节点将包含剩下的文本,并返回这个新文本节点,并且该节点与原节点的parentNode相同;
var div = document.createElement("div");
div.className = "div";
var textNode = document.createTextNode("zeronetwork");
div.appendChild(textNode);
document.body.appendChild(div);
console.log(div.childNodes.length); // 1
var newNode = div.firstChild.splitText(4);
console.log(div.firstChild.nodeValue); // zero
console.log(newNode.nodeValue); // network
console.log(div.childNodes.length); // 2
如果指定的偏移量刚好等于原文本节点所包含字符串的长度,则返回一个内容为空的文本节点;
var fullNode = div.firstChild.splitText(div.firstChild.nodeValue.length);
console.log(div.firstChild);
console.log(fullNode.nodeValue); // ""
分割后的文本节点还可以使用Node.normalize()方法来合并;分割文本节点是从文本节点中提取数据的一种常用DOM解析技术;
// 在一个文本中插入另一个节点
var p = document.createElement("p");
p.appendChild(document.createTextNode("零点程序员"));
document.body.appendChild(p);
var programmer = p.firstChild.splitText(2);
var strongNode = document.createElement("strong");
strongNode.appendChild(document.createTextNode("zeronetwork"));
p.insertBefore(strongNode, programmer);
appendData(text):将text添加到节点的末尾;
deleteData(offset, count):从offset指定的位置开始删除count个字符;
insertData(offset, text);在offset指定的位置插入text;
repalceData(offset, count, text):用text从offset开始替换count个文本;如果count为0,就是在offset处插入text文本;
substringData(offset, count):从offset位置开始提取count个文本;
<h1>零点程序员</h1>
<script>
var h1 = document.getElementsByTagName("h1")[0];
var txtNode = h1.firstChild;
txtNode.appendData("zeronetwork");
txtNode.deleteData(9, 3);
txtNode.insertData(5, "王唯");
txtNode.replaceData(2,3,"王唯");
var result = txtNode.substringData(2,2);
console.log(result); // 王唯
</script>
Comment类型:
在DOM中通过Comment类型来表示注释;
同Text类一样,Comment类也是继承自CharacterData,它本身没有定义属性和方法,因此它的属性和方法都是直接继承自CharacterData或间接继承自Node类;
特征为:
Comment类型与Text类型继承自相同的基类,因此它拥有除了splitText()之外的所有字符串操作方法;其访问方式同Text类型基本一样;也可以通过其父节点来访问,如:
var mydiv = document.getElementById("mydiv");
console.log(mydiv.firstChild);
console.log(mydiv.childNodes[0]); // mydiv中第1个子元素是注释
console.log(mydiv.childNodes[0].nodeType); // 8
console.log(mydiv.childNodes[0].nodeName); // #comment
console.log(mydiv.childNodes[0].nodeValue); // 这是一段注释
console.log(mydiv.childNodes[0].data); // 这是一段注释
console.log(mydiv.childNodes[0].parentNode); // <div id="mydiv" ...
document.createComment(data)方法:创建注释节,参数data为注释文本;
var mydiv = document.getElementById("mydiv");
var comment = document.createComment("创建注释节点");
mydiv.appendChild(comment);
注:chrome浏览器不会识别位于</html>标签之后的注释,其它可以,因此如果要访问注释节点,一定要保证它们是<html>元素的后代;
<!-- html外的注释 -->
<script>
var c = document.childNodes[2];
console.log(c); // FF输出为undefined,其余可以识别
</script>
在实际开发中,已经直接在代码中注释了,所以很少会创建和访问注释节点;
CDATASection类型:
CDATASection类型只针对基于XML的文档,表示的是CDATA区域;该类继承自Text类型,其本身没有定义属性和方法,全部继承自祖先类,因此其拥有除了splitText()之外的所有字符串操作方法;
其特征:
在XML文档中,可以使用document.createCDataSection()来创建CDATA区域,只须为其传入节点的内容即可;
var cdata = document.createCDATASection("cdata"); // 异常,HTML文档不支持
示例:data.xml文件:
<persons>
<person>
<name>王唯</name>
<age>18</age>
<sex>男</sex>
</person>
<person>
<name>静静</name>
<age>22</age>
<sex>女</sex>
</person>
<![CDATA[
if a < b
]]>
<person>
<name>娟娟</name>
<age>28</age>
<sex>女</sex>
</person>
</persons>
html文档:
function loadXMLDoc(fileName){
var xmlHttp;
if(window.ActiveXObject)
xmlHttp = ActiveXObject("Microsoft.XMLDOM");
else
xmlHttp = new window.XMLHttpRequest();
xmlHttp.open("GET",fileName,true);
xmlHttp.send(null);
xmlHttp.onreadystatechange = function(e){
if(xmlHttp.readyState == 4 && xmlHttp.status == 200){
var xmlDoc = xmlHttp.responseXML;
// console.log(xmlDoc);
parseXML(xmlDoc);
}
}
}
function parseXML(xmlDoc){
var persons = xmlDoc.documentElement;
// console.log(persons);
// console.log(persons.childNodes);
// var ps = persons.getElementsByTagName("person");
// console.log(ps);
// console.log(ps[0]);
// var name = ps[0].getElementsByTagName("name")[0];
// console.log(name.firstChild.nodeValue);
// 获取cdata节点
// var cdata = persons.childNodes[5];
// console.log(cdata);
// console.log(cdata.nodeType); // 4
// console.log(cdata.nodeName); // #cdata-section
// console.log(cdata.nodeValue);
// console.log(cdata.data);
// console.log(cdata.parentNode);
var newCDATA = xmlDoc.createCDATASection("这是CDATA数据");
persons.childNodes[3].appendChild(newCDATA);
console.log(persons.childNodes[3].childNodes);
}
loadXMLDoc("data.xml");
Web前端开发之Javascript-零点程序员-王唯
Hyper Text Markup Language, 超文本标记语言
标记又称为标签(Tag), 一般语法:
<tagName></tagName>
它可以有属性(Attribute):
<tagName attributeName="value">, 如:
<meta charset="utf-8" />
标签也可以不成对地关闭:
<tagName />
HTML文档由浏览器解释并执行。
<!DOCTYPE html> ----- 告诉浏览器用html5的标准来解释和执行该网页
<html>
<head> ---- 头部, 可包含meta, title等标签
</head>
<body> ---- 主体, 包含主要内容
</body>
</html>
<meta charset="utf-8" /> 用于告诉浏览器用什么样的字符编码来解释网页中的文本.
常见编码:
iso-8859-1: 纯英文编码
gbk, gb2312: 简体中文编码
big5: 大五码,繁体中文编码,主要应用于台湾地区
utf-8: 国际首选编码,它兼容所有的字符
除此之外, meta还可以通过keywords, description属性对页面关键词及描述信息进行设置, 以提高搜索引擎的命中.
网页标题, 显示在浏览器选项卡的标题栏上!
h1-h6: 内容标题标签
p: 段落
br: 换行
hr: 水平线
strong: 粗体文本
em: 斜体文本
span: 无任何特殊样式的文本
pre: 预格式标签,其中的内容在页面上带格式渲染
small: 比当前字体小的文本
空格
< 小于
> 大于
© 版权符
" 双引号
<!-- 注释内容 -->
<img
src="图像地址"
title="鼠标悬停提示"
alt="图像加载错误时的替代文本"
width="宽度"
height="高度"
/>
图像地址分为2种:
1. 相对地址, 如: img/cc.jpg
2. 绝对地址, 如: http://img.bcd.com/2017/1644232421.jpg
<a href="链接地址" target="目标窗口">文本|图片</a>
目标窗口:
_self: 目标页面在当前窗口打开
_blank: 目标页面在新窗口中打开
如果是在页面具有frameset/frame/iframe的场景下:
_top: 在顶级窗口中打开
_parent: 在父级窗口中打开
_自定义名称: 在指定的特定窗口中打开
三种用法:
1. 页面间链接
<a href="page/login.html"></a>
2. 锚链接
<a href="#help"></a>
help是本页面中一处id为help的标签, 如: <p id="help">
或者:
help是通过a标签命名的锚记, 如: <a name="help"></a>
3. 功能性链接
唤醒本地安装的外部程序如 outlook/foxmail/qq/msn/aliwangwang...
<a href="mailto:abcdef@qq.com"></a>
div是一个容器, 常用于页面的布局
标签的分类:
1. 块级标签/块级元素
如: div, h1-h6, p, hr
特征: 独占容器中的一行, 其宽度是容器的100%
2. 行级标签/行级元素
如: span, img, strong, em, a
特征1: 多个行级元素可以同处一行, 其宽度由内容来撑开(auto)
特征2: 大部分行级元素设置其width/height无效
ctrl + D : 删除当前行
ctrl + PgUp : 当前行上移
ctrl + PgDown : 当前行下移
ctrl + / : 注释 | 取消注释
ctrl + shift + F : 整理代码格式
ctrl + C : 复制当前行
ctrl + X : 剪切当前行
ctrl + V : 粘贴
ctrl + Z : 撤消上一步操作
ctrl + S : 保存当前文件
ctrl + shift + S : 保存项目中全部文件
ctrl + Enter : 在当前行的下方插入新行
ctrl + shift + Enter : 在当前行的上方插入新行
以上知识能做的效果图
部分效果
*请认真填写需求信息,我们会在24小时内与您取得联系。