Vue.js:在 Laravel 中实现 MPA(多页应用程序)的最佳方式
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/48240582/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Vue.js : Best way to implement MPA(Multi page app) in laravel
提问by Gammer
I have been looking around for quite a time, But didn't got anything convening.
我已经环顾了很长时间,但没有任何召集。
What will be the best approach and practice to implement Vue MPA architecture in laravel.
在 laravel 中实现 Vue MPA 架构的最佳方法和实践是什么?
Searched for quite a bit. But there isn't anything which will give you a clear idea. Your answer will help alot, Please make it brief.
搜了好久。但是没有任何东西可以让你有一个清晰的想法。你的回答会很有帮助,请尽量简短。
It will also be helpful to answer the point :
回答这一点也很有帮助:
- Is it a good idea to use just laravel as a data API, And keep Vue separate from laravel ?
- Best approach for implementing hybrid of SPA and MPA.
- 仅使用 laravel 作为数据 API 并保持 Vue 与 laravel 分开是个好主意吗?
- 实现 SPA 和 MPA 混合的最佳方法。
回答by Eduardo Stuart
Some options that I've already used:
我已经使用的一些选项:
Use Laravel to render the "main view" + connect vue.js application.
使用 Laravel 渲染“主视图”+连接 vue.js 应用程序。
Basically laravel will render the Vue application and every request goes throught an API.
基本上,laravel 将呈现 Vue 应用程序,并且每个请求都通过一个 API。
- Easy to setup
- Authentication + user validation is easier (you can use laravel session manager for that - don't need to build/use tokens or whatever. "No need to worry about your application state".)
- Easy to "disconnect" from Laravel - if you choose in the future to decouple the SPA application.
- 易于设置
- 身份验证 + 用户验证更容易(您可以使用 laravel 会话管理器 - 不需要构建/使用令牌或其他任何东西。“无需担心您的应用程序状态”。)
- 很容易从 Laravel 中“断开”——如果你将来选择解耦 SPA 应用程序。
Use laravel (or lumen) only as an API, and on another server render a SPA.
仅将 laravel(或 lumen)用作 API,并在另一台服务器上呈现 SPA。
This can take more time, since you'll need to setup an extra server, prepare cross-origin, etc.
这可能需要更多时间,因为您需要设置额外的服务器、准备跨域等。
- Also easy to setup, but can take more time than option #1
- You'll need to create something for user validation/state management, etc.
- Easy to place into laravel, if you decide in the future to use "only one app".
- Can be easier to maintain/scale (if you have a frontend team, they don't need to worry about laravel - same for your "laravel team", they "won't need to worry" about the frontend)
- 也易于设置,但可能比选项 #1 花费更多时间
- 您需要为用户验证/状态管理等创建一些东西。
- 如果您将来决定使用“仅一个应用程序”,则可以轻松放入 Laravel。
- 可以更容易维护/扩展(如果你有一个前端团队,他们不需要担心 Laravel - 对于你的“laravel 团队”也是如此,他们“不需要担心”前端)
Laravel + Vue = "one application"
Laravel + Vue = “一个应用程序”
You can use Laravel to render all views + vuejs for components/elements in the page.
您可以使用 Laravel 为页面中的组件/元素呈现所有视图 + vuejs。
- Easy to setup. You have laravel + vuejs, and they are already prepared to be used together. https://laravel.com/docs/5.5/frontend#writing-vue-components
- Not so easy to decouple. In this case you'll need to create the same views for vue.js. This can take time.
- This is the "traditional web development" (in my opinion). If I had to start a project like this today, I wouldn't create all pages in Vue.js + something in Laravel (Controller + new route) to render this view. If you do this (again - my opinion), it's just extra work. If you are worried about SEO, there are "fallbacks"/extra options.
- 易于设置。你有laravel + vuejs,它们已经准备好一起使用了。https://laravel.com/docs/5.5/frontend#writing-vue-components
- 没那么容易解耦。在这种情况下,您需要为 vue.js 创建相同的视图。这可能需要时间。
- 这就是“传统的网络开发”(在我看来)。如果我今天必须开始这样的项目,我不会在 Vue.js 中创建所有页面 + Laravel 中的某些内容(控制器 + 新路由)来呈现此视图。如果你这样做(再次 - 我的意见),这只是额外的工作。如果您担心 SEO,还有“后备”/额外选项。
--
——
All options are testable + scalable.
所有选项都是可测试的+可扩展的。
It also depends on how you start (Should I worry about how I'll decouple the app in the future? Laravel + Vue will be for good?), how your team will work (Does the frontend team really needs to setup laravel or they only need to worry about the frontend code?), etc.
这也取决于你如何开始(我是否应该担心我将来会如何解耦应用程序?Laravel + Vue 会永远好吗?),你的团队将如何工作(前端团队是否真的需要设置 Laravel 或他们只需要担心前端代码?)等。
Not sure if i answered your question, if not, please leave a comment.
不确定我是否回答了您的问题,如果没有,请发表评论。
回答by Shafiq al-Shaar
You haven't found anything clear because there isn't really anything to talk about other than 'What feels right to your understanding and project needs'. If you found yourself veryunsure, feel free to dive into doing whatever makes sense to you and then re-adjust the structure when you gain more experience.
您没有找到任何明确的内容,因为除了“您的理解和项目需求感觉如何”之外,实际上没有什么可谈的。如果您发现自己非常不确定,请随时投入到对您有意义的事情中,然后在获得更多经验后重新调整结构。
Also, read books about system architecture, those will help a lot.
另外,阅读有关系统架构的书籍,这些会很有帮助。
Is it a good idea to use just laravel as a data API, And keep Vue separate from Laravel?
仅使用 Laravel 作为数据 API 并保持 Vue 与 Laravel 分开是个好主意吗?
By this, I'm assuming you mean a SPA? Honestly, if your application is small, then I see this is fine.
通过这个,我假设你的意思是SPA?老实说,如果您的应用程序很小,那么我认为这很好。
Larger applications tend to be difficult to maintain if they were SPA.
如果是 SPA,较大的应用程序往往难以维护。
Read: https://medium.com/@NeotericEU/single-page-application-vs-multiple-page-application-2591588efe58
阅读:https: //medium.com/@NeotericEU/single-page-application-vs-multiple-page-application-2591588efe58
If you end up using Laravel as an API endpoint, then use the stripped down version of it, Lumen, because it comes without Blade and few other stuff. Lumen is stripped down version to act as an API-endpoint.
如果您最终使用 Laravel 作为 API 端点,那么请使用它的精简版本Lumen,因为它没有 Blade 和其他一些东西。Lumen 是精简版以充当 API 端点。
Best approach for implementing hybrid of SPA and MPA.
实现 SPA 和 MPA 混合的最佳方法。
From my experience having attempted to build 4+ projects as hybrids, here's what I found the most optimal structure:
根据我尝试将 4 个以上项目构建为混合项目的经验,这是我发现的最佳结构:
My example will be about an app that saves 'Posts'.
我的例子是关于一个保存“帖子”的应用程序。
1. Use a repository design pattern.
1. 使用存储库设计模式。
This one will save you a lot of headache in maintaining your code and maintain a DRY (Don't Repeat Yourself) concept on your code.
这将为您在维护代码和维护代码的 DRY(不要重复自己)概念方面省去很多麻烦。
- Create a directory
App\Repositories\
- 创建目录
App\Repositories\
Make a new class PostsRepository
. This one will be the one communicating with the database and contains most of the logic.
创建一个新类PostsRepository
。这将是与数据库通信并包含大部分逻辑的那个。
- Create the directory
App\Services\
- 创建目录
App\Services\
Make a new class PostsService
. This one will have the PostsRepository
in its constructor.
创建一个新类PostsService
。这个将PostsRepository
在其构造函数中包含 。
The service class will be one handling taking user's input whether from the Web controller or the API controller.
服务类将是一种处理从 Web 控制器或 API 控制器获取用户输入的方法。
<?php
namespace App\Service;
use App\Repositories\PostsRepository;
class PostsService;
{
protected $repository;
public function __construct(PostsRepository $repository)
{
$this->repository = $repository;
}
}
- Make a seperation between Web and API controllers.
- 将 Web 和 API 控制器分开。
For web controllers, you create the controller like usual:
对于 Web 控制器,您可以像往常一样创建控制器:
php artisan make:controller PostsController
php artisan make:controller PostsController
For API controllers, you create the controller to be inside an Api folder.
对于 API 控制器,您可以在 Api 文件夹中创建控制器。
php artisan make:controller Api\PostsController
php artisan make:controller Api\PostsController
The last command will create the directory App\Http\Controllers\Api and have the controller be placed in it.
最后一个命令将创建目录 App\Http\Controllers\Api 并将控制器放置在其中。
Recapping
回顾
Now we have different controllers to return results appropriate to the startpoint (web / api).
现在我们有不同的控制器来返回适合起点(web / api)的结果。
We have services that both the (web / api) controllers send their data to be validated (and have the action taken by the repository).
我们有服务,(web / api)控制器发送他们的数据进行验证(并让存储库采取行动)。
Examples:
例子:
<?php
namespace App\Http\Controllers;
use App\Service\PostsService;
class PostsController extends Controller
{
protected $service;
public function __construct(PostsService $service)
{
$this->service = $service;
}
public function index()
{
/**
* Instead of returning a Blade view and
* sending the data to it like:
*
* $posts = $this->service->all();
* return views('posts.index', compact('posts'));
*
* We go ahead and just return the boilerplate of
* our posts page (Blade).
*/
return view('posts.index');
}
}
...
...
<?php
namespace App\Http\Controllers\Api;
use App\Service\PostsService;
class PostsController extends Controller
{
protected $service;
public function __construct(PostsService $service)
{
$this->service = $service;
}
/**
* Returns all posts.
*
* A vue component calls this action via a route.
*/
public function index()
{
$posts = $this->service->all();
return $posts;
}
/**
* Notice we don't have a store() in our
* Web controller.
*/
public function store()
{
return $this->service->store();
}
}
...
...
<?php
namespace App\Services;
use App\Repositories\PostsRepository;
class PostsService extends Controller
{
protected $repository;
public function __construct(PostsRepository $repository)
{
$this->repository = $repository;
}
public function all()
{
$posts = $this->repository->all();
return $posts;
}
public function store()
{
$request = request()->except('_token');
$this->validation($request)->validate();
return $this->repository->store($request);
}
public function validation(array $data)
{
return Validator::make($data, [
'content' => 'required|string|max:255',
//
]);
}
}
In our PostsRepository we actually call methods that save the data. E.g. Post::insert($request);
.
在我们的 PostsRepository 中,我们实际上调用了保存数据的方法。例如Post::insert($request);
。
2. Dedicate an API group
2. 专属API群
Route::prefix('api/v1')->middleware('auth')->group(function() {
Route::post('posts/store', 'Api\PostsController@store')->name('api.posts.store');
});
Giving API routes a ->name()
helps when you make phpunit tests.
->name()
当您进行 phpunit 测试时,为API 路由提供帮助。
3. Blade views
3. 刀片视图
Those are ought to be stripped-down simple.
这些应该是精简的简单。
views/posts/index.blade.php
:
views/posts/index.blade.php
:
@extends('layouts.app', ['title' => trans('words.posts')])
@section('content')
<!-- Your usual grid columns and stuff -->
<div class="columns">
<div class="column is-6">
<!-- This comp. can have a modal included. -->
<new-post-button></new-post-button>
<div class="column is-6">
<posts-index-page></posts-index-page>
</div>
</div>
@endsection
4. Vue structure.
4.vue结构。
https://github.com/pablohpsilva/vuejs-component-style-guide
https://github.com/pablohpsilva/vuejs-component-style-guide
So those Vue components might live in resources/assets/js/components/posts/
where inside /posts/
I'd have folders titled for example IndexPage
, CreateModal
, EditModal
with each folder having its .vue
and README.md
.
因此,那些 Vue 组件可能resources/assets/js/components/posts/
位于/posts/
我内部的文件夹中,例如IndexPage
,标题为, CreateModal
,EditModal
每个文件夹都有其.vue
和README.md
。
I'd use the <posts-index-page>
in index.blade.php
and drop in the <post-create-modal>
and <edit-post-modal>
whenever I want.
我会用<posts-index-page>
在index.blade.php
和在下降<post-create-modal>
和<edit-post-modal>
每当我想要的。
All the vue components will use the API endpoint we specified in our Routes file.
所有 vue 组件都将使用我们在 Routes 文件中指定的 API 端点。