在这一篇示例教程中,我们将会构建一个类似 Twitter 的 Web 应用。我们将使用到 Laravel 5.6 和 Vue.js,并且在 Vue.js 中定义一些组件,此外,还会使用 Axios 来发送网络请求。当然,篇幅有限,我们不可能开发一个完整的 Twitter 应用,而是实现一个简化版:用户可以发送 Tweet 并在自己的时间线中看到,可以关注或取消关注其他用户,如果关注了其他用户,那么也可以看到关注用户发布的 Tweet。麻雀虽小,五脏俱全,希望大家可以通过这个简单的应用学会 Laravel 和 Vue.js 的基础用法。
注:这是一篇翻译文章,你可以将 Twitter 对标国内新浪微博,一条 Tweet 就是一条微博信息。
安装配置 Laravel
首先,我们需要安装一个新的 Laravel 应用(也可以通过 Composer 安装,看个人喜好):
laravel new laratwitter
进入该项目根目录,安装前端依赖:
npm install
接下来,修改 .env
中数据库相关配置符合本地环境,然后通过如下命令生成用户认证脚手架代码:
php artisan make:auth
运行如下命令生成相关数据表:
php artisan migrate
接下来配置下 Web 服务器(使用 Valet 的话略过),我这里配置的域名是 laratwitter.test
,配置完成后重启下 Web 服务器,然后通过 http://laratwitter.test/register
注册一个新用户:
接下来编辑 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"> 时间线 </div> </div> </div> @endsection
新注册用户登录后就能在新的 Home 页看到变更后的效果了。
创建一个 Tweet 表单
我们使用 Vue.js 来完成表单创建,首先到 resources >> assets >> js >> components
目录下新增一个 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"> 发送 </button> </div> </form> </div> </template> <script> export default { } </script>
然后在 resources >> assets >> js >> app.js
中导入这个组件:
// 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
中使用这个组件:
@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
为了监听前端资源变动,可以在项目根目录下运行如下命令监听前端资源变动并实时编译:
npm run watch
这样,刷新 http://laratwitter.test/home
页面就可以看到变更后的效果了:
创建 Post 模型类及对应数据库迁移文件
下面我们来实现表单提交保存操作,首先创建一个模型类及对应数据库迁移文件:
php artisan make:model Post -m
编写刚生成的数据库迁移文件 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'); }); }
运行数据库迁移命令:
php artisan migrate
现在可以在数据库中看到刚创建的 posts
数据表了。
接下来创建控制器 PostController
:
php artisan make:controller PostController
定义关联关系
在 User
模型类中,我们需要定义一个关联方法建立 Post
模型和 User
模型之间的关联关系(一对多):
public function posts() { return $this->hasMany(Post::class); }
相应地,在 Post
模型类中,也要定义与 User
模型的关联关系:
public function user() { return $this->belongsTo(User::class); }
在数据库中保存 Tweet
前面提到我们将通过 axios
库来发送 POST 请求到 Laravel 后端服务器,这个库在我们运行 npm install
命令的时候已经安装好了,在开始处理请求发送与处理之前,我们先来定义请求路由,在 routes >> web.php
文件中新增一个路由定义如下:
Route::post('tweet/save', 'PostController@store');
此外,还需要定义 Post
模型类的 $fillable
属性来避免批量赋值异常:
protected $fillable = ['user_id', 'body'];
最后要做的准备工作就是到 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)); }
我们使用了关联关系来保存 Post 数据,它会自动将当前登录用户的 id
作为保存 Post 的 user_id
字段。
后端逻辑实现之后,接下来需要使用 axios
库类发送 POST 请求,我们将相应逻辑写到 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
会默认包含到每个 POST 请求,所以不必手动添加。现在,如果一切正常工作的话,你就可以成功保存 Post 数据并在响应中获取到 Post 对象及其关联用户:
创建一个 Vue 事件
要想在前端显示所有 Tweet,首先需要将它们显示到时间线中,为此,我们需要创建一个事件。注意,这里不是要通过刷新页面来获取所有 Tweet,而是当我们添加一条新的 Tweet 时,在不刷新页面的情况下在用户时间线中显示这条 Tweet。
为了实现这个功能,需要创建一个事件并触发这个事件,我们通过时间线组件来监听事件触发并基于该事件更新 UI。可以通过 Vuex 来实现该功能,但是现在,我们不想要深入存储和动作,只想将事情保持简单。
在 resources >> assets >> js
目录下创建一个名为 event.js
的文件,并编写代码如下:
// event.js import Vue from 'vue'; export default new Vue();
然后将该文件导入 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>
这样,当新提交数据被保存后,就可以触发包含保存的 Tweet 和用户信息的事件,监听该事件的监听器就可以捕获数据并更新 UI。
创建时间线组件
接下来,我们来定义监听 Tweet 发送成功事件的监听器。
在 resources >> assets >> js >> components
目录下新增一个 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>
这里我们定义了一个监听 added_tweet
事件的监听器,当该事件被触发后,就可以执行相应的方法将数据渲染到时间线组件中。
和 FormComponent.vue
组件一样,在 app.js
中注册这个组件:
Vue.component('timeline-component', require('./components/TimelineComponent.vue'));
我们专注高端建站,小程序开发、软件系统定制开发、BUG修复、物联网开发、各类API接口对接开发等。十余年开发经验,每一个项目承诺做到满意为止,多一次对比,一定让您多一份收获!