利用vue-cli创建的vue脚手架,实现留言板功能

1.搭建项目结构

命令行中创建vue项目,在src路径下的assets文件夹中创建images文件夹存放用户头像,并新建一个pages文件夹用于存放自己的vue文件。

项目初始结构如图里插入图片描述

2.创建组件

在pages文件夹中创建AlbumArticleHomeUCenterMessage五个组件,分别对应相册,文章,主页,个人中心,留言板。

3.编辑组件

编辑除留言板(Message.vue)之外的所有组件,此案例只针对留言板功能
编辑其他页面组件代码如下:

<template>
  <div class="home">
    <h2>主页页面</h2>
  </div>
</template>

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

<style>
</style>

编辑App.vue,导入并注册组件,编写页面结构,修改页面样式

<template>
  <div id="app">
    <h2>个人空间</h2>
    <ul class="nav">
      <li :class="{ active: page === 'Home' }" @click="page = 'Home'">主页</li>
      <li :class="{ active: page === 'Article' }" @click="page = 'Article'">
        文章
      </li>
      <li :class="{ active: page === 'Album' }" @click="page = 'Album'">
        相册
      </li>
      <li :class="{ active: page === 'Message' }" @click="page = 'Message'">
        留言板
      </li>
      <li :class="{ active: page === 'Ucenter' }" @click="page = 'Ucenter'">
        个人中心
      </li>
    </ul>
    <hr />
    <keep-alive>
      <component :is="page"></component>
    </keep-alive>
  </div>
</template>

<script>
import Album from "./pages/Album.vue";
import Article from "./pages/Article.vue";
import Home from "./pages/Home.vue";
import Message from "./pages/Message.vue";
import Ucenter from "./pages/Ucenter.vue";

export default {
  name: "App",
  components: {
    Album,
    Article,
    Home,
    Message,
    Ucenter,
  },
  data() {
    return {
      page: "Home",
    };
  },
};
</script>

<style>
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
html,
body {
  background-color: #eee;
}
.nav {
  margin: 50px 0;
  height: 50px;
  background-color: antiquewhite;
  font-size: 22px;
  display: flex;
  list-style: none;
}
.nav li {
  line-height: 40px;
  padding: 5px 20px;
  cursor: pointer;
}
.nav li:hover {
  font-weight: bold;
}
.nav li.active {
  color: orangered;
  border-bottom: 2px solid orangered;
}
</style>

编辑Message.vue,代码如下

<template>
  <div class="message">
      <h2>留言板</h2>
      <div class="input-msg">
          <textarea name="" id="msg" cols="50" rows="5" v-model.trim="content" @keyup.enter="sendMsg" placeholder="请输入评论内容"></textarea>
          <button class="send-msg" @click="sendMsg">发送留言</button>
      </div>
      <div class="history">
          <div class="msg-item" v-for="msg in msgList" :key="msg.id">
              <img class="header-img" :src="msg.img" alt="">
                <div>
                    <h2>作者:{{msg.author}}<small>{{msg.time | formatTime}}</small></h2>
                    <p class="cont">{{msg.content}}</p>
                    <p class="control">
                        <button class="btn btn-edit"  @click="editMsg(msg)">编辑</button>
                        <button class="btn btn-del" @click="delMsg(msg.id)">删除</button>
                    </p>
                </div>
          </div>
          <!-- <div class="msg-item">
              <img class="header-img" src="../assets/images/1.webp" alt="">
                <div>
                    <h2>作者:豆子<small>2022-10-14 15:03:26</small></h2>
                    <p>留言内容</p>
                </div>
          </div> -->
      </div>
  </div>
</template>

<script>
// 限于纯前端测试时使用
import m1 from "../assets/images/1.jpg"
import m2 from "../assets/images/2.jpg"
import m3 from "../assets/images/3.jpg"
import m4 from '../assets/images/4.jpg'
export default {
    created(){
        // 当前实例创建时,模拟从接口获取数据
        this.msgList=[
            {id:3,author: "尔尔",time:Date.now(),img:m1,content:"我也爱你!"},
            {id:2,author: "依依",time:Date.now(),img:m2,content:"我爱你!"},
            {id:1,author: "思思",time:Date.now(),img:m3,content:"我爱你爱你!"},
        ];
    },
    data(){
        return{
            // 双向绑定的留言内容
            content: "",
            // 留言内容
            msgList: [],
            // 声明编辑的id
            editId:""
        }
    },
    methods: {
        sendMsg () {
            // console.log("用户准备发表留言",this.content)
            if(this.content===""){
                alert("留言内容为空")
                return
            }
            if(this.editId){
                // 拆分数据
                let [content]=this.content.split(" ")
                let index = this.msgList.findIndex(msg=>msg.id === this.editId)
                this.msgList[index].content=content
                // 清空文本域、清空editId
                this.content=""
                this.editId=""
            }else {
                // 创建留言对象
                let id=this.msgList.length>0?this.msgList[0].id+1:1
                let m={id,author:"豆子",time: Date.now(),img:m4,content:this.content}
                // 添加留言
                this.msgList.unshift(m)
                // 清空留言框
                this.content=""
            }
        },
        editMsg(msg) {
            // 给编辑的id赋值
            this.editId = msg.id
            // 给输入框绑定的变量赋值(展示编辑数据)
            this.content = msg.content
        },
        delMsg(id) {
            // 二次确认
            const result = confirm("确认删除?")
            if (!result) return
            // 删除
            this.msgList = this.msgList.filter(msg => msg.id !== id)
            // 防止点击编辑之后在点击删除按钮出现的bug
            this.editId=""
            this.content=""
        },
    },
    filters: {
        formatTime:value=>{
            const date=new Date(value)
            return `${date.getFullYear()}${(date.getMonth()+1).toString().padStart(2,0)}${date.getDate().toString().padStart(2,0)}${date.getHours().toString().padStart(2,0)}${date.getMinutes().toString().padStart(2,0)}${date.getSeconds().toString().padStart(2,0)}`
        }
    }
}
</script>
<!-- 如果想让这里编写的样式只对当前组件有效,style上添加一个scoped属性-->
<style scoped>
.input-msg{
    width: 80%;
    margin: 10px auto;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
}
#msg{
    width: 100%;
    height: 180px;
    padding: 10px;
    outline: none;
    border: 1px solid rgba(219, 73, 73, 0.466);
    border-radius: 5px;
    resize: none;
    display: block;
    margin: 10px auto;
    font-size: 18px;
}
.send-msg{
    width: 200px;
    height: 40px;
    border: none;
    background-color: orangered;
    color: wheat;
    border-radius: 20px;
    cursor: pointer;
    font-size: 18px;
}
.send-msg:hover{
    background-color: rgb(34, 231, 109);
    color: #000;
}
.history{
    width: 80%;
    padding: 20px 10px;
    margin: 10px auto;
    background-color: #fff;
}
.msg-item{
    display: flex;
    padding: 10px;
    border-bottom: 1px dashed #888;
}
.msg-item img{
    width: 100px;
    height: 100px;
    border-radius: 10px;
}
.msg-item div{
    margin-left: 10px;
    width: 100%;
}
.msg-item div h2{
    font-size: 22px;
}
.msg-item div h2 small{
    font-size: 16px;
    color: #888;
    font-weight: 600;
    margin-left: 20px;
}
.msg-item div p.cont{
    font-size: 16px;
    color: #444;
    margin: 10px 0;
    word-wrap: break-word;
    word-wrap: break-word;
    white-space: pre-wrap;
    min-height: 50px;
    /* border: 1px solid red; */
}
.control{
    width: 100%;
    display: flex;
    justify-content: flex-end;
}
.btn{
    width: 80px;
    height: 30px;
    border: 1px solid #888;
    border-radius: 15px;
    cursor: pointer;
}
.btn-edit{
    background-color: rgb(20, 187, 247);
}
.btn-edit:hover{
    background-color: rgb(17, 148, 196);
    color: #fff;
}
.btn-del{
    background-color: rgb(247, 20, 88);
}
.btn-del:hover{
    background-color: rgb(192, 21, 72);
    color: #fff;
}
</style>

浏览器效果如图

在这里插入图片描述

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐