Laravel + Vue 使用示例系列:構(gòu)建一個(gè)類似 Twitter 的 Web 應(yīng)用
  • 更新時(shí)間:2024-12-22 02:35:30
  • 分享
  • 發(fā)布時(shí)間:6年前
  • 8146

在這一篇示例教程中,我們將會(huì)構(gòu)建一個(gè)類似 Twitter 的 Web 應(yīng)用。我們將使用到 Laravel 5.6 和 Vue.js,并且在 Vue.js 中定義一些組件,此外,還會(huì)使用 Axios 來發(fā)送網(wǎng)絡(luò)請(qǐng)求。當(dāng)然,篇幅有限,我們不可能開發(fā)一個(gè)完整的 Twitter 應(yīng)用,而是實(shí)現(xiàn)一個(gè)簡(jiǎn)化版:用戶可以發(fā)送 Tweet 并在自己的時(shí)間線中看到,可以關(guān)注或取消關(guān)注其他用戶,如果關(guān)注了其他用戶,那么也可以看到關(guān)注用戶發(fā)布的 Tweet。麻雀雖小,五臟俱全,希望大家可以通過這個(gè)簡(jiǎn)單的應(yīng)用學(xué)會(huì) Laravel 和 Vue.js 的基礎(chǔ)用法。

注:這是一篇翻譯文章,你可以將 Twitter 對(duì)標(biāo)國內(nèi)新浪微博,一條 Tweet 就是一條微博信息。

安裝配置 Laravel

首先,我們需要安裝一個(gè)新的 Laravel 應(yīng)用(也可以通過 Composer 安裝,看個(gè)人喜好):

laravel?new?laratwitter

進(jìn)入該項(xiàng)目根目錄,安裝前端依賴:

npm?install

接下來,修改?.env?中數(shù)據(jù)庫相關(guān)配置符合本地環(huán)境,然后通過如下命令生成用戶認(rèn)證腳手架代碼:

php?artisan?make:auth

運(yùn)行如下命令生成相關(guān)數(shù)據(jù)表:

php?artisan?migrate

接下來配置下 Web 服務(wù)器(使用 Valet 的話略過),我這里配置的域名是?laratwitter.test,配置完成后重啟下 Web 服務(wù)器,然后通過?http://laratwitter.test/register?注冊(cè)一個(gè)新用戶:

用戶注冊(cè)

接下來編輯?resoureces >> views >> home.blade.php?文件:

@extends('layouts.app')

@section('content')
<div?class="container">
????<div?class="row?justify-content-center">
????????<div?class="col-md-4">
????????????Tweet?表單
????????</div>
????????<div?class="col-md-8">
???????????時(shí)間線
????????</div>
????</div>
</div>
@endsection

新注冊(cè)用戶登錄后就能在新的 Home 頁看到變更后的效果了。

創(chuàng)建一個(gè) Tweet 表單

我們使用 Vue.js 來完成表單創(chuàng)建,首先到?resources >> assets >> js >> components?目錄下新增一個(gè)?FormComponent.vue?文件:

//?FormComponent.vue

<template>
????<div?class="col-md-4">
????????<form>
????????????<div?class="form-group">
????????????????<textarea?
????????????????????class="form-control"?
????????????????????rows="8"?cols="8"?
????????????????????maxlength="130"?
????????????????????required>
????????????????</textarea>
????????????</div>
????????????<div?class="form-group">
????????????????<button?class="btn?btn-primary">
????????????????????發(fā)送
????????????????</button>
????????????</div>
????????</form>????????
????</div>
</template>
<script>
export?default?{

}
</script>

然后在?resources >> assets >> js >> app.js?中導(dǎo)入這個(gè)組件:

//?app.js

require('./bootstrap');

window.Vue?=?require('vue');

Vue.component('form-component',?require('./components/FormComponent.vue'));

const?app?=?new?Vue({
????el:?'#app'
});

最后在?home.blade.php?中使用這個(gè)組件:

@extends('layouts.app')

@section('content')
<div?class="container">
????<div?class="row?justify-content-center">
???????<form-component></form-component>
????????<div?class="col-md-8">
????????????TimeLines
????????</div>
????</div>
</div>
@endsection

為了監(jiān)聽前端資源變動(dòng),可以在項(xiàng)目根目錄下運(yùn)行如下命令監(jiān)聽前端資源變動(dòng)并實(shí)時(shí)編譯:

npm?run?watch

這樣,刷新?http://laratwitter.test/home?頁面就可以看到變更后的效果了:

用戶主頁

創(chuàng)建 Post 模型類及對(duì)應(yīng)數(shù)據(jù)庫遷移文件

下面我們來實(shí)現(xiàn)表單提交保存操作,首先創(chuàng)建一個(gè)模型類及對(duì)應(yīng)數(shù)據(jù)庫遷移文件:

php?artisan?make:model?Post?-m

編寫剛生成的數(shù)據(jù)庫遷移文件?create_posts_table.php

//?create_posts_table

public?function?up()
{
???Schema::create('posts',?function?(Blueprint?$table)?{
???????$table->increments('id');
???????$table->integer('user_id')->unsigned();
???????$table->string('body',?140);
???????$table->timestamps();

???????$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
????});
}

運(yùn)行數(shù)據(jù)庫遷移命令:

php?artisan?migrate

現(xiàn)在可以在數(shù)據(jù)庫中看到剛創(chuàng)建的?posts?數(shù)據(jù)表了。

接下來創(chuàng)建控制器?PostController

php?artisan?make:controller?PostController

定義關(guān)聯(lián)關(guān)系

在?User?模型類中,我們需要定義一個(gè)關(guān)聯(lián)方法建立?Post?模型和?User?模型之間的關(guān)聯(lián)關(guān)系(一對(duì)多):

public?function?posts()
{
???return?$this->hasMany(Post::class);
}

相應(yīng)地,在?Post?模型類中,也要定義與?User?模型的關(guān)聯(lián)關(guān)系:

public?function?user()
{
???return?$this->belongsTo(User::class);
}

在數(shù)據(jù)庫中保存 Tweet

前面提到我們將通過?axios?庫來發(fā)送 POST 請(qǐng)求到 Laravel 后端服務(wù)器,這個(gè)庫在我們運(yùn)行?npm install?命令的時(shí)候已經(jīng)安裝好了,在開始處理請(qǐng)求發(fā)送與處理之前,我們先來定義請(qǐng)求路由,在?routes >> web.php?文件中新增一個(gè)路由定義如下:

Route::post('tweet/save',?'PostController@store');

此外,還需要定義?Post?模型類的?$fillable?屬性來避免批量賦值異常:

protected?$fillable?=?['user_id',?'body'];

最后要做的準(zhǔn)備工作就是到?PostController.php?中定義?store?方法:

public?function?store(Request?$request,?Post?$post)
{
????$newPost?=?$request->user()->posts()->create([
????????'body'?=>?$request->get('body')
????]);

????return?response()->json($post->with('user')->find($newPost->id));
}

我們使用了關(guān)聯(lián)關(guān)系來保存 Post 數(shù)據(jù),它會(huì)自動(dòng)將當(dāng)前登錄用戶的?id?作為保存 Post 的?user_id?字段。

后端邏輯實(shí)現(xiàn)之后,接下來需要使用?axios?庫類發(fā)送 POST 請(qǐng)求,我們將相應(yīng)邏輯寫到?FormComponent.vue?組件中:

//?FormComponent.vue

<template>
????<div?class="col-md-4">
????????<form?@submit.prevent="saveTweet">
????????????<div?class="form-group">
????????????????<textarea?
????????????????????class="form-control"?
????????????????????rows="8"?cols="8"?
????????????????????maxlength="130"
????????????????????v-model="body"
????????????????????required>
????????????????</textarea>
????????????</div>
????????????<div?class="form-group">
????????????????<button?class="btn?btn-primary">
????????????????????Tweet
????????????????</button>
????????????</div>
????????</form>????????
????</div>
</template>
<script>
export?default?{
????data()?{
????????return?{
????????????body:?''
????????}
????},
????methods:?{
????????saveTweet()?{
????????????axios.post('/tweet/save',?{body:?this.body}).then(res?=>?{
????????????????console.log(res.data);
????????????}).catch(e?=>?{
????????????????console.log(e);
????????????});

????????}
????}
}
</script>

CSRF_TOKEN?會(huì)默認(rèn)包含到每個(gè) POST 請(qǐng)求,所以不必手動(dòng)添加?,F(xiàn)在,如果一切正常工作的話,你就可以成功保存 Post 數(shù)據(jù)并在響應(yīng)中獲取到 Post 對(duì)象及其關(guān)聯(lián)用戶:

發(fā)送Tweet

創(chuàng)建一個(gè) Vue 事件

要想在前端顯示所有 Tweet,首先需要將它們顯示到時(shí)間線中,為此,我們需要?jiǎng)?chuàng)建一個(gè)事件。注意,這里不是要通過刷新頁面來獲取所有 Tweet,而是當(dāng)我們添加一條新的 Tweet 時(shí),在不刷新頁面的情況下在用戶時(shí)間線中顯示這條 Tweet。

為了實(shí)現(xiàn)這個(gè)功能,需要?jiǎng)?chuàng)建一個(gè)事件并觸發(fā)這個(gè)事件,我們通過時(shí)間線組件來監(jiān)聽事件觸發(fā)并基于該事件更新 UI??梢酝ㄟ^?Vuex?來實(shí)現(xiàn)該功能,但是現(xiàn)在,我們不想要深入存儲(chǔ)和動(dòng)作,只想將事情保持簡(jiǎn)單。

在?resources >> assets >> js?目錄下創(chuàng)建一個(gè)名為?event.js?的文件,并編寫代碼如下:

//?event.js

import?Vue?from?'vue';
export?default?new?Vue();

然后將該文件導(dǎo)入?FormComponent.vue

//?FormComponent.vue

<template>
????<div?class="col-md-4">
????????<form?@submit.prevent="saveTweet">
????????????<div?class="form-group">
????????????????<textarea?
????????????????????class="form-control"?
????????????????????rows="8"?cols="8"?
????????????????????maxlength="130"
????????????????????v-model="body"
????????????????????required>
????????????????</textarea>
????????????</div>
????????????<div?class="form-group">
????????????????<button?class="btn?btn-primary">
????????????????????Tweet
????????????????</button>
????????????</div>
????????</form>????????
????</div>
</template>
<script>
import?Event?from?'../event.js';
export?default?{
????data()?{
????????return?{
????????????body:?'',
????????????postData:?{}
????????}
????},
????methods:?{
????????saveTweet()?{
????????????axios.post('/tweet/save',?{body:?this.body}).then(res?=>?{
????????????????this.postData?=?res.data;
????????????????Event.$emit('added_tweet',?this.postData);
????????????}).catch(e?=>?{
????????????????console.log(e);
????????????});
????????????this.body?=?'';
????????}
????}
}
</script>

這樣,當(dāng)新提交數(shù)據(jù)被保存后,就可以觸發(fā)包含保存的 Tweet 和用戶信息的事件,監(jiān)聽該事件的監(jiān)聽器就可以捕獲數(shù)據(jù)并更新 UI。

創(chuàng)建時(shí)間線組件

接下來,我們來定義監(jiān)聽 Tweet 發(fā)送成功事件的監(jiān)聽器。

在?resources >> assets >> js >> components?目錄下新增一個(gè)?TimelineComponent.vue?組件,編寫該組件代碼如下:

//?TimelineComponent.vue

<template>
????<div?class="col-md-8?posts">
????????<p?v-if="!posts.length">No?posts</p>
????????<div?class="media"?v-for="post?in?posts"?:key="post.id">
????????????<img?class="mr-3"?/>
????????????<div?class="media-body">
????????????????<div?class="mt-3">
????????????????????<a?href="#">{{?post.user.name?}}</a>
????????????????</div>
????????????????<p>{{?post.body?}}</p>
????????????</div>
????????</div>
????</div>
</template>
<script>
import?Event?from?'../event.js';

export?default?{
????data()?{
????????return?{
????????????posts:?[],
????????????post:?{}
????????}
????},
????mounted()?{
????????Event.$on('added_tweet',?(post)?=>?{
????????????this.posts.unshift(post);
????????});
????}
}
</script>

這里我們定義了一個(gè)監(jiān)聽?added_tweet?事件的監(jiān)聽器,當(dāng)該事件被觸發(fā)后,就可以執(zhí)行相應(yīng)的方法將數(shù)據(jù)渲染到時(shí)間線組件中。

和?FormComponent.vue?組件一樣,在?app.js?中注冊(cè)這個(gè)組件:

Vue.component('timeline-component',?require('./components/TimelineComponent.vue'));

我們專注高端建站,小程序開發(fā)、軟件系統(tǒng)定制開發(fā)、BUG修復(fù)、物聯(lián)網(wǎng)開發(fā)、各類API接口對(duì)接開發(fā)等。十余年開發(fā)經(jīng)驗(yàn),每一個(gè)項(xiàng)目承諾做到滿意為止,多一次對(duì)比,一定讓您多一份收獲!

本文章出于推來客官網(wǎng),轉(zhuǎn)載請(qǐng)表明原文地址:https://www.tlkjt.com/marketing/77.html
推薦文章

在線客服

掃碼聯(lián)系客服

3985758

回到頂部