例如:下图所示:
依次识别获取.js文件中的tag和props,可以理解为字符串拼接,将整个vue的标签结构看作是一个字符串。
话不多说,先放上完整代码,思路看代码备注。(自己实现的时候,可以先把tag标签,即vue结构弄出来,后续再加上props属性,这样思路会更加清晰)
实现方法:
首先想到的是利用递归,一点一点的拼接字符串,因为.js文件到底多大是不确定的。
data() {
return {
previewContent: '',
suojinStr: ''// 获取缩进字符
}
},
methods: {
handlePreview() {
var jsdata = require('../../../public/js/bbb.js') //获取文件
this.obtainData(jsdata.default) //调用递归方法
this.previewContent = '<template>' + this.previewContent + '\n' + '</template>'
},
obtainData(data) {
var children = data.children
if (children) {
this.suojinStr += '\t'
for (var i = 0; i < children.length; i++) {
// 拼接字符串:换行符+缩进+开始标签
this.previewContent += '\n' + this.suojinStr + '<' + children[i].tag + '>'
// 获取props相关数据---放在开始标签的里面--比开始标签在往里缩进一格
if (children[i].props !== undefined) {
for (var key in children[i].props) {
// 拼接字符串:换行符+缩进+(再一格缩进)+props的内容
this.previewContent += '\n' + this.suojinStr + '\t' + key + '=' + '"' + children[i].props[key] + '"'
}
}
// 调用自身,递归---挖掘孩子节点,一层一层拼接
this.obtainData(children[i])
// 拼接字符串:换行符+缩进+结束标签---当没有孩子时,闭合标签
this.previewContent += '\n' + this.suojinStr + '</' + children[i].tag + '>'
}
// 结束标签的空格回退---父亲的结束标签和和父亲的开始标签对齐,所以等没有孩子时,回退一格缩进
this.suojinStr = this.suojinStr.substr(1)
}
}
}
后面,和Sweny-blog讨论了一下,发现她的字符串是整个拼接起来的,不像我拼接的这么零碎。然后我也尝试了一下拼接完整版。
methods: {
handlePreview() {
var jsdata = require('../../../public/js/bbb.js')
this.previewContent = this.obtainData1(jsdata.default)
this.previewContent = '<template>' + this.previewContent + '\n' + '</template>'
},
obtainData1(data) {
// 换行+缩进+首标签+递归(找孩子)+换行+缩进+尾标签
var previewContent = ''
var children = data.children
if (children) {
this.suojinStr += '\t'
for (var i = 0; i < children.length; i++) {
// 获取props属性的值---这块可以写成一个函数,后面完整拼接的时候,直接调用就行了
var propsStr = ''
if (children[i].props !== undefined) {
for (var key in children[i].props) {
propsStr += '\n' + this.suojinStr + '\t' + key + '=' + '"' + children[i].props[key] + '"'
}
}
// 完整的拼接
previewContent += '\n' + this.suojinStr + '<' + children[i].tag + '>' + propsStr + this.obtainData1(children[i]) + '\n' + this.suojinStr + '</' + children[i].tag + '>'
}
// 结束标签的空格回退
this.suojinStr = this.suojinStr.substr(1)
}
return previewContent
},
}
这里面用到了previewContent这个局部变量进行拼接
为什么要使用局部变量?不像之前使用全局变量?
因为,拼接字符串中,调用了this.obtainData1(children[i])获取孩子拼接的字符串。若是全局变量,没有清空的过程,它会累加多余的字符。这里涉及到的知识点是变量作用域。
下面简单写个相似的递归:
function test1(num){
var str = ''
console.log('外面的str:'+ str)
num++
if(num<5){
str+='a'+test1(num)
console.log('if里面的str:'+ str)
}
return str;
}
test1(0);
依次输出:
递归的过程是一层一层调用函数,每调用一个函数,又重新声明赋值了变量str,这就相当于子函数重新生成了一个同名变量,操作的是自己的变量。这个return str,是每次递归调用子函数,子函数返回的字符串,一层一层的累加。
其实相当于:先走到最内层,然后从最内层一层一层往外加str。
再看一个var变量作用域的示例:
var a = 1
function test4(){
var a= 2;
console.log(a)
}
console.log(a) // 输出:1
test4(); // 输出:2
console.log(a) // 输出:1
若是还不懂,之前发过一篇博客JS中变量(var、let、const)的声明提升和作用域梳理专门讲作用域的,可以看看。