sokil / frontend-bundle
前端组件,用于快速启动前端应用程序
Requires
- php: ^5.6 || ^7.0
- friendsofsymfony/rest-bundle: ~1.7 || ~2.0
- symfony/framework-bundle: 2.*
Requires (Dev)
- phpunit/phpunit: 5.4.*
- satooshi/php-coveralls: 0.7.*
Suggests
- sokil/deploy-bundle: Deploy symfony2 apps
README
基于 Backbone、Marionette 和 Twitter Bootstrap 的单页面应用程序
安装
添加 composer 依赖项
composer require sokil/frontend-bundle
将捆绑包添加到 AppKernel
<?php class AppKernel extends Kernel { public function registerBundles() { $bundles = array( new Sokil\FrontendBundle\FrontendBundle(), ); } }
构建资源
bower install
npm install
grunt
捆绑包使用 assetic,因此您需要在 assetic 配置中注册它
assetic: bundles: - FrontendBundle
您可以使用 DeployBundle 来处理静态资源的部署过程。
控制器
单页面应用程序
我们可以配置一个预定义的控制器,负责渲染单页面应用程序,并将其作为服务
acme.spa.controller: class: Sokil\FrontendBundle\Controller\IndexController arguments: - 'AcmeBundle:Spa:index.html.twig' calls: - [setContainer, ["@service_container"]]
或使用您自己的控制器
<?php namespace Acme\SiteBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request; class SpaController extends Controller { public function indexAction(Request $request) { if (!$this->isGranted('IS_AUTHENTICATED_REMEMBERED')) { throw $this->createAccessDeniedException(); } // render response return $this->render('SiteBundle:Spa:index.html.twig', [ 'applicationData' => $this->get('acme.spa.app_data')->getData(), // optional appdata ]); } }
在下面的 视图部分 中查看如何配置 spa 的示例 SiteBundle:Spa:index.html.twig
。
如果需要将一些额外的数据从后端传递到前端,这可以通过 应用数据
完成。
应用数据
应用数据可以用来从后端传递一些数据到前端。创建一个服务,负责从不同来源获取应用数据
acme.spa.app_data: class: Sokil\FrontendBundle\Spa\ApplicationData
现在将此服务的名称传递给您的 spa 动作的定义
acme.spa.controller: class: Sokil\FrontendBundle\Controller\IndexController arguments: - 'AcmeBundle:Spa:index.html.twig' - '@acme.spa.app_data' calls: - [setContainer, ["@service_container"]]
应用数据来自多个提供者。提供者是一个服务,由标签 frontend.spa.app_data_provider
标识。此外,app 数据服务必须通过键 app_data
定义,指向应用数据服务的实例。
acme.spa.some_app_data_provider; class: Acme\Spa\SomeApplicationDataprovider tags: - {name: frontend.spa.app_data_provider, app_data: acme.spa.app_data}
提供者类必须实现 Sokil\FrontendBundle\Spa\ApplicationDataProviderInterface
。它必须实现一个方法 getData()
,该方法返回应用参数的映射。
模型
处理 JSON 请求
Backbone 模型发送 JSON 请求。
要启用支持,您可以添加 FOSRestBundle 并配置序列化器。 app/AppKernel.php
new FOS\RestBundle\FOSRestBundle(),
app/config/config.yml
:
framework: serializer: enabled: true enable_annotations: true
如果您不需要整个捆绑包,只需注册一个监听器,它将 JSON 请求转换为数组
services:
json_request_listener:
class: Sokil\FrontendBundle\EventListener\JsonRequestListener
tags:
- {name: kernel.event_listener, event: kernel.request, method: onKernelRequest, priority: -255 }
视图
模板
视图渲染 Marionette 2
应用程序并启动它。使用 Bootstrap 3
作为 UI 框架。要在页面上添加一些 CSS 和 JS 资源,请使用来自 src/Resources/views/macro.html.twig
的宏。
{% import "@FrontendBundle/Resources/views/macro.html.twig" as frontend %} <!DOCTYPE html> <html> <head> {{ frontend.commonCssResources() }} </head> <body> <div id="content"></div> <div id="popup"></div> </body> {{ frontend.commonJsResources() }} <script type="text/javascript"> (function() { // app options may be accessed through applicationData variable var options = {{ applicationData|json_encode|raw }}; // router may be passed as option options.router = [ AcmeRouter ]; // container with fromtend services may be passed as option options.serviceDefinition = [ AcmeServiceDefinition ]; // root element of SPA app // optional, `body` used by default options.root = 'body'; // requirejs options.requirejs = [ AcmeRequireJsConfig ] // regions of root app, optional options.regions = { content: '#content', // region for content of app popup: '#popup' // region for popup rendering } // start app window.app = new Application(options); window.app.start(); })(); </script> </html>
区域
应用程序指的是根视图 app.rootView
,该视图处理单页应用(SPA)的根元素。根元素可以在应用程序选项中配置,或者使用默认值 body
。根元素包含一些区域,其中渲染不同的功能。主要内容渲染到 app.rootView.content
区域,弹出窗口渲染到 app.rootView.popup
区域。您可以传递自己的区域,并通过 app.rootView
来引用它们。
路由器
路由器是 Backbone.Router
的实例。您还可以使用 Marionette.AppRouter
。
如果您有少量路由,您可以将它们全部传递到 routers
选项中。
window.app = new Application({ routers: [ Bundle1Router, Bundle2Router ] });
要设置默认路由,请使用 defaultRoute
选项。
var Bundle1Router = new Backbone.Router({ routes: { '/some/route': 'someRoute' }, someRoute: function() { // ... } }); window.app = new Application({ routers: [ Bundle1Router, Bundle2Router ], defaultRoute: [Bundle1Router, 'someRoute']; });
服务容器
容器是一个注册表,用于构建和获取已构建的服务。服务定义只是一个具有构建服务实例的方法的对象,其中 this
指向 Container
实例。
AcmeServiceDefinition = { someService: function() { return new SomeService(this.get('otherService')); }, otherService: function() { return new OtherService(); } }
通过 serviceDefinitions
配置参数传递给容器的定义。
options.serviceDefinitions = [ Bundle1ServiceDefinition, Bundle2ServiceDefinition ];
然后可以从容器中获取服务。
var someService = app.container.get('someService');
RequireJs
依赖项可以合并并传递到容器中。
options.requireJs = [ Bundle1RequireJsConfig, Bundle2RequireJsConfig ];
每个配置可能匹配一个或两个 path
和 shim
参数。
var Bundle1RequireJsConfig = { paths: { 'bundle1_tinymce': 'staticpage/js/tinymce/tinymce.min' }, shim: { 'bundle1_tinymce': { exports: 'tinymce' } } };
默认情况下,应用程序已经预先配置了 FrontendRequireJsConfig
。它有一些依赖项,例如 Twitter Typeahead。
前端组件
弹出窗口
弹出窗口必须扩展 PopupView
。
var MyPopupView = PopupView.extend({ events: { 'click .save': 'saveButtonClickListener' }, title: 'My Popup', buttons: [ {class: 'btn-primary save', title: 'Save'} ] }
列表
此组件允许生成模型的集合。
var SomeListView = ListView.extend({ showColumnHeader: true, // show table header /** * Defines list of columns * Array, or function that return array * @return {array} */ columns: function() { return [ { caption: app.t('SomeListView.some_column_name'), // column caption name: 'some_column_name' // column name }, ]; }, /** * Defines list of buttons, rendered in all rows * Array, or function that return array * @return {array} */ buttons: function() { return [ { name: 'edit', // button name class: 'btn btn-default btn-xs', // button class icon: 'glyphicon glyphicon-pencil', // button icon caption: app.t('SomeListView.edit'), // button cation click: function(e, itemId, view) { // click handler alert('edit'); } } ]; } });
多类型预测
包装 ListView
,并为列表添加添加新元素的类型预测功能。