1、修改源代码
在输出结果中赋值compiled.ast
即在createCompileToFunction函数返回的函数compileToFunctions中添加
function createCompileToFunctionFn(compile) {
var cache = Object.create(null);
return function compileToFunctions(template, options, vm) {
options = extend({}, options);
var warn = options.warn || warn$2;
delete options.warn;
/* istanbul ignore if */
{
// detect possible CSP restriction
try {
new Function('return 1');
}
catch (e) {
if (e.toString().match(/unsafe-eval|CSP/)) {
warn('It seems you are using the standalone build of Vue.js in an ' +
'environment with Content Security Policy that prohibits unsafe-eval. ' +
'The template compiler cannot work in this environment. Consider ' +
'relaxing the policy to allow unsafe-eval or pre-compiling your ' +
'templates into render functions.');
}
}
}
// check cache
var key = options.delimiters
? String(options.delimiters) + template
: template;
if (cache[key]) {
return cache[key];
}
// compile
var compiled = compile(template, options);
// check compilation errors/tips
{
if (compiled.errors && compiled.errors.length) {
if (options.outputSourceRange) {
compiled.errors.forEach(function (e) {
warn("Error compiling template:\n\n".concat(e.msg, "\n\n") +
generateCodeFrame(template, e.start, e.end), vm);
});
}
else {
warn("Error compiling template:\n\n".concat(template, "\n\n") +
compiled.errors.map(function (e) { return "- ".concat(e); }).join('\n') +
'\n', vm);
}
}
if (compiled.tips && compiled.tips.length) {
if (options.outputSourceRange) {
compiled.tips.forEach(function (e) { return tip(e.msg, vm); });
}
else {
compiled.tips.forEach(function (msg) { return tip(msg, vm); });
}
}
}
// turn code into functions
var res = {};
var fnGenErrors = [];
res.render = createFunction(compiled.render, fnGenErrors);
res.ast = compiled.ast;
res.staticRenderFns = compiled.staticRenderFns.map(function (code) {
return createFunction(code, fnGenErrors);
});
// check function generation errors.
// this should only happen if there is a bug in the compiler itself.
// mostly for codegen development use
/* istanbul ignore if */
{
if ((!compiled.errors || !compiled.errors.length) && fnGenErrors.length) {
warn("Failed to generate render function:\n\n" +
fnGenErrors
.map(function (_a) {
var err = _a.err, code = _a.code;
return "".concat(err.toString(), " in\n\n").concat(code, "\n");
})
.join('\n'), vm);
}
}
return (cache[key] = res);
};
}
详细代码参考:
https://github.com/wuli2496/OJ/blob/master/vue/vue.js
2、在浏览器控制台上用json输出ast
由于ast中的parent会存在循环依赖问题,如果需要输出json形式,可以使用如下代码:
var cache = [];
var str = JSON.stringify(result.ast, function(key, value) {
if (typeof value === 'object' && value !== null) {
if (cache.indexOf(value) !== -1) {
// Circular reference found, discard key
return;
}
// Store value in our collection
cache.push(value);
}
return value;
});
cache = null; // Enable garbage collection
其中result是调用Vue.compile(template)返回的结果
以template为例
<div id="app">
<ul>
<li v-for="book in books">{{book.name}}</li>
</ul>
</div>
输出结果为
{
"type":1,
"tag":"div",
"attrsList":[
{
"name":"id",
"value":"app"
}
],
"attrsMap":{
"id":"app"
},
"rawAttrsMap":{
},
"children":[
{
"type":1,
"tag":"ul",
"attrsList":[
],
"attrsMap":{
},
"rawAttrsMap":{
},
"children":[
{
"type":1,
"tag":"li",
"attrsList":[
],
"attrsMap":{
"v-for":"book in books"
},
"rawAttrsMap":{
},
"children":[
{
"type":2,
"expression":"_s(book.name)",
"tokens":[
{
"@binding":"book.name"
}
],
"text":"{{book.name}}",
"static":false
}
],
"for":"books",
"alias":"book",
"plain":true,
"static":false,
"staticRoot":false,
"forProcessed":true
}
],
"plain":true,
"static":false,
"staticRoot":false
}
],
"plain":false,
"attrs":[
{
"name":"id",
"value":"\"app\""
}
],
"static":false,
"staticRoot":false
}