是否可以将 PHP 前端渲染到 Vue 节点中?
Posted
技术标签:
【中文标题】是否可以将 PHP 前端渲染到 Vue 节点中?【英文标题】:Is it possible to render a PHP frontend into a Vue node? 【发布时间】:2021-07-29 20:04:54 【问题描述】:我有一个旧的 php 应用程序,我想慢慢迁移到 Vue。 PHP 应用程序以相当复杂的方式呈现一堆 html 和 javascript 文件,即
foo.js.php
...
<script src="mysite.com/some_js_file.js" />
...
const a = '<?=$variable_from_php?>';
所以最终浏览器显然不知道这些js文件是如何构造的,但是可以运行它们。我想做的是从外层 Vue 应用程序请求 index
页面以获取旧版应用程序的某个子部分,并将其渲染到 Vue 节点,作为一种微前端。当我请求每个索引时,它当然会包含一个标题,其中包含该微前端需要运行的许多其他导入(脚本/样式)。所以,这个问题有两个部分:1)在 Vue.使用v-html
?框架? (请说没有 iframe)和 2)这种方法是否会出现任何安全问题(因为我基本上是说获取标头中的所有 JS 并运行它)。让我知道这个问题是否有意义。谢谢!
【问题讨论】:
是否可以使用H-include 或网络组件(如micro-frontends.org)? 您是否尝试将 PHP 动态生成的 HTML 渲染为 Vue 模板?或者您想在现有 PHP 生成的内容旁边添加新的 Vue 内容? @ssc-hrep3 第一个,从 PHP 动态生成的 HTML。然而,就迁移而言,我想基本上只是盲目地将 Vue 组件的内容设置为这个 HTML,然后不再为它烦恼,因为它可以完全管理自己。 没有很好的解决方案。脚本不由 v-html、innerHTML 或类似的处理。它们的元素应使用document.createElement("script")
显式创建。开箱即用的 jQuery html
支持此功能,如有必要,请使用它。即使处理了脚本,它们也不会以与原始页面相同的顺序进行评估,因为它们是以这种方式异步加载的。而且即使可行,Vue 应用也不应该是 SPA,因为您无法在页面之间进行适当的清理,会出现错误和内存泄漏。
安全性由旧版应用决定。结果不能比它更容易受到攻击,但可能更容易受到攻击,这取决于如何利用这些黑客攻击新应用程序。就安全性和常识而言,iframe 是这里唯一直接的方式。
【参考方案1】:
Vue.js 可以以两种不同的方式使用:对于更复杂的应用程序,您将使用构建过程并从源代码预编译模板,这些模板通常是单文件组件 SFC; *.vue 文件。然后模板将成为渲染函数,并且没有 HTML 最终出现在输出资产中。然而,还有另一种定义 Vue 组件的方法。您可以使用仅运行时的 Vue 包内联定义它们。对于迁移和较小的应用程序,建议使用这种方法。您需要包含编译器。另请参阅有关该主题的 Vue 文档 Vue v2 和 Vue v3)。如果您将 Vue 作为模块导入并且缺少编译器,请参阅 here。
如果您想将 PHP 动态生成的 HTML 渲染为 Vue 模板,则需要第二种方法。请记住,使用这种方法,您始终需要使生成的 PHP 输出与 Vue 组件同步。并且您需要完全信任您使用 PHP 生成的 HTML,否则您将面临注入风险。
然而,还有另一个问题:您需要将生成的 PHP 输出 HTML 作为 JavaScript 中的字符串,并且不应被浏览器解释(理想情况下)或再次从 DOM 中删除。因此,您需要(根据您的项目)决定如何生成 HTML,以便可以将其作为 JavaScript 字符串读取。以下是一些方法:
-
将 HTML 直接生成到页面中。然后,定义您要定位的元素,使用
.innerHTML
获取 HTML 并从 HTML 中删除节点(缺点:您将渲染 HTML 两次,可能会产生短暂的视觉故障)。
通过 XHR 从单独的页面获取 HTML。您将直接将 HTML 作为字符串包含在响应中(参见例如fetch
)。
围绕生成的 HTML 内容渲染 <script type="text/x-template" id="static-html-content"></script>
。然后,您不需要将 HTML 作为字符串,您可以直接使用 id 作为参考(使用template: '#static-html-content'
)。见the documentation of X-Templates in Vue。
然后,您可以使用仅运行时版本的 Vue 并定义您的组件。这是一个活生生的例子:
const Counter =
// retrieve and add your template string here
template: `
<div class="counter">
This is a counter: counter
<button @click="counter++">Increase Counter</button>
</div>
`,
data: function()
return
counter: 0
;
const App =
components: Counter ,
template: `
<div class="app">
This is the app component.
<hr />
<counter />
</div>
`
;
new Vue(
el: '#element',
template: '<App />',
components: App
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="element"></div>
另一种方法是仅在具有v-html
属性的组件中呈现HTML 字符串。然而,这个解决方案的主要缺点是内容不是反应性的。您不能更改内部组件数据并期望模板对更改做出反应。因此,您错过了 Vue 的主要优势,但您并不仅限于与您的组件内部结构匹配的模板。
Vue 论坛也有类似的提问:link
【讨论】:
这是关于服务器渲染模板的一个很好的解释,但它没有解决问题的重点,即如何处理这些模板中的脚本。【参考方案2】:也许你需要:一个模块 php 或组件作为 template.php(php server)
export const templateOfAdvanceTemplatePage = `
<div class="content edit-page management">
<md-card class="page-card">
<?php echo "My Component" ?>
</md-card>
</div>
从节点服务器
import * as url from "url";
var templateOfAdvanceTemplatePage = url.parse("http://www.website.com/template.php");
export default
template: templateOfAdvanceTemplatePage,
...
更多信息导入vue here, php 为javascript file here
【讨论】:
以上是关于是否可以将 PHP 前端渲染到 Vue 节点中?的主要内容,如果未能解决你的问题,请参考以下文章