python工业互联网应用实战18—前后端分离模式之jquery vs vue
前面我们分三章来说明了使用django template与jquery的差别,通过jquery如何来实现前后端的分离,同时再9章节使用vue.js 我们浅尝辄止的介绍了JQuery到vue的切换,由于监控界面没有数据提交,无法很好的体现处我说的vue的优势,所以笔者增加本章节来进一步的对比两者异同点(没有对比就没有伤害),读者可以通过代码去体会vue的优势。vue作为精简版本的MVVM,完成双向绑定后我们编程的时候可以更专注于model本身,而不像JQuery还需要知道DOM元素的标签去读写值。两者都是前端脚本框架,实际项目中,有些时候我们会混合使用两者的。
1.1. 重构模板tasks.html
说干就干,我们通过重构tasks.html模板切换到vue模式下来理解和对比两者的差异吧,MVVM要点之一:MVVM 将数据双向绑定(data-binding)作为核心思想,View 和 Model 之间没有联系,它们通过 ViewModel 这个桥梁进行交互。
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>任务列表</title>
<link href="https://cdn.bootcss.com/twitter-bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
<div id="content-main" class="container">
<div><a href='0/change/'>新增</a></div> {% csrf_token %}
<table id="id_task_table">
<tr>
<th>ID</th>
<th>任务号</th>
<th>源地址</th>
<th>目标地址</th>
<th>条码</th>
<th>状态</th>
<th>优先级</th>
<th>开始时间</th>
<th>结束时间</th>
<th>作业数量</th>
<th>操作</th>
</tr>
<tr v-for="task in taskList"> <!--①-->
<td>[[task.TaskId]]</td>
<td><a :href="task.TaskId + '/view/'">[[task.TaskNum]]</a></td>
<td>[[task.Source]]</td>
<td>[[task.Target]]</td>
<td>[[task.Barcode]]</td>
<td>[[task.State]]</td>
<td>[[task.Priority]]</td>
<td>[[task.BeginDate]]</td>
<td>[[task.EndDate]]</td>
<td>[[task.SystemDate]]</td>
<td>[[task.JobCount]]</td>
<td>[[task.JobCount]]</td>
<td><a :id="task.TaskId+'-decompose'" :href="task.TaskId+'/decompose/'">分解</a> <a :id="task.TaskId+'-start'" :href="task.TaskId+'/start/'">下达</a> <a :id="task.TaskId+'-change'" :href="task.TaskId+'/change/'">修改</a> <a :id="task.TaskId+'-delete'" href='#' @click="taskDel(task.TaskId)">删除</a></td>
</tr>
</table>
</div>
<script> var vm = new Vue({
el: '#content-main',
data: {
taskList: [],
},
delimiters: ['[[', ']]'],
mounted() {
this.getData()
},
methods: {
getData: function () {
_this = this
//本例使用ajax实现vue的异步请求
$.ajax({
url: "/task/taskGetList/", success: function (result) {
d = result
_this.taskList = d.rows //② //for (const task of d.rows) {
// var row = "";
// row += "<tr>";
// row += "<td>" + task.TaskId + "</td>";
// row += "<td><a href='" + task.TaskId + "/view/'>" + task.TaskNum + "</a></td>";//①
// row += "<td>" + task.Source + "</td>";
// row += "<td>" + task.Target + "</td>";
// row += "<td>" + task.Barcode + "</td>";
// row += "<td>" + task.State + "</td>";
// row += "<td>" + task.Priority + "</td>";
// row += "<td>" + (task.BeginDate ? task.BeginDate : '-') + "</td>";
// row += "<td>" + (task.EndDate ? task.EndDate : '-') + "</td>";
// row += "<td>" + task.SystemDate + "</td>";
// row += "<td>" + task.JobCount + "</td>";
// row += "<td><a id='" + task.TaskId + "-decompose' href='" + task.TaskId + "/decompose/'>分解</a> <a id='" + task.TaskId + "-start' href='" + task.TaskId + "/start/'>下达</a>"
// + (task.State == '未处理' ? " <a id='" + task.TaskId + "-change' href='" + task.TaskId + "/change/'>修改</a>" : "")
// + " <a id='" + task.TaskId + "-delete' href='#' onclick=taskDel(" + task.TaskId + ")>删除</a></td>"; //②
// row += "</tr>";
// $("#id_task_table tbody").append(row); //}
}
});
},
taskDel: function (pk) {
//异步从后台获得值
url_str = "/task/taskDel/"
data = {
pk: pk,
csrfmiddlewaretoken: $('[name="csrfmiddlewaretoken"]').val()
}
$.ajax({
type: 'POST', url: url_str, data: data, success: function (result) {
//alert('HEHE')
window.location.replace("/task/");
}
});
}, },
}); </script>
</body>
</html>
标注①:原来jquery写DOM标签的赋值操作改成了vue的循环模板绑定;标注②:ajax异步请求获得的数据集直接赋值给vue model层即可,vue MVVM会感知数据变化而把数据同步渲染到view层。
上代码如上菜,相对于一大堆原理图,阅读代码、比较代码如直接下筷!自行品味vue是否可口可乐!于笔者这个改变确实爽点很多!
1.1.1. 运行结果

代码改动不是很大的情况下,我们任务列表不知不觉中就迁移到MVVM模式下了,刚开始使用vue的时候没注意,后来vue是国人写的,那个眼睛瞪大了很久,只要写代码也能基本衣食无忧,我们还是能出牛人的嘛。哎,那帮踢球的不早就衣食无忧了!?
1.2. 重构模板taskChange.html
上面小节我们见识了Vue的model层变化后数据自动同步到view的方向,双向绑定的另一个面就是: View 的变化会自动同步到 Model,当用户操作 View,ViewModel 感知到变化,然后自动更新 Model层数据,我们提交数据到后台直接提交model层即可。下面我们来改造taskChange.html支持vue吧。
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
<link href="https://cdn.bootcss.com/twitter-bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="content-main" class="container">
<h1>任务详情</h1>
<div class="row"><div><b>对象标识:</b></div><div id="task_id">{{pk}}</div></div>
<form method="post" id="edit_form">
<div class="row"><div><b>任务号:</b></div><input v-bind:disabled="pk>0" v-model="model.TaskNum" /></div> <!--①-->
<div class="row"><div><b>源地址:</b></div><input v-model="model.Source"/></div>
<div class="row"><div><b>目标地址:</b></div><input v-model="model.Target" /></div>
<div class="row"><div><b>条码:</b></div><input v-bind:disabled="pk>0" v-model="model.Barcode"/><input type="button" value="提交" @click="saveData()"></div>
{% csrf_token %}
</form>
<div class="row"><div><b>任务状态:</b></div><div id="state">[[model.State]]</div></div>
<div class="row"><div><b>优先级:</b></div><div id="priority">[[model.Priority]]</div></div>
<div class="row"><div><b>开始时间:</b></div><div id="begin_date">[[model.BeginDate]]</div></div>
<div class="row"><div><b>结束时间:</b></div><div id="end_date">[[model.EndDate]]</div></div>
<div class="row"><div><b>作业数量:</b></div><div id="job_count">[[model.JobCount]]</div></div>
</div>
<script> var vm = new Vue({
el: '#content-main',
data: {
model: {},
pk: parseInt($('#task_id').text()), },
delimiters: ['[[', ']]'],
mounted() {
this.getData()
}, methods: {
getData: function () {
_this = this
url_str = "/task/taskGet/" + this.pk + '/'
$.ajax({
url: url_str, success: function (result) {
_this.model = result.model
// ③ 注意不在jquery写元素值
//if (task.pk) { 修改
// $('#id_task_num').removeAttr('disabled')
// $('#id_barcode').removeAttr('disabled') //} else { // 新增
// $('#id_task_num').attr('disabled',true)
// $('#id_barcode').attr('disabled',true)
//} //$('#id_source').val(task.Source)
//$('#id_target').val(task.Target)
//$('#id_task_num').val(task.TaskNum)
//$('#id_barcode').val(task.Barcode) //$('#state').text(task.State)
//$('#priority').text(task.Priority)
//$('#begin_date').text(task.BeginDate)
//$('#end_date').text(task.EndDate)
//$('#job_count').text(task.JobCount)
}
});
},
taskDel: function (pk) {
url_str = "/task/taskDel/"
data = {
pk: pk,
csrfmiddlewaretoken: $('[name="csrfmiddlewaretoken"]').val()
}
$.ajax({
type: 'POST', url: url_str, data: data, success: function (result) {
window.location.replace("/task/");
}
});
},
saveData:function() {
//异步提交数据到后台
url_str = "/task/taskSave/" + this.pk + '/'
//data = {
// source: $('#id_source').val(),
// target: $('#id_target').val(),
// csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val()
//}
//if ($('#task_id').text() <= 0)
// data.taskNum = $('#id_task_num').val()
// data.barcode = $('#id_barcode').val() // ④ 不再判断处理直接通过model获取提交后台值
data = {
source: this.model.Source, target: this.model.Target, taskNum: this.model.TaskNum,
barcode: this.model.Barcode, csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val()
}
$.ajax({
type: 'POST', url: url_str, data: data, success: function (result) {
window.location.replace("/task/");
}
});
},
},
});
</script>
</body>
</html>
标注①:原来jquery写DOM标签的赋值操作改成了vue v-model绑定,v-bind:disabled等等;标注②:获取通过django模板传过来的对象标识; 标注③:ajax异步请求获得的数据集直接赋值给vue model层,MVVM会感知数据变化而把数据同步渲染到view层。;标注④:提交数据到后台直接操作model值,后面会进一步优化提交方法。
数据提交到后台同样也不在关注DOM上的元素和标签,直接操作model层即可,项目的实战中,为了简化交互赋值操作,我们常常采用获取的model修改属性值后直接提交回去的方式,这样就进一步简化了代码。
1.3. 简化提交代码
1.3.1. 前端代码
saveData:function() {
//异步提交数据到后台
url_str = "/task/taskSave/" + this.pk + '/'
// ④ 不再判断处理直接通过model获取提交后台值
//data = {
// source: this.model.Source, target: this.model.Target, taskNum: this.model.TaskNum,
// barcode: this.model.Barcode, csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val()
//}
data = this.model
data.csrfmiddlewaretoken=$("[name='csrfmiddlewaretoken']").val()
$.ajax({
type: 'POST', url: url_str, data: data, success: function (result) {
window.location.replace("/task/");
}
});
},
运行修改任务点击提交,调试窗口会提示后台服务器错误!


1.3.2. 后端代码
错误的原因主要是因为,model属性大小写的问题,我们进一步重构后台代码来支持这一提交模式的变更。
def taskSave(request,pk):
if int(pk) > 0:
data={"Source":request.POST['Source'],"Target":request.POST['Target']}
model = Task.objects.filter(pk=pk).update(**data)
else:
data={"Source":request.POST['Source'],"Target":request.POST['Target'],"Barcode":request.POST['Barcode'],\
"TaskNum":request.POST['TaskNum'], "State":1,"Priority":1,}
model=Task.objects.create(**data) data={'total':1,'success':True} return JsonResponse(data)
简单的调整后端获取参数大小写,前端技术栈切换到vue了,采用vue我们大大的简化了提交数据的操作,由于MVVM模式实现UI端的业务逻辑分层,model与view就聚焦专注相应的功能领域,大大的提高了开发和维护效率。高内聚、低耦合这个开发的底层逻辑应该是我们日常开发过程需要构建的核心的思维模型!
1.4. 小结
本章节vue vs jquery给我们总体的的印象也是好像改动不大嘛,咋个就切换技术栈了,当然没有完全说jquery就不用了,那个方便用那个,那个便于团队开发、协作和维护。代码写的简明又能搞定功能,应该是coder的追求之一吧。简单又好用,这点是vue成功的地方,也是该向vue的作者学习地方。
python工业互联网应用实战18—前后端分离模式之jquery vs vue的更多相关文章
- python工业互联网应用实战17—前后端分离模式之django template vs jquery3
上一章节我们完成了"CRUD"的后面3个功能点,新增由于改动较大我们专门增加本章来阐述,主要是完成技术栈切换后,会发现模板的代码判断过多,逻辑过于复杂.对未来存在的扩展和维护友好性 ...
- Spring Cloud实战 | 最八篇:Spring Cloud +Spring Security OAuth2+ Axios前后端分离模式下无感刷新实现JWT续期
一. 前言 记得上一篇Spring Cloud的文章关于如何使JWT失效进行了理论结合代码实践的说明,想当然的以为那篇会是基于Spring Cloud统一认证架构系列的最终篇.但关于JWT另外还有一个 ...
- 在centos7.6上部署前后端分离项目Nginx反向代理vue.js2.6+Tornado5.1.1,使用supervisor统一管理服务
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_102 这一次使用vue.js+tornado的组合来部署前后端分离的web项目,vue.js不用说了,前端当红炸子鸡,泛用性非常广 ...
- AngularJS中在前后端分离模式下实现权限控制 - 基于RBAC
一:RBAC 百科解释: 基于角色的访问控制(Role-Based Access Control)作为传统访问控制(自主访问,强制访问)的有前景的代替受到广泛的关注.在RBAC中,权限与角色相关联,用 ...
- beego-vue URL重定向(beego和vue前后端分离开发,beego承载vue前端分离页面部署)
具体过程就不说,是搞这个的自然会动,只把关键代码贴出来. beego和vue前后端分离开发,beego承载vue前端分离页面部署 // landv.cnblogs.com //没有授权转载我的内容,再 ...
- python工业互联网应用实战15-前后端分离模式1
我们在13章节里通过监控界面讲了如何使用jquery的动态加载数据写法,通过简单案例来说明了如何实现动态的刷新监控界面的数据,本章我们将演示如何从Django模板加载数据逐步演化到前后端分离的异步数据 ...
- 简述前后端分离的情况下,Vue实现点击图片下载到本地(并实现IE11浏览器的兼容)
1.简述 在前后端分离的项目中涉及跨域问题,通常都会使用token进行验证.最近在前后端分离的项目中在一个问题上搞了很久,就是以前下载附件或者导出数据为文件的时候,在以前的那些项目前端可以直接用 wi ...
- Vue的学习总结之---Vue项目 前后端分离模式解决开发环境的跨域问题
原文:https://blog.csdn.net/localhost_1314/article/details/83623526 在前后端分离的web开发中,我们与后台联调时,会遇到跨域的问题. 比如 ...
- 服务器上详细前后端分离项目搭建(springboot+vue)
介绍:本文用的经典的前后端分离开源项目ruoyi Gitee链接地址:https://gitee.com/y_project/RuoYi 一.拉取项目: 利用Git把项目拉取到本地,也可以直接利用id ...
随机推荐
- Http Get与Post的区别
GET和POST是HTTP请求的两种基本方法,要说它们的区别,接触过WEB开发的人都能说出一二. 最直观的区别就是GET把参数包含在URL中,POST通过request body传递参数. 你可能自己 ...
- Python中的Pexpect模块的简单使用
Pexpect 是一个用来启动子程序并对其进行自动控制的 Python 模块. Pexpect 可以用来和像 ssh.ftp.passwd.telnet 等命令行程序进行自动交互.以下所有代码都是在K ...
- POJ1722二维spfa+优先队列优化
题意: 给你一个有向图,然后求从起点到终点的最短,但是还有一个限制,就是总花费不能超过k,也就是说每条边上有两个权值,一个是长度,一个是花费,求满足花费的最短长度. 思路: 一开 ...
- Python 爬虫之Scrapy框架
Scrapy框架架构 Scrapy框架介绍: 写一个爬虫,需要做很多的事情.比如:发送网络请求.数据解析.数据存储.反反爬虫机制(更换ip代理.设置请求头等).异步请求等.这些工作如果每次都要自己从零 ...
- java 运用Cipher加密再解密后会变乱码。解决方案!
同样的方法类用main调用加解密都正常,就是当用到业务就是加密后再解密变乱码. 后来发现同样的内容加密后的内容竟不相同. 经调试发现 encryptData.getBytes() 转为字节是的使用 C ...
- 手把手教你部署验证freeswitch(避免踩坑)
前言:请各大网友尊重本人原创知识分享,谨记本人博客:南国以南i 介绍:freeswitch可集成ASR(语音识别)和TTS(文本转语音)创建智能电话机器人和用户通话,可用于问卷调查,自动催缴等业务,电 ...
- C++ primer plus读书笔记——第5章 循环和关系表达式
第5章 循环和关系表达式 1. cout.setf(ios_base::boolalpha); cout << (100 > 3) << endl;将输出true,而不是 ...
- 【近取 key】功能规格说明书
目录 前置信息说明 概念介绍 记忆宫殿 A4纸背单词法 词图 单词掌握程度相关 用户和典型场景 系统功能设计 主页 词图相关功能 创建词图 查看词图 复习词图 个人控制台相关功能 我的词图 统计信息 ...
- oo第四单元作业总结
一.本单元两次作业的架构: 本单元两次作业的架构基本是一致的,所以两次作业的架构就一起说了. 为了避免查询时出现同一个结果反复计算的情况(连续两次查询一个类的顶级父类,如果我们在查询的指令中来计算其父 ...
- MSSQL·最长输出长度限制之解决方案
阅文时长 | 0.11分钟 字数统计 | 234.4字符 主要内容 | 1.引言&背景 2.声明与参考资料 原文『MSSQL·最长输出长度限制之解决方案』 编写人 | SCscHero 编写时 ...