初始化项目

composer create-project laravel/laravel comments

创建数据库,配置.env 文件。我这里的数据库是comments

使用系统自带的验证程序。

php artisan make:auth
php artisan migrate

使用npm命令安装依赖和tailwindcss

cnpm install tailwindcss --save-dev
cnpm install

本教程涉及到的代码我都将上传至:

https://github.com/leienshu/comments

构建组件结构

先使用下面的命令来观察sass文件或者js文件的一些变动情况。

npm run watch

清除home.blade.php文件中@section 和 @endsection 部分的内容。

home.blade.php

对了,上面的Laravel标题在env文件中可以改成Comments Demo。

好了,现在我们进入 resources/js/components 目录,新建一个新的Vue文件,名字叫:CommentsManager.vue ,具体内容如下:

<template>
    <div>
        <h1>Hello World</h1>
    </div>
</template>

<script>
    export default {
        data: function() {
            return {

          }
        },
    }
</script>

在 app.js 文件中注册上面新建的 vue 文件。把之前的example-component注释掉。

Vue.component('comments-manager', require('./components/CommentsManager.vue').default);

在 home.blade.php 文件的section部分添加下面的模板。

<comments-manager></comments-manager>
成功引入组件

用户界面有点丑,不过我们继续干吧。

显示评论

在CommentsManager的data属性里,我们增加一些评论数据。如下:

return {
                comments: [
                {
                    id: 1,
                    body: "咋整的呢?",
                    edited: false,
                    created_at: new Date().toLocaleString(),
                    author: {
                        id: 1,
                        name: '雷经纬',
                    }
                }
            ]
          }

现在我们就有了一些数据可以使用,我们可以开始在页面上显示它。但是,现在虽然可以将所有逻辑保存在CommentsManager组件中,但我们最终必须编写一些奇怪的方法来解析每个注释的详细信息。所以,我们最好为每个评论制作另一个组件。

在 comments-manager.vue 相同目录下,再新建一个 CommentItem.vue 文件。

<template>
    <div>
    
    </div>
</template>

<script>
    export default {
        data: function() {
            return {
                
          }
        },
    }
</script>

现在,让我们通过一个评论属性,包含所有评论的数据,然后将其添加到模板中。

<template>
    <div>
        <div>
            <p>{{comment.body}}</p>
        </div>
        <div>
            <p>{{comment.author.name}} <span>--</span>{{ comment.created_at}}</p>
        </div>
    </div>
</template>

<script>
    export default {
        props: {
                comment: {
                    required: true,
                    type: Object,
                }
            },
        data: function() {
            return {

          }
        },
    }
</script>

现在进入 CommentsManager.vue 文件来注册CommentItem。

<template>
    <div>
        <div>
            <comment v-for="comment in comments"
                     :key="comment.id"
                     :comment="comment">
            </comment>
        </div>
    </div>
</template>

<script>
    import comment from './CommentItem'
    export default {
        components: {
                    comment
                    },
        data: function() {
            return {
                comments: [
                {
                    id: 1,
                    body: "咋整的呢?",
                    edited: false,
                    created_at: new Date().toLocaleString(),
                    author: {
                        id: 1,
                        name: '雷经纬',
                    }
                }]
          }
        },
    }
</script>

上面的代码看懂了么?我们在<script>标签里面引入CommentItem的comment属性。在评论显示的地方用v-for和:key来提取评论。

显示评论

评论显示好了,但是还不能编辑,下面我们就来编辑评论。

编辑评论

因为我们的编辑功能并不是对所有人开放的,所以我们需要传递当前用户到CommentItem里。

为此,我们需要为我们的两个组件添加一个用户属性,然后对经过身份验证的用户添加传递。我们可以这样添加那个属性:

//CommentsManager
<comment v-for="comment in comments"
         :key="comment.id"
         :user="user"
         :comment="comment">
</comment>
...
props: {
    user: {
        required: true,
        type: Object,
    }
},

//CommentItem
props: {
    user: {
        required: true,
        type: Object,
    },
    comment: {
        required: true,
        type: Object,
    }
},

//home.blade.php
<comments-manager :user="{{ auth()->user() }}"></comments-manager>

在CommentItem中添加一个computed属性来判断当前用户是否可以编辑评论。

computed: {
    editable() {
        return this.user.id === this.comment.author.id;
    }
}

我们再给评论添加一个Edit按钮。

<div>
    <p>{{comment.body}}</p>
    <button v-if="editable">Edit</button>
</div>

上面的v-if可以确保只有当前用户才能点击这个Edit按钮。然后,我们再在CommentsManeger里面的comments里面添加一个对象。

comments: [
                    {
                        id: 1,
                        body: "咋整的呢?",
                        edited: false,
                        created_at: new Date().toLocaleString(),
                        author: {
                            id: 1,
                            name: '雷经纬',
                        }
                    },
                    {
                        id: 2,
                        body: "这样整的啊?",
                        edited: false,
                        created_at: new Date().toLocaleString(),
                        author: {
                            id: 2,
                            name: '王者归来',
                        }
                    },
                ]

出来的效果如下图:

当前用户显示Edit按钮

怎么样,现在的Edit还不能编辑,我们继续。

我们首先在CommentItem的组件数据中添加一个state属性,这样我们就可以跟踪编辑的时间。我们还要添加一个updatedComment属性,用来跟踪我们做的更改。

data: function() {
            return {
                state: 'default',
                data:{
                    body:this.comment.body,
                }

          }
        },

因为这里的state比较简单,我就用了字符串类型,其实也可以用布尔类型。

使用comment.body中的值初始化data.body,这样就可以让我们用正确的初始数据填充编辑表单。

绑定一个点击事件,将state设置为editing。

<button v-if="editable" @click="state = 'editing'">Edit</button>

接下来,让我们添加我们的编辑表单。

<template>
    <div>
        <div v-show="state === 'default'">
            <div>
                <p>{{comment.body}}</p>
                <button v-if="editable" @click="state = 'editing'">Edit</button>
            </div>
            <div>
                <p>{{comment.author.name}} <span>--</span>{{ comment.created_at}}</p>
            </div>
        </div>
        <div v-show="state === 'editing'">
            <div>
                <h3>Update Comment</h3>
            </div>
            <textarea v-model="data.body"
                      placeholder="Update comment"
                      class="border">
            </textarea>
            <div>
                <button>Update</button>
                <button>Cancel</button>
            </div>
        </div>
    </div>
</template>

上面用两个div来对应state的变化,我们再添加一个resetEdit的方法,用来重置data.body和state。

//Template
<button @click="resetEdit">Cancel</button>
...

//Vue Instance
methods: {
    resetEdit() {
        this.state = 'default';
        this.data.body = this.comment.body;
    }
}

继续添加一个saveEdit()的方法。

在这里,我们有几个选项可以将我们的更改返回到评论所在的父组件。我们可以直接使用 $parent.comments 去直接访问,也可以改变我们的 comment 属性。

但这些并不是最佳选择,因为它们和我们的组件结合过于紧密。不过,这样用也不是不行。不过,我建议我们还是使用event去搞。

在saveEdit()方法中,我们把state的设置回给它的默认值,并且我们这时候将修改评论这个事件传递过去。这样在CommentsManager我们将有一个updateComment方法,当我们的事件触发时就会调用它。

//CommentItem

//Template
<button @click="saveEdit">Update</button>

//Script
saveEdit() {
    this.state = 'default';

    this.$emit('comment-updated', {
        'id': this.comment.id,
        'body': this.data.body,
    });
}

//CommentsManager

//Template
<comment v-for="comment in comments"
         :key="comment.id"
         :user="user"
         :comment="comment"
         @comment-updated="updateComment($event)">
</comment>

//Script
methods: {
    updateComment($event) {
        let index = this.comments.findIndex((element) => {
            return element.id === $event.id;
        });

        this.comments[index].body = $event.body;
    }
}

再次打开浏览器,你就可以编辑评论了。

删除评论

跟上面的更新评论一样,我们增加一个按钮和事件就行了,具体代码如下:

//CommentItem

//Template
<div>
    <button @click="saveEdit">Update</button>
    <button @click="resetEdit">Cancel</button>
    <button @click="deleteComment">Delete</button>
</div>

//Script
deleteComment() {
    this.$emit('comment-deleted', {
        'id': this.comment.id,
    });
}

//Comments Manager

//Template
<comment v-for="comment in comments"
         :key="comment.id"
         :user="user"
         :comment="comment"
         @comment-updated="updateComment($event)"
         @comment-deleted="deleteComment($event)">
</comment>

//Script
deleteComment($event) {
    let index = this.comments.findIndex((element) => {
        return element.id === $event.id;
    });

    this.comments.splice(index, 1);
}

添加评论

搞完了更新删除评论,我们继续来搞添加评论吧。

我们搞得简单点,直接在CommentsManager里面增加。

<template>
    <div>
        <div>
            <div>
                <h2>Comments</h2>
            </div>
            <textarea placeholder="Add a comment"
                          class="border">
              </textarea>
            <div>
                <button>Save</button>
                <button>Cancel</button>
            </div>
        </div>
        <div>
            <comment v-for="comment in comments"
                     :key="comment.id"
                     :user="user"
                     :comment="comment"
                     @comment-updated="updateComment($event)"
                     @comment-deleted="deleteComment($event)">
            </comment>
        </div>
    </div>
</template>

为了实现添加功能,我们还需要添加一个saveComment的方法,并且添加一个data.body的属性到data,而且还要给textarea 添加一个v-model。

//template
<div>
            <div>
                <h2>Comments</h2>
            </div>
            <textarea v-model="comments.body"
                placeholder="Add a comment"
                class="border">
              </textarea>
            <div>
                <button @click="saveComment">Save</button>
                <button>Cancel</button>
            </div>
        </div>
//script
saveComment() {
                let newComment = {
                    id: this.comments[this.comments.length - 1].id + 1,
                    body: this.comments.body,
                    edited: false,
                    created_at: new Date().toLocaleString(),
                    author: {
                        id: this.user.id,
                        name: this.user.name,
                    }
                }

                this.comments.push(newComment);

                this.comments.body = '';
            },

打开浏览器,你会发现添加功能有了。

添加评论

总结

好了,今天先到这里,界面有点丑陋,不过几本的CURD已经实现了,我们下一篇文章继续实现增加Tailwind CSS,让界面优雅点。

使用Vue.js、Laravel和Tailwind CSS构建评论系统-(一)
Tagged on:         

35 thoughts on “使用Vue.js、Laravel和Tailwind CSS构建评论系统-(一)

  • 2019-02-28 at 19:35
    Permalink

    Simply want to say your article is as astounding.
    The clearness in your post is just cool and i could assume you are an expert on this subject.
    Well with your permission allow me to grab your RSS feed to keep up to date with forthcoming post.

    Thanks a million and please keep up the rewarding
    work. http://dominoqiu.link/ref.php?ref=DOMINO_QIU

    Reply
  • 2019-03-11 at 18:37
    Permalink

    Wow that was unusual. I just wrote an extremely long comment but after
    I clicked submit my comment didn’t show up. Grrrr…
    well I’m not writing all that over again. Regardless, just wanted
    to say great blog!

    Reply
  • 2019-03-15 at 14:48
    Permalink

    Greetings! I’ve been following your web site for a long time now and finally
    got the bravery to go ahead and give you a shout out from Porter Texas!
    Just wanted to mention keep up the fantastic work!
    I’ve been surfing online more than three hours today, yet I never found any interesting article like yours.
    It is pretty worth enough for me. In my view, if all web owners and bloggers made good content as you did, the web will be much more useful than ever before.

    This is a topic that is near to my heart… Many thanks! Where are your contact details though?
    http://samsung.com

    Reply
  • 2019-04-01 at 11:13
    Permalink

    What’s Taking place i am new to this, I stumbled upon this I’ve found It positively helpful and it has aided me out loads.
    I’m hoping to give a contribution & help other customers like its helped me.
    Good job. https://caferule.com/

    Reply
  • 2019-04-09 at 15:12
    Permalink

    Greetings! Very useful advice within this post!

    It is the little changes which will make the most significant changes.
    Thanks a lot for sharing!| I seriously love your
    website.. Very nice colors & theme. Did you develop this web site
    yourself? Please reply back as I?m trying to create my own blog and would love to find out where you got this from
    or what the theme is called.
    Appreciate it! https://clindoeilmontreal.ca/services/

    Reply
  • 2019-04-11 at 23:39
    Permalink

    Howdy would you mind letting me know which webhost you’re using?

    I’ve loaded your blog in 3 different browsers and I
    must say this blog loads a lot quicker then most. Can you
    recommend a good web hosting provider at a honest price?
    Thank you, I appreciate it!

    Reply
  • 2019-04-12 at 19:13
    Permalink

    Its like you learn my mind!
    You appear to understand a
    lot about this, like you wrote the ebook in it or something.
    I feel that you just can do with a few percent to pressure the message
    home
    a little bit, however instead of that, this is
    wonderful
    blog. An excellent read.
    I will certainly be back.|
    I visited multiple web sites but the audio feature for audio songs existing at this web
    site is genuinely wonderful.|
    Hello, i read your blog occasionally and i own a similar one and
    i was just wondering if you get a lot of spam responses?
    If so how do you reduce it, any plugin or anything you can advise?
    I get so much lately it?s driving me mad so any assistance is
    very much appreciated.|
    Greetings! Very helpful advice in this particular post!

    It is the little changes which will make the most significant changes.
    Thanks a lot for sharing!|
    I absolutely love your blog.. Very nice colors & theme. Did you
    build this site yourself? Please reply back as I?m trying to
    create my own personal blog and would like
    to find out where you got this from or what the theme
    is called. Cheers! https://www.entreprisesjosemelo.ca

    Reply
  • 2019-04-13 at 14:11
    Permalink

    Please let me know if you’re looking for a article writer for your site.
    You have some really good articles and I believe I would be a good asset.
    If you ever want to take some of the load off, I’d absolutely love to write some content for your blog in exchange for a
    link back to mine. Please shoot me an e-mail if interested.

    Thanks!

    Reply
  • 2019-04-13 at 19:04
    Permalink

    Thank you for writing this awesome article.
    I’m a long time reader but I’ve never been compelled to leave a comment.
    I subscribed to your blog and shared this on my Facebook.
    Thanks again for a great post! https://tesgo.ca

    Reply
  • 2019-04-13 at 19:20
    Permalink

    A person necessarily
    assist to make severely posts
    I would state. That is the very first time I frequented your
    website page and up to now? I amazed with the research you made to make this
    actual put up amazing. Excellent process!|
    Heya i am for the primary time here. https://www.lmesthetique.ca

    Reply
  • 2019-04-13 at 21:38
    Permalink

    I visited various web pages however the audio feature for audio songs current at this site is really marvelous.

    Reply
  • 2019-04-13 at 22:51
    Permalink

    Hello would you mind letting me know
    which web host you?re working with? I?ve loaded your blog
    in 3 completely different browsers and I must say this blog loads a
    lot faster then most.
    Can you suggest a good hosting provider at a
    fair price? Kudos, I appreciate it! https://www.josee-lemieux.com

    Reply
  • 2019-04-13 at 23:32
    Permalink

    Howdy, I do believe your blog might be having internet browser compatibility problems.
    When I look at your web site in Safari, it looks fine however, when opening in Internet
    Explorer, it has some overlapping issues.

    I simply wanted to provide
    you with a quick heads up! Besides that, fantastic blog! https://ultrascoot.com/gps-speedometer-lcd-12-volts.html

    Reply
  • 2019-04-14 at 04:49
    Permalink

    You’re so cool! I ddo not believe I’ve read something like this
    before. So great to find someone with some original thoughts on this subject.
    Really.. thank yyou for starting this up. This web site is one thing that is needed on the internet, someone with some originality!

    Reply
  • 2019-04-17 at 15:44
    Permalink

    Thank you for posting this awesome article. I’m a long
    time reader but I’ve never been compelled to leave a
    comment. I subscribed to your blog and shared this on my Facebook.
    Thanks again for a great post! https://www.publissoft.mx

    Reply
  • 2019-04-17 at 15:45
    Permalink

    Thanks for publishing this awesome article. I’m a long
    time reader but I’ve never been compelled to leave
    a comment. I subscribed to your blog and shared this on my Facebook.
    Thanks again for a great article! https://www.perform-art.com

    Reply
  • 2019-04-17 at 15:54
    Permalink

    Thank you for writing this awesome article. I’m a long time reader but I’ve never been compelled to leave
    a comment. I subscribed to your blog and shared this
    on my Facebook. Thanks again for a great post! https://www.publissoft.es

    Reply
  • 2019-04-17 at 19:37
    Permalink

    Hello there! This post could not be written any better!
    Reading this post reminds me of my good old room mate!
    He always kept talking about this. I will forward this post to him.
    Pretty sure he will have a good read. Many thanks for sharing! https://www.tosuresure.com

    Reply
  • 2019-04-17 at 21:18
    Permalink

    What a fantastic post! This is so chock full of useful information I can’t
    wait to dig deep and start utilizing the resources you have given me.

    Your exuberance is refreshing. Thanks for a great post! https://publissoft.com

    Reply
  • 2019-04-18 at 16:35
    Permalink

    Having read this I thought it was really enlightening. I appreciate you
    spending some time and energy to put this information together.
    I once again find myself spending way too much time both reading and commenting.
    But so what, it was still worth it!

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *