vue-组件评论功能的实现

效果图

效果图

起步

涉及知识:

  • <code>vue父子组件</code>定义以及传值
  • <code>H5 localStorage</code>
  • <code>JSON.stringify()</code>和<code>JSON.parse()</code>

效果分析

页面构成

  • 父组件包含评论列表
  • 子组件包含评论人、评论内容以及评论时间


    页面结构

发表评论功能[子组件]

  1. 先组织出一个最新的评论数据 如:<code>{user:'张三',content:'今天天气不错~'}</code>
  2. 定义变量<code>var list</code>。先从localStorage获取到之前评论数据(string),转换为一个数组对象,<code>JSON.parse()</code>【从一个字符串中解析出json对象,再<code>localStorage.getItem('cmts')||'[]'</code>
  3. 把组织出的最新的评论数据push至list数组 如:<code>list.unshift(最新的评论数据)</code>
    注:unshift()-----向数组的开头添加一个或多个元素,并且返回新的长度
  4. 把第一步得到的评论数据,保存到localStorage中
    <code>注:</code>
    4.1 localStorage只支持存放字符串数据,要先JSON.stringify。JSON.stringify()【从一个对象中解析出字符串】
    4.2 把最新的评论列表数组,存入本地存储localStorage中,首先调用JSON.stringify转为数据字符串【localStorage只支持存放字符串数据】,然后调用localStorage.setItem('','')
  5. 父组件把加载评论功能传递给子组件(子组件可以调用父组件函数),点击发表评论,从本地的localStoage中,加载评论列表 <code>$emit()</code>

加载评论列表[父组件]

  1. 定义变量<code>var list</code>。先从localStorage获取到之前评论数据(string),转换为一个数组对象,<code>JSON.parse()</code>【从一个字符串中解析出json对象,再<code>localStorage.getItem('cmts')||'[]'</code>
  2. created()钩子函数开始执行时,从本地的localStoage中取出数据,加载评论列表

代码实现

页面构成

注:这里的样式均引用<code>bootstrap</code>

<div id="app">
    <!--调用定义子组件 && 定义父组件函数-->
    <cmt-box @func="loadComments"></cmt-box>

    <!--评论列表-->
    <ul class="list-group">
        <li class="list-group-item" v-for="item in list" :key="item.id">
            <span class="badge">评论人:{{item.user}}</span>
            {{item.content}}
        </li>
    </ul>
    
</div>
<!--子组件:评论人、评论内容以及评论时间-->
<template id="tmp1">
    <div>
        <div class="form-group">
            <label>评论人:</label>
            <input type="text" class="form-control" v-model="user">
        </div>
        <div class="form-group">
            <label>评论内容:</label>
            <textarea class="form-control" v-model="content"></textarea>
        </div>
        <div class="form-group">
            <input type="button" value="发表评论" class="btn btn-primary" @click="postComment">
        </div>
    </div>
</template>

数据:

<script>

var commentBox={     //定义子组件
    template:'#tmp1',     //定义子组件模板对象
    data(){
        return {
            user:'',      //评论人 
            content:''    //评论内容
        }
    },
}

var vm=new Vue({   //父组件
    el:'#app',
    data:{
        list:[
            /*假数据*/
            {id:Date.now(),user:'李白',content:'天生我材必有用'},
            {id:Date.now(),user:'江小白',content:'劝君更尽一杯酒'}
        ]
    },
    /*注册子组件*/
    components:{
        'cmt-box':commentBox
    }
    });
</script>

发表评论功能[子组件]

methods:{
    /*点击发表评论按钮触发函数*/
    postComment(){
        /*组织出一个最新的评论数据*/
        var comment={id:Date.now(),user:this.user,content:this.content}

        /*localStorage获取到之前评论数据(string),转换为一个数组对象*/
        var list=JSON.parse(localStorage.getItem('cmts')||'[]')

        /*把组织出的最新的评论数据push至list数组*/
        list.unshift(comment)

        /*重新保存最新的评论*/
        localStorage.setItem('cmts',JSON.stringify(list))

        /*清空输入框*/
        this.user=this.content=''

        /*子组件调用父组件加载评论列表功能函数*/
        this.$emit('func')
    }
}

localStorage存入效果:[点击f12查看]

localStorage

加载评论列表[父组件]

methods:{
    /*加载评论列表*/
    loadComments(){ 
        /*从本地的localStoage中,加载评论列表*/
        var list=JSON.parse(localStorage.getItem('cmts')||'[]')
        this.list=list
    }
},
/*页面刚加载执行函数*/
created(){
    this.loadComments()
},

完整代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>评论功能</title>
    <script src="vue.js"></script>
    <link rel="stylesheet" href="bootstrap/css/bootstrap.min.css">
</head>

<body>
    <div id="app">
        <cmt-box @func="loadComments"></cmt-box>

        <ul class="list-group">
            <li class="list-group-item" v-for="item in list" :key="item.id">
                <span class="badge">评论人:{{item.user}}</span>
                {{item.content}}
            </li>
        </ul>
        
    </div>

    <template id="tmp1">
        <div>
            <div class="form-group">
                <label>评论人:</label>
                <input type="text" class="form-control" v-model="user">
            </div>
            <div class="form-group">
                <label>评论内容:</label>
                <textarea class="form-control" v-model="content"></textarea>
            </div>
            <div class="form-group">
                <input type="button" value="发表评论" class="btn btn-primary" @click="postComment">
            </div>
        </div>
    </template>
    <script>
        var commentBox={
            template:'#tmp1',
            data(){
                return {
                    user:'',
                    content:''
                }
            },
            methods:{
                postComment(){
                    var comment={id:Date.now(),user:this.user,content:this.content}
                    var list=JSON.parse(localStorage.getItem('cmts')||'[]')
                    list.unshift(comment)
                    localStorage.setItem('cmts',JSON.stringify(list))
                    this.user=this.content=''
                    this.$emit('func')
                }
            }
        }
        var vm=new Vue({
           el:'#app',
           data:{
               list:[
                   {id:Date.now(),user:'李白',content:'天生我材必有用'},
                   {id:Date.now(),user:'江小白',content:'劝君更尽一杯酒'},
                   {id:Date.now(),user:'小马',content:'我姓马,风吹草低见牛羊'}
               ]
           },
           methods:{
               loadComments(){
                 var list=JSON.parse(localStorage.getItem('cmts')||'[]')
                 this.list=list
               }
           },
           created(){
               this.loadComments()
           },
           components:{
               'cmt-box':commentBox
           }
        });
    </script>
</body>

</html>

小结

  • vue父子组件传函数方法:
    • 父组件定义函数---loadComments(){ …… }
    • 子组件定义父组件函数方法---@func="loadComments"
    • 子组件引用父组件函数方法---this.$emit('func')
  • H5 localStorage:
    • localStorage中一般浏览器支持的是5M大小
    • localStorage.setItem("key","value"):存储名字为key的一个值value,如果key存在,就更新value
    • localStorage.getItem("key"):获取名称为key的值,如果key不存在则返回null
    • localStorage.removeItem("key"):删除名称为"key"的信息,这个key所对应的value也会全部被删除
    • localStorage.clear():清空localStorage中所有信息
  • JSON.stringify()和JSON.parse()
    • JSON.parse(); 将字符串格式转换成JSON对象进行处理
    • JSON.stringify(); 将JSON对象转换成字符串格式

来源我的博客:我的博客

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,898评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,401评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,058评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,539评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,382评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,319评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,706评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,370评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,664评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,715评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,476评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,326评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,730评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,003评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,275评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,683评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,877评论 2 335