Laravel+Vue コンポーネントに基づいて記事の公開、編集、閲覧機能を実装する方法を説明します。

藏色散人
リリース: 2020-11-13 14:08:50
転載
2898 人が閲覧しました


次のチュートリアル コラムでは、Laravel Vue コンポーネントに基づいて記事の公開、編集、閲覧機能を実装する方法を紹介します。必要な友人の助けになれば幸いです。

Laravel をベースとしたバックエンド インターフェイス、フロントエンド JavaScript コンポーネント開発フレームワークとして Vue.js、CSS フレームワークとして Bootstrap を提供します。

Laravel+Vue コンポーネントに基づいて記事の公開、編集、閲覧機能を実装する方法を説明します。Laravel バックエンド インターフェイス

まず、前のチュートリアルで作成したリソース コントローラーをベースにします。

PostController

バックエンドの追加、削除、変更、インターフェイス実装の確認を手早く作成します。コード:

<?php namespace App\Http\Controllers;

use App\Models\Post;
use Exception;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Auth;

class PostController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth')->except('index', 'all', 'show', 'data');
    }

    /**
     * Display a listing of the resource.
     *
     * @return Application|Factory|View|Response|\Illuminate\View\View
     */
    public function index()
    {
        return view('posts.index', ['pageTitle' => '文章列表页']);
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return Application|Factory|View|Response|\Illuminate\View\View
     */
    public function create()
    {
        return view('posts.create', ['pageTitle' => '发布新文章']);
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param Request $request
     * @return array
     */
    public function store(Request $request)
    {
        $data = $request->validate([
            'title' => 'required|max:128',
            'content' => 'required'
        ]);

        $post = new Post($data);
        $post->status = 1;
        $post->user_id = Auth::user()->id;
        if ($post->save()) {
            return ['success' => true, 'message' => '文章发布成功'];
        }
        return ['success' => false, 'message' => '保存文章数据失败'];
    }

    /**
     * Display the specified resource.
     *
     * @param Post $post
     * @return Application|Factory|View|Response|\Illuminate\View\View
     */
    public function show(Post $post)
    {
        return view('posts.show', ['id' => $post->id, 'pageTitle' => $post->title]);
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param Post $post
     * @return Application|Factory|View|Response|\Illuminate\View\View
     */
    public function edit(Post $post)
    {
        return view('posts.edit', ['pageTitle' => '编辑文章', 'id' => $post->id]);
    }

    /**
     * Update the specified resource in storage.
     *
     * @param Request $request
     * @param Post $post
     * @return array
     */
    public function update(Request $request, Post $post)
    {
        $data = $request->validate([
            'title' => 'required|max:128',
            'content' => 'required'
        ]);

        $post->fill($data);
        $post->status = 1;
        if ($post->save()) {
            return ['success' => true, 'message' => '文章更新成功'];
        }
        return ['success' => false, 'message' => '更新文章数据失败!'];
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param Post $post
     * @return array
     * @throws Exception
     */
    public function destroy(Post $post)
    {
        if ($post->delete()) {
            return ['success' => true, 'message' => '文章删除成功'];
        }
        return ['success' => false, 'message' => '删除文章失败'];
    }

    /**
     * 获取所有文章数据
     *
     * @return Collection
     */
    public function all()
    {
        return Post::orderByDesc('created_at')->get();
    }

    /**
     * 获取单个文章数据
     *
     * @param Post $post
     * @return Post
     */
    public function data(Post $post)
    {
        $post->author_name = $post->author->name;
        return $post;
    }
}
ログイン後にコピー

Laravel リソース コントローラーに付属のメソッドに加えて、記事の取得に使用される all

data

という 2 つの追加メソッドが提供されています。 Vue コンポーネントの AJAX リクエストを通じて、リスト データと記事の詳細データを取得します。したがって、リソース ルートをルーティング ファイル routes/web.php: <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">use App\Http\Controllers\PostController; Route::get('posts/all', [PostController::class, 'all']); Route::get('posts/{post}/data', [PostController::class, 'data']); Route::resource('posts', PostController::class);</pre><div class="contentsignin">ログイン後にコピー</div></div> に登録する前に、これら 2 つのメソッドに対応するルートを追加する必要があります。ここでは、提供されている暗黙的モデルを使用していることに注意してください。 Laravel ルーティングによるバインディング関数は、モデル インスタンスを迅速に取得します。さらに、対応するビュー テンプレート パスも調整されました。これらのビュー テンプレート ファイルについては、間もなく紹介します。 フィラーを使用してテスト データを入力します。

前のチュートリアルで入力したテスト データに基づいて他のデータを追加した場合は、

php Artisan Midnight:refresh## を実行できます。 # command データ テーブルを再構築して、既存のデータをすばやく消去して再充填します。

返されたインスタンス データ形式の詳細を表示したくない場合は、組み込みフィラー

database/seeders/DatabaseSeeder.php:

<?php namespace Database\Seeders;

use App\Models\Post;
use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application&#39;s database.
     *
     * @return void
     */
    public function run()
    {
        // \App\Models\User::factory(10)->create();
        Post::factory(10)->create();
    }
}
ログイン後にコピー
次に、

php Artisan Migrate:refresh --seed を実行します。このコマンドは、データ テーブルの再構築、テスト データのクリアと再充填を 1 つのステップで完了できます。

Laravel+Vue コンポーネントに基づいて記事の公開、編集、閲覧機能を実装する方法を説明します。テンプレート継承によるビュー テンプレートの再構築

Laravel+Vue コンポーネントに基づいて記事の公開、編集、閲覧機能を実装する方法を説明します。laravel/ui## によって提供される Bootstrap および Vue フロントエンド スキャフォールディング コードを使用しているため、 # Laravel が提供する拡張パッケージ、拡張パッケージもユーザー認証に関連するスキャフォールディング コード実装を提供し、ビュー テンプレート レイアウト ファイル

resources/views/layouts/app.blade.php

を提供します。テンプレート継承により、このレイアウト ファイルに基づいてリストが作成され、フォームと詳細ページに関連するビュー テンプレート ファイルにより、UI 全体が統一されます。

異なるページに異なるタイトルを設定する以前、PostController## のすべての GET ルートによってレンダリングされるビュー ファイル内の別のページとして pageTitle

値を渡しました。 # title。この関数を実装するには、

resources/views/layouts/app.blade.php

レイアウト ファイルの

title ラベルに対応するラベル テキスト値を変更する必要があります。 ##<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">&lt;title&gt;{{ $pageTitle ?? config('app.name', 'Laravel') }}&lt;/title&gt;</pre><div class="contentsignin">ログイン後にコピー</div></div>記事リスト ビュー次に、元の記事関連のビュー ファイルをすべて resources/views/posts ディレクトリに移動し、記事リスト ビュー ファイルのテンプレート コードを書き換えます。次のようにします (元の posts.blade.php

index.blade.php

に名前変更しました):

@extends('layouts.app')

@section('content')
    <p>
        <post-list></post-list>
    </p>
@endsection
ログイン後にコピー

公開後のビュー名前を変更します元の form.blade.php 名前を create.blade.php に変更し、フォーム ページ ビュー ファイルのテンプレート コードを公開する記事を次のように記述します。フォームの公開と編集は Vue フォーム コンポーネントを共有するため、ここではフォーム タイトル (

title

)、アクション タイプ (

action

)、フォームなどの追加の props 属性をコンポーネント テンプレートに渡します。送信 URL (url) については、フォーム コンポーネントの調整を後ほど紹介します。 記事編集ビュー

新しい edit.blade.phpresources/views/posts ディレクトリにファイル編集ページ ビュー ファイルとして作成します<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">@extends('layouts.app') @section('content')     &lt;p&gt;         &lt;/p&gt;&lt;p&gt;             &lt;post-form&gt;             &lt;/post-form&gt;         &lt;/p&gt;     </pre><div class="contentsignin">ログイン後にコピー</div></div>

@endsection は、記事編集フォームをレンダリングするために post-form

テンプレートも使用しますが、記事データを初期化するために追加の id 属性が渡されます。フォームコンポーネントで編集されました。

記事詳細ページビューについては後ほど別途紹介します。 Vue フォーム コンポーネントのコードを再構築する記事編集フォームに適応させ、バックエンド インターフェイスから返されるデータ形式を調整するには、Vue フォーム コンポーネントの実装コードを変更する必要があります。 :

@extends('layouts.app')

@section('content')
    <p>
        </p><p>
            <post-form> $id]) }}">
            </post-form>
        </p>
    
@endsection
ログイン後にコピー

記事の公開ページと編集ページはタイトルで区別する必要があるため、親スコープから title 属性を通じてタイトル値を渡します。

記事編集フォームの場合、まず、親から渡された

id

属性値に基づいて、

mounted

フック関数で新しい

load を呼び出します。

メソッドは、バックエンド インターフェイス /posts/{post}/data から対応する記事データを読み込み、フォームに入力します。

现在后端接口可以自动获取当前认证用户的 ID,所以 author 字段就没有必要填写了,直接将其移除。

文章创建和编辑对应的请求方式是不一样的,操作成功后处理逻辑也是不一样的(前者重定向到列表页,后者重定向到详情页),所以根据 action 属性值分别进行了处理。

此外,由于后端对表单数据进行验证后,保存数据阶段依然可能失败,所以前端提交表单后返回的响应状态码为 200 并不表示表单提交处理成功,还需要借助响应实体(JSON 格式)中的 success 字段进一步判断,进而通过 ToastMsg 子组件渲染成功或失败的提示文本。

ToastMsg 是从之前的 SuccessMsg 组件升级而来,直接将 SuccessMsg 组件重命名为 ToastMsg 并改写组件代码如下:

<style>
.alert {
    margin-top: 10px;
}
</style>

<template>
    <p>
        <slot></slot>
    </p>
</template>

<script>
export default {
    props: [&#39;validated&#39;, &#39;success&#39;]
}
</script>
ログイン後にコピー

可以看到,如果表单提交处理成功(依然基于父级作用域传递的 form.success 属性)则显示成功提示样式及文案,否则显示失败提示样式和文案,而是否渲染该组件取决于表单验证是否成功,该字段基于父级作用域传递的 form.validated 属性,之前是没有这个属性的,所以我们需要额外添加,在 resources/js/form.js 中,调整相关代码实现如下:

class Form {
    constructor(data) {
        ...
        this.validated = false;
    }

    ...
    
    /**
     * 表单提交处理
     *
     * @param {string} url
     * @param {string} method
     */
    submit(url, method) {
        return new Promise((resolve, reject) => {
            axios[method](url, this.data())
                .then(response => {
                    this.onSuccess(response.data);
                    this.validated = true;
                    if (this.success === true) {
                        resolve(response.data);
                    } else {
                        reject(response.data);
                    }
                })
                .catch(error => {
                    this.onFail(error.response.data.errors);
                    reject(error.response.data);
                });
        });
    }


    /**
     * 处理表单提交成功
     *
     * @param {object} data
     */
    onSuccess(data) {
        this.success = data.success;
        this.message = data.message;
        this.reset();
    }
    
    ...

}
ログイン後にコピー

这样一来,文章发布和编辑共用的 Vue 表单组件就重构好了。

文章详情页视图和 Vue 组件实现

我们接着来实现文章详情页。

PostDetail 组件

component-practice/resources/js/components 目录下新建一个 PostDetail.vue 文件作为渲染文章详情的 Vue 单文件组件,并编写组件代码如下:

<style>
.post-detail {
    width: 100%;
}
.post-title {
    margin-bottom: .25rem;
    font-size: 2.5rem;
}
.post-meta {
    margin-bottom: 1.25rem;
    color: #999;
}
.post-content {
    font-size: 1.1rem;
    font-weight: 400;
    line-height: 1.5;
    color: #212529;
}
</style>

<template>
    <p>
        <span>Loading...</span>
    </p>
    <p>
        </p>
<h2>{{ title }}</h2>
        <p>
            Created at {{ created_at | diff_for_human }} by <a>{{ author_name }}</a>,
            Status: {{ status | post_status_readable }},
            Action: <a>编辑</a>
        </p>
        <p>
            {{ content }}
        </p>
    
</template>

<script>
export default {
    props: [&#39;post_id&#39;],
    data() {
        return {
            id: this.post_id,
            title: &#39;&#39;,
            content: &#39;&#39;,
            status: &#39;&#39;,
            author_name: &#39;&#39;,
            created_at: &#39;&#39;,
            loaded: false
        }
    },

    mounted() {
        if (!this.loaded) {
            this.load(Number(this.id));
        }
    },

    methods: {
        load(id) {
            axios.get(&#39;/posts/&#39; + this.id + &#39;/data&#39;).then(resp => {
                this.title = resp.data.title;
                this.content = resp.data.content;
                this.status = resp.data.status;
                this.author_name = resp.data.author_name;
                this.created_at = resp.data.created_at;
                this.loaded = true;
            }).catch(err => {
                alert(&#39;加载文章数据失败&#39;);
            });
        }
    }
}
</script>
ログイン後にコピー

这个组件功能比较简单,在 mounted 钩子函数中通过父级作用域传递的 id 属性值调用 load 函数加载后端接口返回的文章数据,并通过数据绑定将其渲染到模板代码中,在加载过程中,会有一个动态的加载状态提示用户文章数据正在加载。

这里我们还使用了过滤器对数据进行格式化,日期过滤器已经是全局的了,状态过滤器之前是本地的,这里我们将其从文章列表卡片组件 CardItem 中将其迁移到 app.js 中作为全局过滤器:

Vue.filter('post_status_readable', status => {
    switch(status) {
        case 0:
            return '草稿';
        case 1:
            return '已发布';
        default:
            return '未知状态';
    }
});
ログイン後にコピー

然后就可以在任何 Vue 组件中调用它了(CardItem 中过滤器调用代码做一下相应调整)。

app.js 中注册这个组件:

Vue.component('post-detail', require('./components/PostDetail.vue').default);
ログイン後にコピー

文章详情页视图文件

再到 component-practice/resources/views/posts 目录下新建 show.blade.php 视图文件引用 post-detail 组件即可:

@extends('layouts.app')

@section('content')
<p>
    <post-detail></post-detail>
</p>
@endsection
ログイン後にコピー

优化文章列表组件

最后,我们到文章列表组件中新增一个发布文章入口。

打开子组件 ListSection,在视图模式切换按钮右侧新增一个插槽,用于从父级作用域传递更多额外操作按钮:

<style>
.card-header h5 {
    margin-top: 0.5em;
    display: inline-block;
}
.card-header .float-right {
    float: right;
}
</style>

<template>
<p>
    </p>
<p>
        </p>
<h5><slot></slot></h5>
        <p>
            <button>
                {{ view.switch_to }}
            </button>
            <slot></slot>
        </p>
    
    
    ...</template>
ログイン後にコピー

然后在 PostList 中将发布文章按钮放到这个插槽中(样式代码也做了微调):

<style>
.post-list {
    width: 100%;
}
</style>

<template>
    <p>
    <listsection>
        <template>文章列表</template>
        <template>
            <a>新文章</a>
        </template>
        <template>
            <listitem>
                {{ post.title }}
            </listitem>
        </template>
    ...</listsection></p></template>
ログイン後にコピー

顺便也为文章列表所有文章设置详情页链接,ListItem 链接是从 PostList 通过 props 属性传递的,CardItem 需要去子组件中设置:

<a><slot></slot></a>
ログイン後にコピー

至此,我们就完成了文章列表、发布、编辑和详情页的所有前后端功能代码编写。

整体测试

如果你已经在本地运行了 npm run watch 并且通过 php arstisan serve 启动 PHP 内置 Web 服务器的话,就可以在浏览器通过 http://127.0.0.1:3002/posts (启用了 BrowserSync 代理)访问新的文章列表页了:

Laravel+Vue コンポーネントに基づいて記事の公開、編集、閲覧機能を実装する方法を説明します。

点击任意文章链接,即可进入文章详情页,加载数据成功之前,会有如下动态加载效果:

Laravel+Vue コンポーネントに基づいて記事の公開、編集、閲覧機能を実装する方法を説明します。

Laravel+Vue コンポーネントに基づいて記事の公開、編集、閲覧機能を実装する方法を説明します。

你可以点击「编辑」链接对这篇文章进行编辑:

Laravel+Vue コンポーネントに基づいて記事の公開、編集、閲覧機能を実装する方法を説明します。

更新成功后,会跳转到文章详情页,对应字段均已更新,并且状态也从草稿变成了已发布:

Laravel+Vue コンポーネントに基づいて記事の公開、編集、閲覧機能を実装する方法を説明します。

もちろん、記事公開・編集機能はログインが必要です(現時点では権限検証は行われません)。ログインしていない場合は、編集ボタンと新規記事ボタンをクリックすると、まずログインページにジャンプします(この機能はPostController コントローラーコンストラクターで定義されたミドルウェアメソッドの実装によって提供されます)、ログインした状態で、記事一覧ページの右上隅にある「新しい記事」ボタンをクリックして記事公開に入りますページ:

Laravel+Vue コンポーネントに基づいて記事の公開、編集、閲覧機能を実装する方法を説明します。

公開が成功すると、記事一覧ページにジャンプし、作成したばかりの記事が一覧に表示されます:

Laravel+Vue コンポーネントに基づいて記事の公開、編集、閲覧機能を実装する方法を説明します。

追加、削除、修正、確認してください。まだ 1 つ残っています。「削除」は次のチュートリアルで記事削除機能の実装を説明します。なぜ個別に紹介するのでしょうか。削除機能を組み合わせて、Vue コンポーネントに基づくモーダル ボックス、ダイアログ ボックス、トランジション効果の実装をデモンストレーションしたいと考えています。

以上がLaravel+Vue コンポーネントに基づいて記事の公開、編集、閲覧機能を実装する方法を説明します。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:xueyuanjun.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート