把 vue 组件转换为任何 web 类模板
Transfer vue file to any language code.
vnode
而非string
+ vue
文件内的依赖需要转化).vue
组件 => vue-template-compiler
=> ssrRender
ssrRender
=> esprima
=> js-ast
js-ast
=> estraverse(各种替换/解析处理)
=> result-js-ast
result-js-ast
=> escodegen
=> result-ssrRender
result-ssrRender
=> vue-server-rander
=> html-php-code
html-php-code
中无法解析的 vnode(component)
=> html-php-code
核心问题:
相关工具:
相关资料:
AST三板斧:
esprima文档: http://esprima.readthedocs.io/en/latest/getting-started.html#using-node-js-to-play-with-esprima http://www.cnblogs.com/ziyunfei/p/3183325.html http://blog.csdn.net/dear_mr/article/details/72587908
已有实践:
解决痛点:通过专业的语法解析工具,避免了单薄可用性低的正则匹配,且可以根据不同的(ES默认方)法来定制转译后的 PHP 方法,以支持 PHP 基本方法的使用,可以参考 js2php
npm i vue-to-any --save
const VueToAny = require('vue-to-any')
// 实例化(options部分可选)
const vueToAny = new VueToAny({
// 目标语言(default: php)
language: 'php',
// 转译使用的服务端通讯字段,无需$等特殊符(default: PHPDATA)
variable: 'PHPDATA',
// 文件是否压缩后输出(default: false)
minify: false,
// 是否展示调试信息
debug: false,
// 是否输出进度
progress: true,
// 分别为 [ 入口/出口 ] 文件的 [ 路径和文件名字 ](必须指定,默认指向开发文件夹)
entryFile: path.join(__dirname, '/..', '/test', '/vue/', 'Test.vue'),
outFile: path.join(__dirname, '/..', '/test', '/out/', 'test.php')
})
// 执行转换输出转换
vueToAny.generate()
console.log(vueToAny)
// 插件/中间件(可选),方便分别对 [ 转译前/后 ] 的数据进行中间处理
// 处理转译前的 [ ssrRender ] 数据
vueToAny.useMiddleware('before', ssrRender => {
return ssrRender
})
// 处理转译后的 [ targetLangCode ] 数据
vueToAny.useMiddleware('after', resultTemplate => {
return resultTemplate
})
// 移除指定中间件(注意:如果要想移除指定某个中间件,则之前 use 时需要传入函数名字,而不是一个匿名函数实体)
vueToAny.delMiddleware('after', oldAfterMiddleware)
// 移除所有编译后中间件
vueToAny.delMiddleware('after')
// 移除所有中间件
vueToAny.delMiddleware()
// 添加不同语言版本的转译器(参考:transfers/php.js)
vueToAny.addTransfer({
'ejs': ejsTransfer
})
// 设置使用哪个语言版本进行工作
vueToAny.setTransfer('ejs')
// 更新实例配置对象
vueToAny.updateOptions({ ...newOptions })
window
对象的js文件或库import
语句引入 .vue
结尾的相对路径require
语句config
的block
,以json
的形式配置路径假设以SERVERDATA
字段为约定字段:
<div v-text="parseMethod(SERVERDATA.xxx.content)"></div>
<div>{{ SERVERDATA.xxx.content + '222' }}</div>
<img class="php-img" :src="SERVERDATA.imgSrc || '22'" alt="a image">
<img class="php-img" :src="SERVERDATA.imgSrc ? SERVERDATA.imgSrc : localImage">
<ul>
<li class="item" v-for="(item, key) in SERVERDATA.arr.filter(a => !!a.id)">
<div>{{ item.abc + 'string' }}</div>
</li>
</ul>
trnasfer="group"
<div>{{ SERVERDATA.name }}</div>
<input type="text" v-model="SERVERDATA.name.model">
<div v-text="SERVERDATA.arr.content"></div>
<div v-html="SERVERDATA.arr.xxx"></div>
<div v-show="SERVERDATA.isShow">show</div>
<div v-if="SERVERDATA.isRender">show</div>
<div v-else-if="SERVERDATA.isRenderElse">show</div>
<div v-else>not show</div>
<div class="static-class" :class="{
active: SERVERDATA.active, first: localData
}"></div>
<div class="static-class" :class="[
SERVERDATA.active ? 'active': '', 'static-class', localFitst ? 'first' : ''
]"></div>
<div class="static-class" :style="{
background: SERVERDATA.bg,
fontSize: localData.fontSize
}"></div>
<ul>
<li class="item" v-for="item in SERVERDATA.arr">
<div>{{ item.abc }}string</div>
</li>
</ul>
<ul>
<li class="item" v-for="(item, key) in SERVERDATA.arr">
<div>{{ item.abc }} - {{ key }}</div>
<div>嵌套循环</div>
<div v-for="children in item.childrens">
{{ children.name }}
</div>
</div>
</li>
</ul>
# 安装依赖
npm install
# 进入开发模式
npm run dev
# 构建
npm run build
# 测试脚本
npm run test
nuxt.js-blog/
|
├──src/ * 主程序
│ │
│ │──index.js * 核心类
│ │
│ └──transfers * 不同语言的转译器方法
│ │
│ └──solution(render-ast) * 核心解决方案
│ │
│ │──build.js * vue-server-render 的衍生版
│ │
│ │──parses.js * 对 ast 函数的匹配和替换
│ │
│ └──generate.js * ast 抽象 + vm 创建 / 文件分析 / 依赖分析 / 转换执行
│
│──test/ * 测试用的文件
│ │
│ ├──dev.js * 开发脚本
│ │
│ └──test.js * 测试脚本
│ │
│ ├──vue * 用于测试/开发的 vue 组件
│ │
│ └──out * 测试/开发输出的 php 脚本
│
│──package.json * 包信息
│
│──.babelrc * Babel配置
│
│──.gitignore * Git忽略文件配置
│
└──.editorconfig * 编码风格配置