基于Vue+nodejs+Element-ui的聊天框项目(一)

简介: 基于Vue+nodejs+Element-ui的聊天框项目

一、项目简介

本项目基于纯前端(移动端)技术开发一个聊天系统,界面美观大方,采用Nodejs+Vue+ElemenetUI开发实现,主要包含:登录注册,修改个人资料,更改头像,发送消息,单对单聊天等。

二、环境介绍

语言环境:nodejs

数据库:MySQL

应用服务器:nodejs

开发工具:vscode

开发技术:nodejs+vue+elementUI

三、系统展示

c6e230919b9b497987d2c55fcfefa191.png

4307033e637741cfa60861b5c900fe0b.png


7eda145f75174614bc7e93c8f80de8cc.png


2ab23b2aa4264a67b1ea2e2be1998cf4.png

0e90d7687f9d45e3a7e398edfacf1c43.png

四、视频功能展示

image.png


基于Vue+nodejs+Element-ui的聊天系统项目

五、前端核心代码展示

  • 头部导航功能代码
<template>
  <div>
    <el-tabs v-model="activeName" type="card" @tab-click="handleClick">
      <el-tab-pane label="用户" name="user"><User></User></el-tab-pane>
      <el-tab-pane label="我的" name="mine"><Mine></Mine></el-tab-pane>
    </el-tabs>
  </div>
</template>
<script>
import User from "@/views/user/index.vue";
import Mine from "@/views/mine/index.vue";
export default {
  components: {
    User,
    Mine,
  },
  data() {
    return {
      activeName: "Home",
    };
  },
  mounted() {
    this.activeName = this.$route.name;
  },
  methods: {
    handleClick(tab, event) {
      // console.log(this.activeName);
      this.$router.push({
        name: this.activeName,
      });
    },
  },
};
</script>
<style></style>
  • 登录注册页居中旋转功能代码
<template>
  <div class="box" :class="{ box_rolling: isRolling }">
    <div class="box_register"><register></register></div>
    <div class="box_login"><login></login></div>
  </div>
</template>
<script>
import login from "@/views/login/login.vue";
import register from "@/views/login/register.vue";
import { mapState } from "vuex";
export default {
  components: {
    login,
    register,
  },
  computed: {
    ...mapState(["isRolling"]),
  },
};
</script>
<style lang="scss" scoped>
.box {
  &_register,
  &_login {
    transform-style: preserve-3d; //表示所有子元素在3D空间中呈现
    backface-visibility: hidden; //元素背面向屏幕时是否可见
    transition-duration: 0.5s;
    transition-timing-function: "ease-in";
    background: #008080;
  }
  &_login {
    transform: rotateY(180deg);
    visibility: hidden; //元素不可见,但占据空间
    position: absolute;
    top: 0;
    bottom: 0;
    right: 0;
    left: 0;
  }
}
.box_rolling {
  .box_register {
    transform: rotateY(180deg);
    visibility: hidden;
  }
  .box_login {
    transform: rotateY(360deg);
    visibility: visible;
  }
}
</style>
  • 登录页代码
<template>
  <div class="box">
    <p class="title">欢迎登录</p>
    <input
      type="text"
      class="name"
      placeholder="请输入账号"
      v-model="username"
    />
    <input
      type="password"
      class="password"
      placeholder="请输入密码"
      v-model="password"
    />
    <button @click="add">登录</button>
    <p class="login">
      <span @click="addlogin">点击跳转到注册页</span>
    </p>
  </div>
</template>
<script>
export default {
  data() {
    return {
      username: "",
      password: "",
    };
  },
  methods: {
    addlogin() {
      this.$store.commit("addlogin");
    },
    add() {
      this.$axios({
        url: "/api/api/login",
        method: "POST",
        data: {
          username: this.username,
          password: this.password,
        },
      }).then(({ data }) => {
        console.log(data);
        localStorage.setItem("token", data.token);
        location.href = "/";
      });
    },
  },
};
</script>
<style lang="scss" scoped>
.box {
  width: 100%;
  height: 100vh;
  padding: 0 0.5rem;
  overflow: hidden;
  text-align: center;
  background-color: #f7f7f7;
  .title {
    font-size: 0.4rem;
    text-align: center;
    letter-spacing: 0.2rem;
    margin: 0.2rem 0 0.5rem;
    color: #7c7c7c;
  }
  .name,
  .password,
  .user {
    width: 100%;
    padding-left: 0.1rem;
    height: 0.5rem;
    border: 2px solid #cccccc;
    border-radius: 0.2rem;
    font-size: 0.15rem;
  }
  input::-webkit-input-placeholder {
    color: #97040b;
  }
  .password {
    margin-top: 0.75rem;
  }
  button {
    width: 0.6rem;
    height: 0.6rem;
    border-radius: 50%;
    background-color: #0b24fb;
    border: none;
    color: #fff;
    font-size: 0.1rem;
    margin-top: 0.5rem;
  }
  .login {
    display: flex;
    justify-content: flex-end;
    margin-top: 0.3rem;
    span {
      font-size: 0.1rem;
      color: #000;
      font-weight: 400;
    }
  }
}
</style>
  • 注册页代码
<template>
  <div class="box">
    <p class="title">欢迎注册</p>
    <input
      type="text"
      class="name"
      placeholder="请输入账号"
      v-model="username"
    />
    <input
      type="password"
      class="password"
      placeholder="请输入密码"
      v-model="password"
    />
    <button @click="add">注册</button>
    <p class="login">
      <span @click="addlogin">点击跳转到登录页</span>
    </p>
  </div>
</template>
<script>
export default {
  data() {
    return {
      username: "",
      password: "",
    };
  },
  methods: {
    addlogin() {
      this.$store.commit("addlogin");
    },
    add() {
      this.$axios({
        url: "/api/api/reguser",
        method: "POST",
        data: {
          username: this.username,
          password: this.password,
        },
      }).then(({ data }) => {
        console.log(data);
      });
    },
  },
};
</script>
<style lang="scss" scoped>
.box {
  width: 100%;
  height: 100vh;
  padding: 0 0.5rem;
  overflow: hidden;
  text-align: center;
  background-color: #f7f7f7;
  .title {
    font-size: 0.4rem;
    text-align: center;
    letter-spacing: 0.2rem;
    margin: 0.2rem 0 0.5rem;
    color: #7c7c7c;
  }
  .name,
  .password,
  .user {
    width: 100%;
    padding-left: 0.1rem;
    height: 0.5rem;
    border: 2px solid #cccccc;
    border-radius: 0.2rem;
    font-size: 0.15rem;
  }
  input::-webkit-input-placeholder {
    color: #97040b;
  }
  .password {
    margin-top: 0.75rem;
  }
  button {
    width: 0.6rem;
    height: 0.6rem;
    border-radius: 50%;
    background-color: #0b24fb;
    border: none;
    color: #fff;
    font-size: 0.1rem;
    margin-top: 0.5rem;
  }
  .login {
    display: flex;
    justify-content: flex-end;
    margin-top: 0.3rem;
    span {
      font-size: 0.1rem;
      color: #000;
      font-weight: 400;
    }
  }
}
</style>
  • 我的主页代码
<template>
  <div class="box">
    <div class="top">
      <img :src="imageUrl" class="avatar" />
      <p>
        {{ list.username }}
        <br />
        <router-link :to="{ name: 'setMessage' }">修改用户基本信息</router-link>
        <span @click="tuichu">退出</span>
      </p>
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      list: [],
      imageUrl: "",
    };
  },
  mounted() {
    this.list = this.$store.state.userInfo;
    this.imageUrl = this.list.image;
  },
  methods: {
    handleAvatarSuccess(res, file) {
      this.imageUrl = URL.createObjectURL(file.raw);
    },
    beforeAvatarUpload(file) {
      const isJPG = file.type === "image/jpeg";
      const isLt2M = file.size / 1024 / 1024 < 2;
      if (!isJPG) {
        this.$message.error("上传头像图片只能是 JPG 格式!");
      }
      if (!isLt2M) {
        this.$message.error("上传头像图片大小不能超过 2MB!");
      }
      return isJPG && isLt2M;
    },
    tuichu() {
      localStorage.removeItem("token");
      location.href = "/";
    },
  },
};
</script>
<style lang="scss" scoped>
.box {
  .top {
    display: flex;
    .avatar {
      width: 0.8rem;
      height: 0.8rem;
      display: block;
    }
    p {
      margin-left: 0.2rem;
      font-size: 0.25rem;
      a {
        text-decoration: none;
        font-size: 0.1rem;
        color: gray;
        margin-right: 0.2rem;
      }
    }
  }
}
</style>
  • 修改个人信息代码
<template>
  <div class="box">
    <div>
      <el-upload
        class="avatar-uploader"
        action="/api/api/upload"
        :show-file-list="false"
        :on-success="handleAvatarSuccess"
        :before-upload="beforeAvatarUpload"
      >
        <img v-if="imageUrl" :src="imageUrl" class="avatar" />
        <i v-else class="el-icon-plus avatar-uploader-icon"></i>
      </el-upload>
      <p>
        用户名:
        <el-input v-model="input" :placeholder="list.username"> </el-input>
      </p>
      <p>
        个人简介:
        <el-input
          type="textarea"
          :rows="2"
          placeholder="请输入内容"
          v-model="textarea"
        >
        </el-input>
      </p>
      <el-button type="primary" @click="add">提交</el-button>
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      list: [],
      imageUrl: "",
      input: "",
      textarea: "",
      image: "",
    };
  },
  mounted() {
    this.list = this.$store.state.userInfo;
    this.imageUrl = this.list.image;
    this.input = this.list.username;
    this.textarea = this.list.brief;
  },
  methods: {
    handleAvatarSuccess(res, file) {
      //   console.log(res, file.name);
      this.image = file.name;
      this.imageUrl = URL.createObjectURL(file.raw);
    },
    beforeAvatarUpload(file) {
      const isJPG = file.type === "image/jpeg";
      const isLt2M = file.size / 1024 / 1024 < 2;
      if (!isJPG) {
        this.$message.error("上传头像图片只能是 JPG 格式!");
      }
      if (!isLt2M) {
        this.$message.error("上传头像图片大小不能超过 2MB!");
      }
      return isJPG && isLt2M;
    },
    add() {
      this.$axios({
        url: `/api/my/setmessages`,
        method: "post",
        data: {
          image: this.image
            ? "http://127.0.0.1:830/api/uploads?img=image_" + this.image
            : this.list.image,
          username: this.input,
          brief: this.textarea,
        },
        headers: {
          Authorization: localStorage.getItem("token"),
        },
      }).then(({ data }) => {
        console.log(data);
        location.href = "/footer/mine";
      });
    },
  },
};
</script>
<style lang="scss" scoped>
.box {
  div {
    .avatar-uploader .el-upload {
      border: 1px dashed #d9d9d9;
      border-radius: 6px;
      cursor: pointer;
      position: relative;
      overflow: hidden;
    }
    .avatar-uploader .el-upload:hover {
      border-color: #409eff;
    }
    .avatar-uploader-icon {
      font-size: 28px;
      color: #8c939d;
      width: 178px;
      height: 178px;
      line-height: 178px;
      text-align: center;
    }
    .avatar {
      width: 178px;
      height: 178px;
      display: block;
    }
  }
}
</style>
相关文章
|
27天前
|
数据采集 监控 JavaScript
在 Vue 项目中使用预渲染技术
【10月更文挑战第23天】在 Vue 项目中使用预渲染技术是提升 SEO 效果的有效途径之一。通过选择合适的预渲染工具,正确配置和运行预渲染操作,结合其他 SEO 策略,可以实现更好的搜索引擎优化效果。同时,需要不断地监控和优化预渲染效果,以适应不断变化的搜索引擎环境和用户需求。
|
14天前
|
JavaScript 前端开发
如何在 Vue 项目中配置 Tree Shaking?
通过以上针对 Webpack 或 Rollup 的配置方法,就可以在 Vue 项目中有效地启用 Tree Shaking,从而优化项目的打包体积,提高项目的性能和加载速度。在实际配置过程中,需要根据项目的具体情况和需求,对配置进行适当的调整和优化。
|
1月前
|
JavaScript
如何在 Vue 项目中选择合适的模块格式
【10月更文挑战第20天】选择合适的模块格式需要综合考虑多个因素,没有一种绝对正确的选择。需要根据项目的具体情况进行权衡和分析。在实际选择过程中,要保持灵活性,根据项目的发展和变化适时调整模块格式。
21 7
|
26天前
Vue3 项目的 setup 函数
【10月更文挑战第23天】setup` 函数是 Vue3 中非常重要的一个概念,掌握它的使用方法对于开发高效、灵活的 Vue3 组件至关重要。通过不断的实践和探索,你将能够更好地利用 `setup` 函数来构建优秀的 Vue3 项目。
|
1月前
|
JavaScript 前端开发 编译器
在 Vue 项目中使用 ES 模块格式的优点
【10月更文挑战第20天】在 Vue 项目中使用 ES 模块格式具有众多优点,这些优点共同作用,使得项目能够更高效、更可靠地开发和运行。当然,在实际应用中,还需要根据项目的具体情况和需求进行合理的选择和配置。
33 6
|
26天前
|
JavaScript 测试技术 UED
解决 Vue 项目中 Tree shaking 无法去除某些模块
【10月更文挑战第23天】解决 Vue 项目中 Tree shaking 无法去除某些模块的问题需要综合考虑多种因素,通过仔细分析、排查和优化,逐步提高 Tree shaking 的效果,为项目带来更好的性能和用户体验。同时,持续关注和学习相关技术的发展,不断探索新的解决方案,以适应不断变化的项目需求。
|
1月前
|
SQL JavaScript 关系型数据库
node博客小项目:接口开发、连接mysql数据库
【10月更文挑战第14天】node博客小项目:接口开发、连接mysql数据库
|
NoSQL JavaScript 应用服务中间件
node+mongo + vue 开发管理平台部署到阿里云服务器入坑之旅
导语:使用vue+element-ui开发前端,node.js+express+mongodb开发后端,部署到阿里云服务器(镜像信息Node.js)。 1、申请阿里云服务器 可以申请一个最便宜的用来练手。
2711 0
|
2月前
|
JavaScript
NodeJs的安装
文章介绍了Node.js的安装步骤和如何创建第一个Node.js应用。包括从官网下载安装包、安装过程、验证安装是否成功,以及使用Node.js监听端口构建简单服务器的示例代码。
NodeJs的安装
|
1月前
|
JavaScript 开发工具 git
已安装nodejs但是安装hexo报错
已安装nodejs但是安装hexo报错
32 2
下一篇
无影云桌面