前面我们分三章来说明了使用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. 洛谷P1424 小鱼的航程(改进版)

    题目背景 原来的题目太简单,现改进让小鱼周末也休息,请已经做过重做该题. 题目描述 有一只小鱼,它上午游泳150公里,下午游泳100公里,晚上和周末都休息(实行双休日),假设从周x(1<=x&l ...

  2. 开启Android Apk调试与备份选项的Xposed模块的编写

    本文博客地址:https://blog.csdn.net/QQ1084283172/article/details/80963610 在进行Android应用程序逆向分析的时候,经常需要进行Andro ...

  3. Xposed框架Hook Android应用的所有类方法打印Log日志

    本文博客地址:https://blog.csdn.net/QQ1084283172/article/details/80954759 在进行Android程序的逆向分析的时候,经常需要Android程 ...

  4. POJ1135比较有意思的对短路(多米骨牌)

    题意:      有一个骨牌游戏,就是推到一个后所有的牌都会被退到的那种游戏,起点是1,有两种骨牌,一种是关键牌,另一种是普通牌,普通牌是连接关键牌用的,给你一些边a b c的意思是关键牌a倒之后c时 ...

  5. hdu3706基础的单调队列

    题意: 解释题意不如直接把这个题粘贴过来,因为题目很短题意很容易懂. Give you three integers n, A and B.  Then we define Si = Ai mod B ...

  6. Win64 驱动内核编程-8.内核里的其他常用

    内核里的其他常用 1.遍历链表.内核里有很多数据结构,但它们并不是孤立的,内核使用双向链表把它们像糖 葫芦一样给串了起来.所以遍历双向链表能获得很多重要的内核数据.举个简单的例子,驱 动对象 Driv ...

  7. 【】POST、GET、RequestParam、ReqestBody、FormData、request payLoad简单认知

    背景: 使用vue+axios方式代替ajax后向后台发送数据出现问题了,controller获取不到数据.然后查.找.查.找中似乎找到一些门道.以下列出总结性的东西来记录自己的思考成果,仅供参考,不 ...

  8. 对标印度的PostMan,一款中国接口测试软件的崛起

    对于我们开发者,Api接口调试一定不陌生.包括我在内,之前进行Api调试时,一直使用的是一款印度的软件Postman.记得刚入手的时候,由于该款软件缺乏中文版本,上手一直比较慢,而且还至少存在如下几个 ...

  9. Git 系列教程(5)- 记录每次更新到仓库

    文件状态 你工作目录下的每一个文件只有两种状态:tracked 或 untracked tracked 已跟踪 tracked 的文件是指那些被纳入了版本控制的文件 在上一次快照中有它们的记录,在工作 ...

  10. Mybatis学习之自定义持久层框架(一) 为什么要用框架而不直接用JDBC?

    前言 说起Mybatis,相信大家都不会感到陌生,它是一款优秀的持久层框架,应用于java后端开发中,为客户端程序提供访问数据库的接口. 我们都知道,JDBC是Java语言中用来规范客户端程序如何来访 ...