上一章--简单的聊天程序(一):HTML+CSS实现响应式界面已经实现了响应式的界面,接下来我们要实现一些简单的交互操作。
预期结果
在左边切换不同的对话人物,并显示与其聊天记录;在输入框输入文字后按下发送按钮就会显示在上方的聊天记录区域内,并在信息下方显示发送的时间;在信息数量变多屏幕显示不下时,显示页面滚动条。
Vue-cli的配置
vue-cli基于vue.js,可快速开发,快速生成工程化项目。首先我们对其配置,然后将上一章的HTML界面和css样式粘入。
首先我们在任意位置创建任意名的文件夹,我这里在桌面创建了名为projects的文件夹,如下图:
接下来依次点击VS code的这些部分调出终端:
确保正常安装了node.js和npm,没有安装的话可以去参考一下网络上其他作者写的文章,这里不再详细讲解。终端输入node -v查看node.js版本,我这里安装的比较早,不是最新版本,安装时直接安装最新版本即可。
接下来在终端输入命令npm install -g @vue/cli,让软件自行安装vue-cli:
安装完成后在终端输入下一条指令vue create project1,注意这里的“project1”是你自己的项目名称,可任意修改,程序会在此目录下创建一个你的项目名称的文件夹,里面包含了vue-cli的各个组件等。
输入命令后程序会让你选择使用vue3还是vue2,键盘上下键选择,回车键确定。这里我选择了vue3,即此界面下直接回车。
终端显示以下文字表示创建完成:
这时候我们根据终端的提示先输入cd .\project1\进入新建项目project1的根目录,再输入npm run serve运行该程序,出现以下文字表示程序已成功运行(此处的默认端口应该为8080,但是我的8080端口运行着另外一个程序,因此它自动将此项目运行在了8081端口):
使用Ctrl+鼠标左键点击或直接在浏览器输入Local后的网址,自动跳转至如下页面,表示vue-cli已经成功配置并可运行:
加入自己的页面
导航至项目内src文件夹内,打开App.vue,可以看到这个文件由三部分组成:<template></template>、<script></script>和<style></style>。其中template内存放HTML代码,script内存放JavaScript代码,style内是css样式代码。我们把各部分里面的代码清空,准备下一步使用。
将上一章的index.html内<body>里的代码粘贴进<template>,将index.css内的所有代码粘贴至<style>,Ctrl+S保存后程序会自动重新运行,进入页面查看,已经可以正常显示了:
文档结构
其中src下自然生成的App.vue为我们主要程序的地方 ,src下的assets新创建了几个json数据文件,来模拟服务器端传来的json数据。其余的文件在没有问题下尽可能不碰。
<style>内相对于index.css的修改
先放一张之前的class、id(“.”后跟class,“#”后跟id)与对应div部分的图:
.left{
width: 30%;
height: 100%;
border-right: 1px solid gray;
background-color: rgb(235, 244, 243);
/*----change----*/
overflow-y: auto;
/*----change----*/
}
.upper{
width: 100%;
height: 80%;
background-color: rgb(254, 247, 236);
display: block;
/*----change----*/
overflow-y: auto;
/*----change----*/
}
两个/*----change----*/内包含相对于原index.css文件的修改。这里使用了overflow-y: auto;来实现内部元素大小如果纵向超过父级元素,右边会显示一个滚动条,这个滚动条只控制这一个div内元素的滚动,如下图:
此章节新加的class(新加的只用到了class,没用到id):
.person{
width: 90%;
height: auto;
border-bottom: 1px solid lightgrey;
margin-left: auto;
margin-right: auto;
}
.sel{
width: 100%;
height: 100%;
text-align: left;
font-size: 60%;
border: 0;
background-color: transparent;
color: black;
margin-bottom: 5%;
}
.notSel{
width: 100%;
height: 100%;
text-align: left;
font-size: 60%;
border: 0;
background-color: transparent;
color: grey;
margin-bottom: 5%;
}
我们要在.left中纵向排列出联系人的id,.person为每个id的容器,横向占据90%父级元素的宽,并有一条下边框以隔开每一个id。.sel和.notSel为select和not select的缩写,当未选中时,文字颜色为灰色,当选择其中一个id时,它会变为黑色。
.oneMess{
margin-left: auto;
margin-right: auto;
width: 80%;
border-bottom: 1px solid lightgray;
}
.you{
width: auto;
height: auto;
padding-top: 2%;
display: flex;
justify-content: left;
}
.me{
width: auto;
height: auto;
padding-top: 2%;
display: flex;
justify-content: right;
}
.urtime{
color: rgb(140, 140, 140);
font-size: 50%;
display: flex;
justify-content: left;
margin-bottom: 1%;
}
.mytime{
color: rgb(140, 140, 140);
font-size: 50%;
display: flex;
justify-content: right;
margin-bottom: 1%;
}
在.upper中纵向排列出与该人物的聊天记录,每条信息的容器样式为.oneMess,和id一样,它也有一条下边框区别下一条信息。这里的.you、.urtime和.me、.mytime表示了对方与自己的信息与时间样式的样式,.you、.urtime左对齐,.me、.mytime右对齐,使用了display: flex;和justify-content: left/right;来实现,且时间的文字颜色浅于正文的颜色。
<template>内相对于index.html的修改
<template>
<body>
<div class="main">
<div class="top">
<div class="l">CHAT</div>
<button class="r">登录</button>
</div>
<div class="bottom">
<div class="left">
<!------change------>
<div v-for="(p, index) in person" :key="p.name" class="person">
<button :class="[p.isSel ? 'sel':'notSel']" @click="selPerson(index)">{{ p.name }}</button>
</div>
<!------change------>
</div>
<div class="right">
<div class="upper">
<!------change------>
<div v-for="item in list" :key="item.mess" class="oneMess">
<div :class="[item.isMe ? 'me':'you']">{{ item.mess }}</div>
<div :class="[item.isMe ? 'mytime':'urtime']">{{ item.time }}</div>
</div>
<!------change------>
</div>
<!------change------>
<div class="lower">
<textarea v-model="datas" name="area" id="area" cols="30" rows="3"></textarea>
<button @click="add" class="send">发送</button>
</div>
<!------change------>
</div>
</div>
</div>
</body>
</template>
<!------change------>内为有修改的部分,接下来三部分文字按顺序对上三个修改部分进行解释。
1.显示人物id
//people.json
[
{
"isOL": true,
"name": "girlfriend",
"isSel": true
},
{
"isOL": false,
"name": "buddy",
"isSel": false
},
{
"isOL": true,
"name": "mom",
"isSel": false
}
]
对于.left的修改:left内的结构为:一个div包裹着一个button,div的样式对应<style>里的.person。
div标签其中的v-for="(p, index) in person" :key="p.name"表示从person(由上面的people.json文件引入得来的响应式变量,这个在<script>标签中解释)这个列表中遍历,得到循环次数,把每个变量给p,把索引给index,并把该div以此循环次数渲染(语法上感觉有点像Python的:for i in arr)。这里person的循环次数为3,因此div也会渲染三次。
button内的:class="[p.isSel ? 'sel':'notSel']" @click="selPerson(index)",其中:class使用了三元运算符(judge? "true":"false"),person列表中每个对象都有一个isSel属性,标志着这个id是否被鼠标选中。@click表示当按下任意一个button时,它会调用selPerson(index)这个函数(也会在<script>标签中具体解释)。button的值为{{ p.name }},vue会自动把每个p对象的name赋给每个div。
2.显示与人物的消息
//data-girlfriend.json
[
{
"isMe": true,
"mess": "love you",
"time": "2024-6-22"
},
{
"isMe": false,
"mess": "ur a good man",
"time": "2024-6-22"
},
{
"isMe": true,
"mess": "...",
"time": "2024-6-22"
}
]
对于.upper的修改:upper内的结构为一个大div包裹着两个竖直排列的div,上面的显示消息正文,下面的显示发送时间。
大div对应样式为.oneMess,它和.left中的div一样使用v-for循环渲染,只是这次循环的对象是list列表(由上面data-girlfriend.json创建的响应式变量,会在<script>标签中解释)。
下面的两个竖直排列的div也由三元运算符来判断其样式,条件是data-girlfriend.json中每个对象的isMe属性,如果是我发出的消息,isMe为true,文字右对齐,如果不是我发出的消息,isMe为false,文字左对齐,时间的样式同理。他们的内容也同button值的形式,不过上面循环的对象变为了item,调用时也要使用{{item.mess}}和{{item.time}}
3.数据发送
对于.lower的修改:lower中包含了一个文本域textarea和一个发送按钮button。
文本域使用v-model="datas"将其内部值与datas这个响应式变量绑定,文本域内的内容更改,datas的值也会更改。
按钮使用@click="add"绑定了add函数(无参函数就不用写括号了),按下按钮add函数执行。
<script>内容
import { ref } from 'vue';
import people from './assets/people.json'
var person = ref(people);
let data;
let list;
let datas;
function changePerson(curPerson){
switch (curPerson){
case 'buddy':
data = require('./assets/data-buddy.json');
break;
case 'mom':
data = require('./assets/data-mom.json');
break;
case 'girlfriend':
data = require('./assets/data-girlfriend.json');
break;
default:
console.log("error");
break;
}
list = ref(data);
datas = ref('');
}
changePerson(person.value[0]["name"]);
第一行中,ref为响应式变量,它必须要从‘vue’中引入,不过即使忘了写了,在创建ref变量时VS code也会帮你自动补上。
第二三行,从assets引入了people.json文件并转为了person这个响应式变量,以便接下来使用。
四五六行初始化了变量,但是没有赋值,接下来在changePerson函数中对各变量赋值。
changePerson函数需要传入当前人名curPerson,使用switch-case语句判断读取哪一个json文件。读取后存储至data变量,再转换为响应式变量list。datas即文本域的内容目前设定为空,由于已经双向绑定,这里也可以看作给文本域初始化了。
在程序开始时第一个调用changePerson函数并传入第一个人名,即可在各个人和消息记录间切换。
function selPerson(index){
for(var i=0; i<person.value.length; i++){
if(i!=index){
person.value[i]["isSel"] = false;
}else{
person.value[i]["isSel"] = true;
var curPerson = person.value[i]["name"];
changePerson(curPerson);
}
}
}
selPerson用于改变当前被选中的id颜色。由于前面在<style>部分我们对button的三元运算符判断该对象的isSel属性,那么在该对象被选中并给selPerson传入了它的索引index时,函数会使用for循环将除该索引外的所有对象的isSel属性设为false,被选中的对象isSel属性设为true。
结合上两部分代码和<template>、<style>,运行可得以下结果,被选择的id颜色深一些,右边上半部分的内容也会随着选择的不同而切换:
function add(){
if(datas.value != ''){
var sendTime = new Date();
var info = {
isMe: true,
mess: datas.value,
time: sendTime
};
list.value.push(info);
datas.value = '';
}
}
add函数用于将文本域内文字发送至消息记录框中,实现思路是当文本域内值不为空时,新建一个对象,对象中的isMe为true,mess即信息内容为双向绑定的变量datas(注意这里想使用响应式变量的值需要用.value取得该值),time则是使用new Date()创建了一个新的时间日期对象(只不过这个时间日期的格式非常“具体”,如果想要统一格式的话可以参照一下网络上关于JavaScript的Date()的相关文档)。
创建完成后使用push()函数添加到该列表的末尾,再将双向绑定至文本域的变量datas的value变空,文本域也就被清空,可以执行下一次输入了。
源码
简单的聊天程序(二):配置Vue-cli以加速开发: 为上一篇:简单的聊天程序(一):HTML+CSS实现响应式界面 的进阶部分,使用vue-cli辅助搭建vue程序。 - Gitee.com
标签:vue,cli,auto,json,Vue,聊天,div,data,id From: https://blog.csdn.net/qq_43059415/article/details/139897015