这个也是参考别的大神的,今天翻到就拿出来了,反正用了蛮久了,现在也不知道是哪位大神的!
<!DOCTYPE html>
<html>
<head>
<meta charset="GBK">
<title></title>
<style>
* {
margin: 0px;
padding: 0px;
}
body {
margin: 20px;
font-family: Arial, "宋体";
font-size: 12px;
line-height: 20px;
color: #333333;
}
</style>
</head>
<body>
<div id="app">
<input type='text' v-model='content'>
<p a=1>aaa</p>
<p b='222'>bbb</p>
</div>
</body>
<script src="vue.js"></script>
<script>
//自行结束标签
var empty = makeMap('area,base,basefont,br,col,embed,frame,hr,img,' +
'input,isindex,keygen,link,meta,param,source,track,wbr');
function makeMap (values) {
values = values.split(/,/);
var map = {};
values.forEach(function (value) {
map[value] = 1;
});
return function (value) {
return map[value.toLowerCase()] === 1;
};
}
function parse(template){
var root;//根节点
var currentParent;//当前父节点
var stack = [];//节点栈
if(!template) return ;
parseHtml(template,{
start:function(tagName,attrs,unary){
//元素节点
var element={
nodeType:1,
tagName:tagName,
attrs:attrs,
children:[],
parent:''
}
//如果是第一次进来
if(!root){
root = element;
}
if(currentParent){
//添加子节点,并建立parent对应关系
element.parent=currentParent
currentParent.children.push(element);
}
if (!unary) {//如果不是自行结束标签
currentParent = element;
stack.push(element)
}
},
end:function(){//处理结束标签
stack.length -=1;
currentParent=stack[stack.length-1]
},
chars:function(text){//处理文字
if(!currentParent){
return;
}
var children = currentParent.children;
children.push({
nodeType:3,
nodeValue:text,
textContent:text
})
},
comment:function (text) {// 处理注释
if(!currentParent){
return;
}
var children = currentParent.children;
children.push({
nodeType:8,
nodeValue:text,
textContent:text
})
}
})
return root ;
}
function parseHtml(template,options){
// 开始标签头
var startTagOpen = /^<([\w\-]+)/,
// 开始标签尾
startTagClose = /^\s*(\/?)>/,
// 标签属性
attribute = /^\s*([^\s"'<>\/=]+)(?:\s*((?:=))\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/,
// 结束标签
endTag = /^<\/([\w\-]+)>/;
var html = template;
var tagStack = []; // 标签栈
var index = 0;
while(html){
var text;
start = html.indexOf('<');
if(start===0){
//处理注释 <!-- -->
var commentMatch = parseCommentsTag();
if(commentMatch){
if(options.comment){
options.comment(commentMatch);
}
continue;
}
// 匹配起始标签
var startTagMatch = parseStartTag(); //处理后得到match
if(startTagMatch){
handleStartTag(startTagMatch);
continue;
}
// 匹配结束标签
var endTagMatch = html.match(endTag);
if (endTagMatch) {
var curIndex = index;
advance(endTagMatch[0].length);
parseEndTag(endTagMatch[1], curIndex, index);
continue;
}
}else if(start>=0){//前面有文本
text = html.slice(0,start);
advance(start);
}else{//没有匹配到< 是纯文本
text = html;
html = '';//直接字符串置空结束循环
}
if(options.chars && text){
options.chars(text);
}
}
function advance(n){//字符串的截取
index += n;
html = html.substring(n);
}
//处理注释标签
function parseCommentsTag(){
var text;
var start = html.indexOf("<!--");
if(start===0){
var end = html.indexOf("-->");
if(end>4){
text = html.substring(start+4,end);
advance(end+3);
}else{
throw new Error('注释节点有误,请检查!');
}
}
return text;
}
function parseStartTag(){
var start = html.match(startTagOpen); // 正则匹配
if(start){
var match = {
tagName:start[1],
attrs:[],
start:index
}
advance(start[0].length)
}
var end,attr;
//当没有遇到结束标签,并且属性标签一直被匹配,这里就是处理属性内容,匹配到一个属性就处理一个
while(!(end = html.match(startTagClose)) &&(attr = html.match(attribute)) ){
advance(attr[0].length);
match.attrs.push(attr);
}
//封装结束标签内容
if(end){
advance(end[0].length);
match.end = index;
return match
}
}
function handleStartTag(startTagMatch){
var tagName = startTagMatch.tagName;
var attrs=[];
var matchAttrs = startTagMatch.attrs;
var len =attrs.length=matchAttrs.length,i=0;
for(i;i<len;i++){
attrs[i] = {
name:matchAttrs[i][1],
value:matchAttrs[i][3] || matchAttrs[i][4] || matchAttrs[i][5] || ''
}
}
var unary = empty(tagName);
// 不是自闭标签
if (!unary) {
tagStack.push({ tagName: tagName, attrs: attrs});
}
if(options.start){
options.start(tagName,attrs,unary);
}
}
function parseEndTag (tagName, start, end) {
var pos;
if (start == null) start = index;
if (end == null) end = index;
if(tagName){
pos = tagStack.length-1;
for(pos;pos>=0;pos--){
if(tagName===tagStack[pos].tagName){
break;
}
}
}else {
pos = 0;
}
if(pos>=0){
for(var i=tagStack.length-1;i>=pos;i--){
if(options.end){
options.end(tagStack[i].tagName, start, end);
}
}
}
tagStack.length = pos;
}
}
var div=document.getElementById("app");
console.log(parse(div.outerHTML))
</script>
</html>
运行一下,就能把指定区域的html内容转换成语法树,很方便好用!