今天的内容有点多哦,使用Vue实现仿新浪微博评论功能

Vue
306
0
0
2022-04-21

好了,实在一点,先看图说话如图1-1-1:

今天的内容有点多哦,使用Vue实现仿新浪微博评论功能

图1-1-1

都别急,其实实现起来很简单的,下面一步一步跟着走吧。

一、准备工作

由于我们需要将数据保存至服务器,所以这里需要写个服务器代码,我使用的是php 代码。

1.首先连接数据库如下图:

今天的内容有点多哦,使用Vue实现仿新浪微博评论功能

连接数据库mysql,创建myword数据库,并生成weibo数据表

注: 这里需要一点php 的知识,如果有不知道的,可以自己百度搜索关于php 操作 mysql 的代码实现。

简单说一下其步骤:

(1) 通过服务器名,数据库名及密码连接数据库。

(2) 设置数据库的编码,创建数据库myword.

(3) 选择myword数据库,在myword数据库中创建表格weibo,并且设置表格字段。

(4) 开始执行mysql 数据操作。

2. 编写服务器方法,用于接收页面请求过来的参数实现具体的业务逻辑。

今天的内容有点多哦,使用Vue实现仿新浪微博评论功能

图1-1-2

今天的内容有点多哦,使用Vue实现仿新浪微博评论功能

图1-1-3

以上便是服务器端的代码,由于我主要想说明的是Vue 的运用,所以服务端代码这里不做详解。

3. 编写html 布局如下图1-1-4:

今天的内容有点多哦,使用Vue实现仿新浪微博评论功能

图1-1-4

注:在编写上述代码之前,需要引入css 样式图1-1-5。

今天的内容有点多哦,使用Vue实现仿新浪微博评论功能

图1-1-5

上面的代码应该没有难度,基本上应该可以看得懂吧,如果有看不懂的朋友,欢迎留言,有问必答。

二、业务实现

  1. 点击提交按钮时执行事件调用 add()方法将数据评论的内容提交到服务器,并请求服务器获取最新数据,刷新界面。

今天的内容有点多哦,使用Vue实现仿新浪微博评论功能

图1-1-6

2. Vue初始化时在created中执行dataReflush() 方法,获取当前评论的数据及页码。

今天的内容有点多哦,使用Vue实现仿新浪微博评论功能

图1-1-7

3. Vue过虑器的运用如图1-1-8

今天的内容有点多哦,使用Vue实现仿新浪微博评论功能

图1-1-8

今天的内容有点多哦,使用Vue实现仿新浪微博评论功能

图1-1-9

三、Vue的生命周期

1. 这里为什么要说明一下呢,因为上面有个需求,当用户刷新界面时,需要将历史留言内容显示出来,所以在这里就需要了解一下Vue 的生命周期了,效果如下图1-2-1

今天的内容有点多哦,使用Vue实现仿新浪微博评论功能

图1-2-1

注:上面展示的是Vue 的完整生命周期。

(1) created ---------创建Vue 实例,这里也可以放至初始的化的数据或调用的方法。

(2) beforeCompile ----- 编译之前,Vue 代码在html 里展示时会将Vue 的代码进行编译。

(3) compiled ------ Vue 代码编译完成。

(4) ready ----- 准备好了界面,可以展示数据了。 这里同样可以放至获取请求数据的方法。

(5) beforeDestroy ----- Vue 对象销毁之前

(6) destroyed ------ Vue 对象销毁完成

2. 编写一个例子,实现如下图1-2-2

今天的内容有点多哦,使用Vue实现仿新浪微博评论功能

图1-2-2

Vue 实例代码如下图1-2-3

今天的内容有点多哦,使用Vue实现仿新浪微博评论功能

图1-2-3

注: 这里所描述Vue 的生命周期指的是Vue1.0 版本,由于我也是初学者,在学习2.0 之前,我想要去先了解1.0版,这样更快上手2.0.

四、贴代码

  1. weibo.php 代码
<?php
/*
**********************************************
Date:2012-4-5
usage:
weibo.php?act=add&content=xxx添加一条
返回:{error:0, id: 新添加内容的ID, time: 添加时间}
weibo.php?act=get_page_count获取页数
返回:{count:页数}
weibo.php?act=get&page=1获取一页数据
返回:[{id: ID, content: "内容", time: 时间戳, acc: 顶次数, ref: 踩次数}, {...}, ...]
weibo.php?act=acc&id=12顶某一条数据
返回:{error:0}
weibo.php?act=ref&id=12踩某一条数据
返回:{error:0}
注意:服务器所返回的时间戳都是秒(JS是毫秒)
**********************************************
*/
//创建数据库之类的
$db=@mysql_connect('localhost', 'root', 'root') or @mysql_connect('localhost', 'root', 'root');
mysql_query("set names 'utf8'");
mysql_query('CREATE DATABASE myword');
mysql_select_db('myword');
$sql= <<< END
CREATE TABLE `myword`.`weibo` (
`ID` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`content` TEXT NOT NULL ,
`time` INT NOT NULL ,
`acc` INT NOT NULL ,
`ref` INT NOT NULL
) CHARACTER SET utf8 COLLATE utf8_general_ci
END;
mysql_query($sql);
header('
Access-Control-Allow-Origin:*');//注意!跨域要加这个头 
$myAct=$_GET['act'];
$PAGE_SIZE=5;
switch($myAct)
{
    case 'add':
        $content=urldecode($_GET['content']);
        $time=time();
        $content=str_replace("\n", "", $content);
        $sql="INSERT INTO weibo (ID, content, time, acc, ref) VALUES(0, '{$content}', {$time}, 0, 0)";
        mysql_query($sql);
        $res=mysql_query('SELECT LAST_INSERT_ID()');
        $row=mysql_fetch_array($res);
        $id=(int)$row[0];
        echo "{\"error\": 0, \"id\": {$id}, \"time\": {$time}}";
        break;
    case 'get_page_count':
        $sql="SELECT COUNT(*)/{$PAGE_SIZE}+1 FROM weibo";
        mysql_query($sql);
        $res=mysql_query($sql);
        $row=mysql_fetch_array($res);
        $count=(int)$row[0];
        echo "{\"count\": {$count}}";
        break;
    case 'get':
        $page=(int)$_GET['page'];
        if($page<1)$page=1;
        $s=($page-1)*$PAGE_SIZE;
        $sql="SELECT ID, content, time, acc, ref FROM weibo ORDER BY time DESC LIMIT {$s}, {$PAGE_SIZE}";
        $res=mysql_query($sql);
        $aResult=array();
        while($row=mysql_fetch_array($res)){
            $arr=array();
            array_push($arr, '"id":'.$row[0]);
            array_push($arr, '"content":"'.$row[1].'"');
            array_push($arr, '"time":'.$row[2]);
            array_push($arr, '"acc":'.$row[3]);
            array_push($arr, '"ref":'.$row[4]);
            array_push($aResult, implode(',', $arr));
        }
        if(count($aResult)>0){
            echo '[{'.implode('},{', $aResult).'}]';
        }else{
            echo '[]';
        }
        break;
    case 'acc':
        $id=(int)$_GET['id'];
        $res=mysql_query("SELECT acc FROM weibo WHERE ID={$id}");
        $row=mysql_fetch_array($res);
        $old=(int)$row[0]+1;
        $sql="UPDATE weibo SET acc={$old} WHERE ID={$id}";
        mysql_query($sql);
        echo '{"error":0}';
        break;
    case 'ref':
        $id=(int)$_GET['id'];
        $res=mysql_query("SELECT ref FROM weibo WHERE ID={$id}");
        $row=mysql_fetch_array($res);
        $old=(int)$row[0]+1;
        $sql="UPDATE weibo SET ref={$old} WHERE ID={$id}";
        mysql_query($sql);
        echo '{"error":0}';
        break;
    case 'del':
        $id=(int)$_GET['id'];
        $sql="DELETE FROM weibo WHERE ID={$id}";
//echo $sql;exit; 
        mysql_query($sql);
        echo '{"error":0}';
        break;
}
?>

2. weibo.css样式

@charset "utf-8";body,ul,ol,li,dl,dt,dd,p,h1,h2,h3,h4,h5,h6,form,fieldset,table,td,img,div{margin:0;padding:0;border:0}
body{font-size:12px;font-family:"Microsoft YaHei"}
ul,ol{list-style-type:none}
select,input,img,select{vertical-align:middle}
a{text-decoration:underline;color:#313030}
a{blr:expression(this.onFocus=this.blur())}
input,textarea{outline:0;resize:none}
a{outline:0}
.znsArea{width:755px;overflow:hidden;margin:0 auto;font-family:"Microsoft YaHei"}
.commentOn{width:753px;display:block;overflow:hidden;border:#a5bcff solid 1px;background:#f3f8fd;margin-top:25px;font-family:Verdana}
.reply{overflow:hidden;padding:10px 20px;background:#FFF;border-top:#e9e9e9 solid 1px;border-bottom:#e9e9e9 solid 1px}
.userInfo{display:block;overflow:hidden;height:25px;border-bottom:#bababa solid 1px}
.userName{float:left;background:url(../img/userBj.png) left center no-repeat;padding-left:15px;color:#000;font-size:14px;font-weight:bold}
.replyTime{float:left;color:#8b8585;line-height:30px;font-size:11px}
.replyContent{line-height:24px;font-size:14px;color:#2b2b2b;font-family:"Microsoft YaHei"}
.operation{clear:both;width:100%;height:30px;margin-top:8px}
.handle{float:right;padding-top:6px}
.handle a{text-decoration:none;float:left;margin-left:12px;background:url(../img/icons.png) 0 0 no-repeat;height:18px;line-height:18px;padding-left:20px}
.handle .top_icon{background-position:0 0}
.handle .down_icon{background-position:0 -17px}
.handle .cut{background-position:0 -33px}
.handle a:active{color:#09F}
.noContent{text-align:center;display:block;background:#FFF;font:14px/2.3 "Microsoft YaHei";border-bottom:#e9e9e9 solid 1px;border-top:#e9e9e9 solid 1px;color:#999}
.takeComment{width:713px;display:block;overflow:hidden;border:#a5bcff solid 1px;background:#f3f8fd;margin-top:25px;font-family:Verdana;padding:15px 20px}
.takeTextField{width:701px;height:70px;border:#b1b1b1 solid 1px;clear:both;display:block;margin:10px 0 10px 0;line-height:20px;padding:5px;box-shadow:inset 0 0 5px #DDD;font-family:"Microsoft YaHei"}
.takeSbmComment{display:block;overflow:hidden}
.takeSbmComment span{float:right;color:#CCC;line-height:37px;padding-right:10px}
.inputs{float:right;width:125px;height:37px;border:none 0;background:tranparent;background:url(../img/takeSbmComment.png) left top no-repeat;cursor:pointer;opacity:.8}
.inputs:hover{opacity:1}
.inputs:active{opacity:.9}
.messList{overflow:hidden}
.page{text-align:right;font-size:0;font-family:Verdana;padding:10px 16px}
.page a{display:inline-block;height:20px;padding:0 7px;border:#CCC solid 1px;font:12px/20px Verdana;text-decoration:none;margin-left:5px;background:#FFF}
.page a:hover{background:#09F;color:#FFF;border-color:#09F}
.page .active{background:#CCC}
.page a:active{opacity:.8}

3. 微博评论HTML代码

<html>
<head> 
    <title>访新浪微博留言</title> 
    <meta charset="utf-8"/> 
    <script src="lib/vue/vue.js" ></script> 
    <script src="lib/vue/vue-resource.js" > </script> 
    <link href="style/weibo.css" rel="stylesheet" type="text/css" /> 
    <script> 
        Vue.filter('date',function(input){ // 由于服务器返回的时间为毫秒数,所以这里需要进行转换 
            var oDate=new Date(input*1000);
            return oDate.getFullYear()+'-'+(oDate.getMonth()+1)+'-'+oDate.getDate()+' '+oDate.getHours()+':'+oDate.getMinutes()+':'+oDate.getSeconds();
        });
        window.onload = function (){
            var apiUrl = "weibo.php" // 接收用户参数的网址 
            new Vue({
                el:".znsArea",
                data:{
                    msgData:[],
                    t1:"",
                    nowIndex:1,
                    pageSize:0
                },
                methods: {
                    add: function(){ // 提交评论内容 
                        var tapiUrl = apiUrl+"?act="+"add&content="+this.t1;
                        this.$http.get(tapiUrl).then(function(res){
                            this.t1 = "";
                            this.dataReflush();
                        },function(errorData){
                            console.log(errorData);
                        });
                        this.t1 = "";
                    },
                    getPageData: function(page){ //根据页码获取评论内容 
                        var tapiUrl = apiUrl+"?act="+"get&page="+page;
                        this.$http.get(tapiUrl).then(function(successData){
                            this.msgData = []; // 避免重复添加,故每次清空记录 
                            var arr=successData.data;
                            for(var i=0; i<arr.length; i++){
                                this.msgData.push({
                                    content:arr[i].content,
                                    time:arr[i].time,
                                    acc:arr[i].acc,
                                    ref:arr[i].ref,
                                    id:arr[i].id
                                });
                            }
                        },function(errorData){
                            console.log("=================getPageData=======errorData==========="+errorData);
                        });
                    },
                    getPageCount: function(){ //根据获取评论内容总页码 
                        var tapiUrl = apiUrl+"?act=get_page_count";
                        this.$http.get(tapiUrl).then(function(res){
                            this.pageSize = res.data.count;
                        },function(errorData){
                            console.log(errorData);
                        });
                    },
                    dataReflush: function(){
                        this.getPageData(this.nowIndex);
                        this.getPageCount();
                    }
                },
                created:function(){
                    this.dataReflush();
                    console.log("==========created============");
                }
            });
        }
    </script>
</head>
<body>
<div class="znsArea"> 
    <!--留言--> 
    <div class="takeComment"> 
        <textarea name="textarea" class="takeTextField" id="tijiaoText" v-model="t1" @keydown.enter="add" placeholder="在这里输入你想要说的话吧"></textarea> 
        <div class="takeSbmComment"> 
            <input type="button" class="inputs" value="" @click="add" /> 
            <span>(可按 Enter 提交)</span> 
        </div> 
    </div> 
    <!--已留--> 
    <div class="commentOn"> 
        <div class="noContent" v-show="msgData.length==0">暂无留言</div> 
        <div class="messList"> 
            <div class="reply" v-for="item in msgData" v-cloak> 
                <p class="replyContent">{{item.content}}</p> 
                <p class="operation"> 
                    <span class="replyTime">{{item.time|date}}</span> 
                    <span class="handle">
<a href="javascript:;" class="top">{{item.acc}}</a>
<a href="javascript:;" class="down_icon">{{item.ref}}</a>
<a href="javascript:;" class="cut">删除</a>
</span> 
                </p> 
            </div> 
        </div> 
        <div class="page"> 
            <a v-for="value in pageSize" class="active:value == 1" @click="getPageData(value)">{{value}}</a> 
        </div> 
    </div>
</div>
</body>
</html>

4. Vue 生命周期的html 代码

<html>
<head> 
    <title>熟悉Vue的生命周期</title> 
    <meta charset="utf-8"/> 
    <script src="lib/vue/vue.min.js" ></script> 
    <script> 
        window.onload = function (){
            var vm = new Vue({
                el:"#box",
                data:{
                    destoryMsg:"Vue对象已销毁,不可用",
                    messages:[]
                },
                created: function(){
                    this.messages = [];
                    this.messages.push("====我执行了created=====方法");
                },
                beforeCompile: function(){
                    this.messages.push("====我执行了beforeCompile=====方法");
                },
                compiled: function(){
                    this.messages.push("====我执行了Compiled=====方法"
                    );
                },
                ready: function(){
                    this.destoryMsg = "Vue对象正常",
                        this.messages.push( "====我执行了ready=====方法"
                        );
                },
                beforeDestroy: function(){
                    console.log( "====我执行了beforeDestory=====方法");
                },
                destroyed: function(){
                    console.log("====我执行了Destoryed=====方法");
                }
            });
            document.getElementById("myClick").onclick=function(){
                vm.$data.destoryMsg = "Vue对象已销毁,不可用";
                alert("Vue对象已销毁");
                setTimeout(function(){ // 为了验证Vue 对象已销毁,使用了定时器函数,用户点按钮后2秒销毁
                    vm.$destroy();
                    console.log("=====Vue对象===="+vm.$el)
                },2000)
            };
        }
    </script>
</head>
<body>
<div id="box"> 
    <p v-for="word in messages" v-text="word"></p> 
    <button id="myClick">点我执行销毁Vue</button> 
    <p >{{destoryMsg}}</p>
</div>
</body>
</html>