Laravel 5.3 + Vue 类似 Reddit 的投票系统

Posted

技术标签:

【中文标题】Laravel 5.3 + Vue 类似 Reddit 的投票系统【英文标题】:Laravel 5.3 + Vue Reddit-like voting system 【发布时间】:2017-02-06 11:31:42 【问题描述】:

我正在学习 Vuejs(首先对 Laravel 不太精通),并且我正在尝试为某些任务制作一个简单的投票系统。我设法添加、编辑和删除任务,但是当我添加赞成/反对的内容时,投票数没有改变。

所以这里是routes\api.php 中的 Laravel 路由:

Route::group(['middleware'=>'api'],function()

Route::get('tasks', function()
    return \App\Task::latest()->orderBy('created_at', 'desc')->get();
);

Route::get('task/id', function($id)
    return \App\Task::findOrFail($id);
);

Route::post('task/store', function(Request $request)
    return App\Task::create(['body' => $request->input(['body'])]);
);

Route::patch('task/id', function(Request $request, $id)
    return \App\Task::findOrFail($id)->update(['body' => $request->input(['body'])]);
);

Route::delete('task/id', function($id)
    return \App\Task::destroy($id);
);

Route::get('task/id/votes', function($id)
    return \App\Task::findOrFail($id)->votes->get();
);

Route::patch('task/id/votes', function(Request $request, $id)
    return \App\Task::findOrFail($id)->update(['votes'=> $request->input(['votes'])]);
); 
);

Tasks 表的迁移是这样的(我用的是 sqlite):

Schema::create('tasks', function (Blueprint $table) 
        $table->increments('id');
        $table->text('body');
        $table->integer('votes')->default(1);
        $table->timestamps();
    );

这是 Vue 的 Tasks 组件模板:

<h1>My Tasks</h1>
<hr>
<h4>New Task</h4>
<form action="#" @submit.prevent="edit ? updateTask(task.id) : createTask()">
    <div class="input-group">
        <input type="text" name="body" v-model="task.body" v-el:taskinput class="form-control" autofocus>
        <span class="input-group-btn">
            <button type="submit" class="btn btn-success" v-show="!edit">New Task</button>
            <button type="submit" class="btn btn-primary" v-show="edit">Edit Task</button>
        </span>
    </div>
</form>
<hr>
<hr>
<h3>All Tasks</h3>
<ul class="list-group">
    <li class="list-group-item" v-for="task in list">
         task.body 
        <button class="btn-success btn-xs" @click="upvote(task.id)" :class="disabled: upvoted">Upvote</button>
        <span class="label label-primary"> task.votes </span>
        <button class="btn-danger btn-xs" @click="downvote(task.id)" :class="disabled: downvoted">Downvote</button>
        <span class="pull-right">
            <button class="btn-primary btn-xs" @click="showTask(task.id)">Edit Task</button>
            <button class="btn-danger btn-xs" @click="deleteTask(task.id)">Delete Task</button>
        </span>
    </li>
</ul>

最后是 Vue 脚本:

export default
    data()
        return
            edit: false,
            list: [],
            task: 
                id: '',
                body: '',
                votes: Number
            ,
            upvoted: false,
            downvoted: false
        
    ,

    ready: function () 
        this.fetchTaskList();
    ,

    methods:

        fetchTaskList: function () 
            this.$http.get('api/tasks').then(function (response) 
                this.list = response.data
            );
        ,

        createTask: function () 
            this.$http.post('api/task/store', this.task);
            this.task.body = '';
            this.edit = false;
            this.fetchTaskList();
        ,

        updateTask: function (id) 
            this.$http.patch('api/task/' + id, this.task);
            this.task.body='';
            this.edit = false;
            this.fetchTaskList();
        ,

        showTask: function (id) 
            this.$http.get('api/task/' + id).then(function (response) 
                this.task.id = response.data.id;
                this.task.body = response.data.body;
            );
            this.$els.taskinput.focus();
            this.edit = true;
        ,

        deleteTask: function (id) 
            this.$http.delete('api/task/' + id);
            this.fetchTaskList();
        ,

        updateVotes: function (id, votes) 
            this.$http.patch('api/task/'+id+'/votes', votes);
        ,

        upvote: function (id) 
            this.$http.get('api/task/'+id+'/votes').then(function (response) 
                this.task.id = response.data.id;
                this.task.votes = response.data.votes + 1;
                updateVotes(this.task.id, this.task.votes);
            );
            this.upvoted = !this.upvoted;
            this.downvoted = false;
        ,

        downvote: function (id) 
            this.$http.get('api/task/'+id+'/votes').then(function (response) 
                this.task.id = response.data.id;
                this.task.votes = response.data.votes - 1;
                updateVotes(this.task.id, this.task.votes);
            );
            this.upvoted = false;
            this.downvoted = !this.downvoted;
        ,
    

我猜错误出在 Vue 脚本的某个地方,要么我宣布投票错误(投票:数字?),要么我不能像我一样从 upvote 和 downvote 函数调用 updateVotes 函数。

编辑: 仍然没有工作,但我有 Vue.js 开发工具,它肯定会识别选票: https://snag.gy/sE5gp6.jpg

...但是以一种非常奇怪的方式。当我点击 upvote 时,devtools 中的投票变为“11”,而不是 1。当我点击 downvote 时,它​​又回到 0。但它在视图中没有改变。这是在我做出改变之后的全部内容:

updateVotes(this.task.id, this.task.votes);

收件人:

this.updateVotes(this.task.id, this.task.votes);

..正如用户 Dan 建议的那样,并在更改后:

upvote: function (id) 
        this.$http.get('api/task/'+id+'/votes')

收件人:

upvote: function (id) 
        this.$http.get('api/task/'+id)

因为我认为我以前只是获得选票,然后将它们视为任务对象,用于函数的其余部分。 downvote 函数也是如此。

这就是现在控制台中出现的内容:

vue-resource.common.js?d39b:966 PATCH http://localhost:8000/api/task/8/votes 500 (Internal Server Error)(匿名函数) @ vue-resource.common.js?d39b:966Promise$1 @ vue-resource.common.js? d39b:192xhrClient@vue-resource.common.js?d39b:927sendRequest@vue-resource.common.js?d39b:1060exec@vue-resource.common.js?d39b:1017next@vue-resource.common.js?d39b: 1042before@vue-resource.common.js?d39b:881exec@vue-resource.common.js?d39b:1017next@vue-resource.common.js?d39b:1042timeout@vue-resource.common.js?d39b:920exec@ vue-resource.common.js?d39b:1017next@vue-resource.common.js?d39b:1042method@vue-resource.common.js?d39b:895exec@vue-resource.common.js?d39b:1017next@vue- resource.common.js?d39b:1042body@vue-resource.common.js?d39b:802exec@vue-resource.common.js?d39b:1017next@vue-resource.common.js?d39b:1042jsonp@vue-resource. common.js?d39b:867exec@vue-resource.common.js?d39b:1017next@vue-resource.common.js?d39b:1042header@vue-resource.common.js?d39b:903exec@vue-resource.common。 j s?d39b:1017next@vue-resource.common.js?d39b:1042cors@vue-resource.common.js?d39b:777exec@vue-resource.common.js?d39b:1017next@vue-resource.common.js? d39b:1042(匿名函数)@VM56:32exec@vue-resource.common.js?d39b:1017(匿名函数)@vue-resource.common.js?d39b:1045Promise$1@vue-resource.common.js?d39b :192Client@vue-resource.common.js?d39b:1010Http@vue-resource.common.js?d39b:1152Http.(匿名函数)@vue-resource.common.js?d39b:1188updateVotes@Tasks.vue?34c5: 94(匿名函数)@vue.common.js?4a36:216(匿名函数)@Tasks.vue?34c5:102 localhost/:1 Uncaught (in promise) 响应 url: "api/task/8/votes", body: "↵↵ ↵ ↵↵↵ ↵ ↵", headers: Object, status: 500, statusText: "Internal Server Error “……

【问题讨论】:

【参考方案1】:

如果你替换它是否有效:

updateVotes(this.task.id, this.task.votes);

this.updateVotes(this.task.id, this.task.votes);

【讨论】:

仍然没有,但我想这是需要改变的事情之一。 您的浏览器控制台或日志文件中是否有任何错误? 加载资源失败:服务器响应状态为 500 (Internal Server Error) localhost:8000/api/task/7/votes Uncaught (in promise) 响应。但是,在您发表第一条评论后,我注意到我在获得选票的路线上犯了一个错误。我这样做了: Route::get('task/id/votes', function($id) return \App\Task::findOrFail($id)->votes->get(); );但将其视为 vue 脚本中的 Task 对象。所以我将 Vue 的 upvote 和 downvote 函数更改为: this.$http.get('api/task/'+id) 而不是 this.$http.get('api/task/'+id +'/votes ') 在 Chrome 开发者工具中,点击网络标签。您应该会看到一个 AJAX 请求列表,因为它们正在生成。单击导致问题的请求,然后单击另一个窗口中的响应或预览选项卡。这可能会让您更好地了解正在发生的事情。如果没有,请尝试查看您的 Laravel 日志文件(通常是 storage/logs/laravel-todaysdate.log) 好的,非常感谢。我一回到家就会这样做。【参考方案2】:

(代表 OP 发布).

问题解决了。我没有在 Task 模型中添加protected $fillable = ['votes']

【讨论】:

以上是关于Laravel 5.3 + Vue 类似 Reddit 的投票系统的主要内容,如果未能解决你的问题,请参考以下文章

带有 Laravel 5.3 的 Vue 多选

Laravel 5.3 vue 2组件不渲染

Vue.js 与 laravel 5.3

Vue 2 Laravel 5.3 Eloquent 无法从对象中检索数据

Vue 2 Laravel 5.3 vue-toastr

Laravel 5.3 Passport - Vue 错误:评估表达式时出错