ZetCode

Symfony Vue

最后修改于 2020 年 7 月 5 日

Symfony Vue 教程展示了如何使用 Vue 前端创建一个简单的 Symfony 应用程序。

Symfony

Symfony 是一组可重用的 PHP 组件和一个用于 Web 项目的 PHP 框架。Symfony 于 2005 年以自由软件的形式发布。Symfony 的灵感来自 Ruby on Rails、Django 和 Spring 框架。

Symfony Encore 是一个 JavaScript 库,用于管理 Symfony 应用程序中的 CSS 和 JavaScript。Encore 使在 Symfony 应用程序中集成 Webpack 更加容易。它封装了 Webpack,为我们提供了干净强大的 API,用于打包 JavaScript 模块、预处理 CSS 和 JavaScript,以及编译和最小化资源。

Vue

Vue 是一个开源的 JavaScript 框架,用于构建用户界面和单页面应用程序。它是 Angular 和 React 的替代品。

Symfony Vue 示例

在下面的示例中,我们创建了一个将数据发送到模板的简单 Symfony 应用程序。数据由 Vue 处理并在组件中显示。

除了 PHP,我们还需要安装 Node.js。请参阅 ZetCode 的 Node.js 教程了解更多详情。

设置项目

我们演示如何使用 Vue 设置 Symfony。

$ symfony new symvue

使用 symfony CLI,我们创建一个新的 Symfony skeleton 项目。

$ cd symvue

我们进入项目目录。

$ composer require maker --dev

此外,我们安装了 maker 组件。maker 包提供了脚手架。

$ composer req annot twig

我们安装用于处理注解和模板的组件。

$ composer require encore
$ npm install

我们安装了 Symfony Encore。这将安装并启用 WebpackEncoreBundle,添加 assets 目录,创建 webpack.config.js 文件,并将 node_modules 添加到 .gitignore

$ npm i vue vue-loader vue-template-compiler

我们安装了 Vue 及其库。

项目文件

我们展示重要的项目文件。

webpack.config.js
var Encore = require('@symfony/webpack-encore');

Encore
    .setOutputPath('public/build/')
    .setPublicPath('/build')

    .enableVueLoader()

    .addEntry('app', './assets/js/app.js')

    .splitEntryChunks()

    .enableSingleRuntimeChunk()

    .cleanupOutputBeforeBuild()
    .enableBuildNotifications()
    .enableSourceMaps(!Encore.isProduction())
    .enableVersioning(Encore.isProduction())

;

module.exports = Encore.getWebpackConfig();

webpack.config.js 文件中,我们启用了 Vue 加载器并设置了公共路径和构建路径。

assets/js/app.js
import Vue from 'vue';
import App from './components/App';
import '../css/app.css';

new Vue({
    el: '#app',
    render: h => h(App)
});

这是主要的 Vue 文件,用于启动 Vue。

Symfony 将 CSS 和 JavaScript 等静态文件存储在 assets 目录中。

assets/js/components/App.vue
<template>
  <div>
    <h2 class="center">My Application</h2>
    <div v-text="message"></div>
    {{ message }}
    <ul>
      <li :key="word.id" v-for="word in words">{{ word }}</li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: "A list of words",
      words: []
    };
  },
  mounted() {

    let el = document.querySelector("div[data-words]");
    let mywords = el.dataset.words.split(",");

    this.words.push.apply(this.words, mywords);
  }
};
</script>

<style>
.center {
  text-align: center;
}
</style>

这是 Vue 组件。Vue 应用程序由组件组成。一个组件由三个部分组成:模板、脚本和样式。

<div v-text="message"></div>
{{ message }}

在 Vue 中输出变量有两种方式;第二种与 Twig 完全相同。

<ul>
    <li :key="word.id" v-for="word in words">{{ word }}</li>
</ul>

使用 v-for 指令,我们遍历 words 数组并在列表项中显示每个元素。:key 指令帮助 Vue 渲染列表;它包含元素的 ID。

数据源自 Symfony Twig 模板;它由 JavaScript 处理,最后在 Vue 组件中使用 v-for 输出。

data() {
    return {
        message: "A list of words",
        words: []
    };
},

data() 函数中,我们初始化了一个 message 变量和一个 words 数组。

mounted() {

    let el = document.querySelector("div[data-words]");
    let mywords = el.dataset.words.split(",");

    this.words.push.apply(this.words, mywords);
}

words 数组在 mounted() 函数中填充数据,该函数解析元素数据集中的数据。它以字符串形式存储在那里;我们将字符串分割成单词。数据插入在 Symfony 的 Twig 模板内的 dataset 中。

assets/css/app.css
body {
    background-color: lightgray;
}

我们在 app.css 中包含了一些基本的 CSS。

$ php bin/console make:controller HomeController

HomeController 是使用 Symfony maker 创建的。

src/Controller/HomeController.php
<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;

class HomeController extends AbstractController
{
    /**
     * @Route("/home", name="home")
     */
    public function index()
    {
        $words = ['sky', 'cloud', 'wood', 'rock', 'forest',
            'mountain', 'breeze'];

        return $this->render('home/index.html.twig', [
            'words' => $words
        ]);
    }
}

控制器方法将单词列表发送到客户端。

return $this->render('home/index.html.twig', [
    'words' => $words
]);

我们渲染 index.html.twig 模板,并将单词发送给它。

templates/home/index.html.twig
{% extends 'base.html.twig' %}

{% block title %}Home page{% endblock %}

{% block body %}

<div ref="words" data-words="{{ words|join(',') }}">

</div>

<div id="app">
    <app></app>
</div>
{% endblock %}

在模板中,我们将 words 数组添加到 data-words 属性。数组使用 Twig join 过滤器连接成一个字符串。HTMLElement 接口上的 dataset 属性提供了对元素上设置的所有自定义数据属性(data-*)的读/写访问。

<div id="app">
    <app></app>
</div>

这是主 Vue 组件的入口点。

templates/base.html.twig
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>{% block title %}Welcome!{% endblock %}</title>
        {% block stylesheets %}
            {{ encore_entry_link_tags('app') }}
        {% endblock %}
    </head>
    <body>

        {% block body %}{% endblock %}

        {% block javascripts %}
            {{ encore_entry_script_tags('app') }}
        {% endblock %}
    </body>
</html>

这是基础模板文件。

{{ encore_entry_link_tags('app') }}

CSS 文件通过 encore_entry_link_tags 加载。

{{ encore_entry_script_tags('app') }}

JavaScript 文件通过 encore_entry_script_tags 加载。

构建资源

我们需要构建资源。

$ npm run dev

对于开发环境,资源使用 npm run dev 命令构建。

运行应用程序

我们启动开发服务器并访问应用程序页面。

$ symfony serve

我们启动开发服务器。然后我们访问 localhost:8000/home 页面。

在本教程中,我们创建了一个在其前端使用 Vue 的 Symfony 应用程序。

查看所有 Symfony 教程