Vue前后端数据交互与显⽰
⼀、技术概述
将后端所计算的数据呈现在前端页⾯的相应位置并根据⽤户点击操作改变相应的数据和界⾯,再传值给后端。该技术是Web开发必备,是前后端交互的纽带。难点在于获取后端数据并且防⽌数据联动。
⼆、技术详述
1. 从接⼝获取后端数据
(1) 仔细查看后端所传数据的类型。主要是区分数组和单个数据。查看后端的请求⽅式,区分post或者get。
(2) ⾸先,在data中return⼀个xxxData:[]数组或⼀个变量xxxData:<;类型>来接收后端传来的数据。
(3) 在⽅法中定义⼀个请求函数,⽐如我们这⾥函数名定义为update。请求函数中最主要的为请求语句通过api获取后端数据。{}中填写的是所携带的参数。
当get时,params作为⼀个关键字,总领所有携带参数的传递,例如传递参数的名字为id,值为data中已声明的值myId,那么在get请求语句中可以写成:
update(){
this.$(baseURL+`api/条件`,{params:{Id}}).then(function(res){
});
},
当post时,可以不加params关键字。直接写成:
update(){
this.$(baseURL+`api/条件`,{Id}).then(function(res){
});
},
返回的参数在then之后的匿名函数⾥。
这⾥baseURL是项⽬的路径,如果项⽬部署在服务器上⾯⼀般格式为www.XXX/项⽬名,之后的api是后端封装的api接⼝。
api/条件这个条件中往往会出现前端定义的变量,在传值时若将其直接写⼊便会成为接⼝地址的⼀部分。要想让其代表它内在的值,则使⽤${}取值。例如:
console.info(`⼤家好,我叫${name},今年${age}岁了`)
// 等价于
console.info('⼤家好,我叫' + name + ',今年' + age + '岁了')
(4) 此时这个请求操作是没有调⽤,是默认执⾏的,所以要在mounted⾥⾯实时执⾏。
整体代码呈现例如:
<script>
export default {
data(){
memberData[],//等待存放后端数据的接收数组
},
mounted(){
this.update();//在html加载完成后进⾏,相当于在页⾯上同步显⽰后端数据
},
methods:{
update(){
this.$(`/api/project/${this.$store.state.project.id}`, {
project_id:this.$store.state.project.id,
}).then(doc => {
var code = doc.data.status;
var msg = doc.data.msg;
if (code == 0){//请求成功,可以根据不同的状态码返回值做出相应的动作
}
})
},
},
};
</script>
在以上例⼦中,doc接收返回的参数,以doc.data开头获取。其中后端传送的数据⼜具有data结构,所以⼜再次.data,深⼊再次获取其
中的member数据。
注意:在我刚开始学习获取数据的时候,将请求URL错⽤单引号(')引⽤。这⾥是使⽤反单引号(`)。
在使⽤vue编程中,组件⾥⾯绑定的事件如果有传⼊事件名称字符串/字符串参数,这个时候光⽤单双引号会出现string is undefined,这个时候我们就需要⽤到反单引号。
对⽐后端项⽬⽂档:
2. 前端向后端传值的交互
前端向后端传值和之前提到的携带参数的概念⼀样,是同样的⽅法。但是不同点在于这是以前端向后端传参为主的交互,所以携带参数很多的情况下,容易造成代码过长,阅读书写繁琐的问题。这就可以建⽴中间变量结构,统⼀传值,这时携带参数只需要填写⼀个。例如:
var obj = {//将所有携带参数放在⼀起
project_id:this.$store.state.project.id,
id:this.id,
finish:checked,
name:this.flowName
}
this.$http.post(`/api/project/${this.$store.state.project.id}/task/update`, obj)//直接传值的合集
.then(doc => {
var code = doc.data.status;
var msg = doc.data.msg;
if (code == 0){
this.update()//更新后端数据后⾃动刷新前端,随着更改外观
}
else{
this.$alert(msg,'false')
}
});
3. 显⽰获取到的数据
相对于获取数据⽽⾔,显⽰数据就显得简单许多了。
⾸先后端传来的数据肯定是很多层结构或者是⼀个集合,所以在⽤⼀个⼤数组接受后台数据的同时,在data return中要声明⼏个⾃⼰需要显⽰的具体的变量,后台数据要分清楚存⼊前端变量中才能被前端所使⽤。将数组中的数据再次分离。例如:
getTaskData:function(){
this.$(`/api/project/${this.$store.state.project.id}/task/info?      id=${ssageId}`,//根据后端提供的URL,其中?后跟参数要注意写法${}
{params:{project_id:this.$store.state.project.id,task_ssageId}})
.
then(doc=>{
if(doc.data.data){//当有数据传来时才可获取。若是为空,则在传来的data下再次.xxx寻结构中的⼦变量则会出错。
this.taskData=doc.data.data;//所谓的整体⼤数组,包含了所有传来的数据
this.defaultChecked=this.taskData.finish;//细分传来的数据结构并放⼊已声明过的变量
this.taskRemarks=arks;
}
else
this.taskData=null;
}).catch(err=>{//处理错误的写法
this.$alert("未知错误", "false");  //服务器还没搭起来
})
},
在第⼀次接触接收数据时我就有个疑问,⼀直不知道类似于这样的“⼦数据”怎么获取:
获得了具体的数据之后,想要显⽰在html⾥。⼀般来说,将变量或者其代表的信息显⽰在⽹页上⼤多是插⼊在html标签中,变量作为属性值就要使⽤v-bind来实现。v-bind就是⽤于绑定数据和元素属性的。例如:
<a href="myHome">OK</a>
想要实时更新href属性值则需要绑定⾃定义的变量上去,⽽在双引号中的变量都会被当作字符串。这时我们需要⽤v-bind实现。绑定之后,对应的值要去vue的数据⾥⾯。当我们在控制台改变url时,对应也会变化。相同的,我们还可以绑定图⽚src属性、class属性。
//这⾥url是在data中return的⾃定义变量,存储链接字符串
//url:"MyHome",
<a v-bind:href="url">OK</a>
//简写为(我简记为在需要变量名作为属性的时候,在属性前加冒号)
<a :href="url">OK</a>
我在刚开始想实时变化页⾯显⽰数据的时候,即根据后端传来的数据更改页⾯显⽰标签属性的时候,错误使⽤dom控制元素显⽰。因为之前没有接触过Vue,所以我对于界⾯元素的更改的意识停留在“ElementById('xxx').<;属性>=xxx”的阶段,这样做起来代码很繁琐,效率也低,增加了代码的耦合性。
字符串转数组 前端
4. 防⽌数据联动
在任务⾯板的模块,为要根据不同的点击显⽰不同的任务详情就要传递每个任务唯⼀的id。⽽在显⽰详情后有更改信息的功能,在这随意的更改可能会影响其他任务的信息,造成信息错乱。主要原因是刚开始我们监听了所有组件的更改,例如这段代码在更改任务紧急程度的时候调⽤:
onFlowPri(pri){
this.taskpriority = pri
this.$http
.post(`/api/project/${this.$store.state.project.id}/task/update`, {//当紧急程度⼀变化的时候就向后端传输
数据,仅⼀项变化,更改的却是全部数据,这时传输其他旧数据就会遇到问题    project_id:this.$store.state.project.id,
id:this.id,
remarks:this.flowMarks,
name:this.flowName,
finish:this.finish,
priority:pri,
})
.then(doc => {
var code = doc.data.status;
var msg = doc.data.msg;
if (code == 0){
this.update()
}else{
this.$alert(msg,'false')
}
});
},
⽽在⽤户是否保存不得⽽知的时候太早的传输更改数据,积极的监听会造成错误。增加了代码的繁琐程度。尤其是和⽤户交互的数据⾜够多的时,会造成混乱。好的⽅式应在⽤户选择确认保存后再将整体表格中要求填写的数据移交给后端,这样⼀次性的传输保证了数据的准确性。
三、技术问题
1. 界⾯⾃动刷新
问题描述:在⽤户改变某些功能性质时,界⾯所表现出来的数据或者组件不能实时变化,即需要⽤户⼿
动刷新整个页⾯。
解决⽅法:⾸先界⾯的加载是要靠mounted⽅法中定义的获取后台数据的⽅法(在这⾥⼀般将该⽅法命名为update)显⽰。作为钩⼦函数,它向后端请求,拿回数据,配合路由器钩⼦做⼀些事情。主要是依靠api拿数据,在mounted和改变的时候直接调⽤update就可以。即在⽤户点击事件发⽣之后在相应事件的位置调⽤update重新从后台获取新数据。
2. 获取数据数组出错
问题描述:后端传⼊前端的是⼀个数组,前端接收到⾃⼰的数组之后,⼆次使⽤push新的元素进⼊时报错。
问题表⾯看起来很简单出原因,是因为我所push的数组不被承认为数组。但是我反复检查过确实在data中接收数据类型被声明为数组。这个报错也不到具体的位置,它报错全是从runtime运⾏时缓存读的,⼀个源⽂件都没映射到。是个⽞学问题。
解决⽅法:选定项⽬。就是这么简单。我们的产品是要通过选择项⽬来向后台传送数据的,即项⽬ID。所以在报错信息不明确的时候要尝试发现有⽆信息没读到的问题。
3. 传值显⽰值(针对时间)
问题描述:前后端数据交互中⽐较绕的问题就是时间作为DateTime类型传值的时候的数据类型转换。以及在使⽤时间选择器的时候将组件中的时间显⽰为所传值的时间。
如图设置时间位置所显⽰的时间是错误的,⽽控制台输出的是从后台传⼊的正确时间。即时间⽆法实时在时间选择框中显⽰。
从设置时间等时间选择框中更改时间并把其传⼊到后端时,会有类型不匹配的问题。即String和DateTime的转换。
解决⽅法:在时间选择器的属性中加⼊:value属性并以moment约束要显⽰的时间变量例如:
:value="[moment(taskDetails.t_begin), moment(taskDetails.t_end)]"
时间格式化组件moment的使⽤:需要在script中导⼊组件,并在methods中声明moment。
<script>import moment from 'moment'</script>
若要将时间数据传回后端的话需要将String类型的数据转换,即需要声明定义⼀个toDateTime函数:
function toDateTime(time) {
var date = new Date(time);
var Y = FullYear() + '-';
var M = (Month()+1 < 10 ? '0'+(Month()+1) : Month()+1) + '-';
var D = (Date() < 10 ? '0'+Date() : Date()) + ' ';
var h = (Hours() < 10 ? '0'+Hours() : Hours()) + ':';
var m = (Minutes() < 10 ? '0'+Minutes() : Minutes()) + ':';
var s = (Seconds() < 10 ? '0'+Seconds() : Seconds());
strDate = Y+M+D+h+m+s;
return strDate;
}
在传值的时候直接规范化。
四、总结
1. Vue中数值传送是⽐较简单的部分,主要是准备好等待接收的变量,保证数据成功被载⼊,数据的类型问题也要注意,要仔细核对后端寄
来的数据。Vue的前后端交互都是有较简单实⽤的模板来实现的,所以很好掌握。
2. 显⽰数据的时候要参透不同组件的展⽰⽅式,有的利⽤item循环展⽰,有的直接引⽤,更多是⽤v-bind来实现变量影响显⽰。
3. 本次项⽬开发中,任务⾯板的开发和代码的编写是很复杂的,容易混淆,因为有多个弹出窗⼝以及⾯板,上⾯⽤户所填写的内容还有从后
台接收所显⽰的内容都是不同的,它们之间的数据联动是很可怕的,稍不注意就容易⼀个新⾯板数据的填写覆盖掉以前已显⽰的旧数据。
尤其对于表单⼀类需要⽤户参与填写的组件来说,需要实时监控每个可能交互的⼦组件,但是千万要注意不⼀定是每个⼦组件都需要有及时的反馈,不然产⽣的不必要的关联动作有可能会影响到最后信息的存储。尤其是带有取消的表单,即需要⼀键归零,过早的产⽣相应动作会适得其反。
五、参考
1. 作者:
2. 作者:
3. 作者:
4. 作者:caixiaodaohaha
5. 作者:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。