是否可以将 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 应用程序以相当复杂的方式呈现一堆 htmljavascript 文件,即

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 内容渲染 &lt;script type="text/x-template" id="static-html-content"&gt;&lt;/script&gt;。然后,您不需要将 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 节点中?的主要内容,如果未能解决你的问题,请参考以下文章

Vue.js的模版渲染

vue常见面试题

VUE—数据渲染

前端渲染优化 - 大量数据展示

如何使用Vue2做服务端渲染

Mapbox大数据量渲染策略