前面我们分三章来说明了使用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的更多相关文章

  1. python工业互联网应用实战17—前后端分离模式之django template vs jquery3

    上一章节我们完成了"CRUD"的后面3个功能点,新增由于改动较大我们专门增加本章来阐述,主要是完成技术栈切换后,会发现模板的代码判断过多,逻辑过于复杂.对未来存在的扩展和维护友好性 ...

  2. Spring Cloud实战 | 最八篇:Spring Cloud +Spring Security OAuth2+ Axios前后端分离模式下无感刷新实现JWT续期

    一. 前言 记得上一篇Spring Cloud的文章关于如何使JWT失效进行了理论结合代码实践的说明,想当然的以为那篇会是基于Spring Cloud统一认证架构系列的最终篇.但关于JWT另外还有一个 ...

  3. 在centos7.6上部署前后端分离项目Nginx反向代理vue.js2.6+Tornado5.1.1,使用supervisor统一管理服务

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_102 这一次使用vue.js+tornado的组合来部署前后端分离的web项目,vue.js不用说了,前端当红炸子鸡,泛用性非常广 ...

  4. AngularJS中在前后端分离模式下实现权限控制 - 基于RBAC

    一:RBAC 百科解释: 基于角色的访问控制(Role-Based Access Control)作为传统访问控制(自主访问,强制访问)的有前景的代替受到广泛的关注.在RBAC中,权限与角色相关联,用 ...

  5. beego-vue URL重定向(beego和vue前后端分离开发,beego承载vue前端分离页面部署)

    具体过程就不说,是搞这个的自然会动,只把关键代码贴出来. beego和vue前后端分离开发,beego承载vue前端分离页面部署 // landv.cnblogs.com //没有授权转载我的内容,再 ...

  6. python工业互联网应用实战15-前后端分离模式1

    我们在13章节里通过监控界面讲了如何使用jquery的动态加载数据写法,通过简单案例来说明了如何实现动态的刷新监控界面的数据,本章我们将演示如何从Django模板加载数据逐步演化到前后端分离的异步数据 ...

  7. 简述前后端分离的情况下,Vue实现点击图片下载到本地(并实现IE11浏览器的兼容)

    1.简述 在前后端分离的项目中涉及跨域问题,通常都会使用token进行验证.最近在前后端分离的项目中在一个问题上搞了很久,就是以前下载附件或者导出数据为文件的时候,在以前的那些项目前端可以直接用 wi ...

  8. Vue的学习总结之---Vue项目 前后端分离模式解决开发环境的跨域问题

    原文:https://blog.csdn.net/localhost_1314/article/details/83623526 在前后端分离的web开发中,我们与后台联调时,会遇到跨域的问题. 比如 ...

  9. 服务器上详细前后端分离项目搭建(springboot+vue)

    介绍:本文用的经典的前后端分离开源项目ruoyi Gitee链接地址:https://gitee.com/y_project/RuoYi 一.拉取项目: 利用Git把项目拉取到本地,也可以直接利用id ...

随机推荐

  1. Windows核心编程 第十八章 堆栈

    第1 8章 堆 栈 对内存进行操作的第三个机制是使用堆栈.堆栈可以用来分配许多较小的数据块.例如,若要对链接表和链接树进行管理,最好的方法是使用堆栈,而不是第 1 5章介绍的虚拟内存操作方法或第1 7 ...

  2. [BUUCTF-Pwn]hitcontraining_uaf

    [BUUCTF-Pwn]hitcontraining_uaf 以此题作为对Pwn中堆利用的学习的开始.堆题初见,肯定有许多地方理解不恰当,希望师傅们能多多指教. 0x00.简述 成因 应用程序调用fr ...

  3. GUI简单实战——贪吃蛇

    将前面学到的GUI基础知识完成实战,完成一个简单的贪吃蛇项目 项目功能 用键盘上下左右实现贪吃蛇的自动移动 贪吃蛇吃到食物后,长度加一,分数加一 贪吃蛇吃到自己的身体,则游戏结束 按空格键实现游戏的暂 ...

  4. FreeBSD系统基本操作

    1:系统安装 2:关机与重启命令 立即关机,但是不关闭电源: shutdown -h now 立即关机,并且关闭电源: shutdown -p now 重启命令 shutdown -r now

  5. C++ primer plus读书笔记——第17章 输入、输出和文件

    第17章 输入.输出和文件 1. 对键盘进行输入缓冲可以让用户在将输入传输给程序之前返回并更正.C++程序通常在用户按下回车键时刷新输入缓冲区. 2. 一些I/O类 streambuf类为缓冲区提供了 ...

  6. oracle 碎片管理和数据文件resize释放表空间和磁盘空间(以及sys.wri$_optstat_histgrm_history过大处理)

    随着互联网的快速发展,各行各业的数据量也是与日俱增,而数据库的数据量也是直线增长,但是,如果表DML太多,则可能会在高水位线以下出现太多空白. 因此,只能将数据文件缩小到高水位线,因为高水位线以下有一 ...

  7. Ribbon导航

    简介 最近都在弄微服务的东西,现在来记录下收获.我从一知半解到现在能从0搭建使用最大的感触有两点 1.微服务各大组件的版本很多,网上很多博客内容不一定适合你的版本,很多时候苦苦琢磨都是无用功 2.网上 ...

  8. Python批量图片去水印,提高工作效率

    ​平常工作中,有时为了采用网络的一些素材,但这些素材往往被打了水印,如果我们不懂PS就无法去掉水印,或者无法批量去掉水印.这些就很影响我们的工作效率. 今天我们就一起来,用Python + OpenC ...

  9. [刷题] 235 Lowest Common Ancestor of a Binary Search Tree

    要求 给定一棵二分搜索树和两个节点,寻找这两个节点的最近公共祖先 示例 2和8的最近公共祖先是6 2和4的最近公共祖先是2 思路 p q<node node<p q p<=node& ...

  10. [刷题] 209 Minimum Size Subarray Sum

    要求 给定一个含有 n 个正整数的数组和一个正整数 s 找出该数组中满足其和 ≥ s 的长度最小的连续子数组 如果不存在符合条件的连续子数组,返回 0 示例 输入:s = 7, nums = [2,3 ...