Vue 实践之路
前段时间比较忙,连续处理了好多的生产故障,导致一直没有时间进行Vue的进一步学习,最近公司出了点问题,几乎所有的工作都处于停滞的状态,有点难受,不过好的一方面就是有了足够的空闲时间来学习了,导致现在上班就是来学习的。
之前有一个业务需求已经逐渐将vue进行实践了,在这段相对空闲的时间借助这个需求正好学习下Vue相关内容。
数据绑定
首先感叹一下,这个数据绑定贼鸡好用,甚至比我想象的都要好用,可能是知识储备限制了我的想象力。这里以商户添加为例进行一个简单的介绍:
声明提交对象
先声明一个对象,用来绑定数据,这里给需要进行初始值声明的属性添加一个初始默认值,对于不需要赋予初始值的属性可以不进行显示声明,这个真的是太方便了,我需要写一大堆没有啥实际意义的初始化代码。
addObj:{
status : 'FALSE',
ticketName: 'YL',
routerPoses:[{bankPosCati:'',posSn:''}]
}
数据绑定
使用 v-model
进行数据绑定,对于以下绑定的 customerName
属性我并不需要进行显示的声明,只要我们填写相应的值,当我们提交数据的时候,其值会填充到 addObj 对应的属性中。
<div class="form-group">
<label class="col-sm-2 control-label" >商户名称:</label>
<div class="col-sm-10">
<input type="text" class="form-control" placeholder="请输入商户名称" v-model.trim="addObj.customerName">
</div>
</div>
数组的绑定
这里我开始的时候没用v-model
将数据进行绑定,而是使用:value
将值显示出来,所以导致没有我删除一行的时候,整个列表都会更新为初始值,这个是在前端同事的提点下得知 v-model
是可以直接绑定数组数据的,真香,再也不需要像jQuery需要自己手写一大堆的东西来维护这个数据了。
<div v-for="(item, index) in addObj.routerPoses" :key="index">
<input type="text" class="form-control posTh" v-model="item.bankPosCati" placeholder="終端号">
<input type="text" class="form-control posTh" v-model="item.posSn" placeholder="机具SN">
<input type="button" class="btn btn-primary btn-sm" style="margin-left:10px;" value="添加" v-on:click="addRouterPos" />
<input type="button" class="btn btn-primary btn-sm" value="删除" v-on:click="delRouterPos(index)" />
</div>
数据提交
基于以上已经可以完成一个表单的设计,接下来需要的是提交表单数据。最初使用的 jQuery.ajax 进行表单提交。其实到现在我已经非常不想使用 jQuery ,因为我发现到现在为止,jQuery中我最需要的只有一个ajax 的操作。
$.ajax({ 表单提交
type: "post",
url: "customerResourceAdd.action",
data: vm.addObj,
dataType: "json",
success: function(data){
// todo something
}
});
后台处理
@RequestMapping(value = "customerResourceAdd.action", method = RequestMethod.POST)
@ResponseBody
public String customerResourceAdd(HttpServletRequest request,RouterCustomerResource routerCustomerResource){
logger.info("customerResourceAdd :{}", JsonUtils.toJsonString(routerCustomerResource));
// TODO do the bussiness
return "success";
}
依赖ajax 进行数据提交,这种情况肯定很普遍,但是jQuery 这个库即使是压缩后也有将近100K,只使用一个ajax 就要引入这么大的一个库有点不值当的,然后我引入了 Axios,这个只有十几K 足够轻量了,写起来感觉都简单了。
axios.post('customerResourceAdd.action', vm.addObj)
.then(function (response) {
console.log(response);
});
但是后台拿不到数据,上网查查相关资料 vue使用axios发送post请求时的坑,然后引入了Qs这个小插件,解决数据拿不到的问题,使用ajax 进行数据提交的时候没有这种问题,我们查看请求可以发现,ajax提交的请求,header中默认的内容设置 Content-Type: application/x-www-form-urlencoded
也就是说ajax 默认就使用了表单数据提交意向的格式进行数据提交。
let params = Qs.stringify(vm.addObj) ;
axios.post('customerResourceAdd.action', params, {headers:{'Content-Type':'application/x-www-form-urlencoded'}})
.then(function (response) {
console.log(response);
});
但问题是无论是哪种形式的数据提交,肯定都已经将数据提交到服务端了,理论上都可以拿到数据才对,本着不抛弃不放弃的原则继续找相关资料,然后找到了 前后端联调之Form Data与Request Payload,你真的了解吗?
axios传递字符串的时候,Content-Type默认为"Form"类型
于是,当我们使用 Qs.stringify(vm.addObj)
将 JSON对象转换为字符串, axios 会将请求头设置 Form
,然后我们看下数据格式都是 key=value
的格式,这个和GET请求的格式是完全一致的,到这里我猜想,其实如果不是这种格式的话后端一样是无法解析成正确的数据封装对象的,当然这个我没有去验证这个。
POST /some-path HTTP/1.1
Content-Type: application/x-www-form-urlencoded
foo=bar&name=John
axios传递对象的时候,Content-Type默认为"JSON"类型
POST /some-path HTTP/1.1
Content-Type: application/json
{ "foo" : "bar", "name" : "John" }
我们可以看出两种方式提交的数据都是放在了请求体中,只是数据格式有所区别。
到这里我们基本上可以断定,数据都已经发送到服务端,只是是JSON对象格式时,没有到正确的解析,但是Spring作为 Java 生态中最优秀的框架,肯定可以解决这个问题,随便找一下,加个 @RequestBody
即可。
@RequestMapping(value = "customerResourceAdd.action", method = RequestMethod.POST)
@ResponseBody
public String customerResourceAdd(HttpServletRequest request,@RequestBody RouterCustomerResource routerCustomerResource){
logger.info("customerResourceAdd :{}", JsonUtils.toJsonString(routerCustomerResource));
// TODO do the bussiness
return "success";
}
两种方式都已经可以解决问题了,接下来需要择优选择下那个更好。目前来说,这个项目中有一个列表提交,当我们使用 foo=bar&name=John
类似这种方式提交的时候,对与后台我们解析复杂数据对象的时候是一件很麻烦的事情,而当我们使用 { "foo" : "bar", "name" : "John" }
类似这种数据格式进行提交的时候,框架几乎可以完美的解决请求数据到对象的封装,可以节省大量的工作。
至此,可以说完成了一个入门级的 vue 的完整使用。
然而截止到目前我还没有摆脱 jQuery,因为我使用的UI框架为 bootstrap,bootstrap 是依赖jQuery构建的,因此我想用 Vuetify
替换掉bootstrap,当然现在还不允许,vue的内容目前刚刚开始,还要学习的东西还很多,项目目前是可以接受我多用几个的,也不会因此体验变差,等这边差不多了,再去看看怎么整治下UI内容。
参考:
vue使用axios发送post请求时的坑
前后端联调之Form Data与Request Payload,你真的了解吗?
CDN引入:
Axios:<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
Qs:<script src="https://cdn.bootcss.com/qs/6.5.1/qs.min.js"></script>
Vue:<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>