浩的博客

python工业互联网应用实战9—使用Vue.js

  本章简要的说明如何通过对监控页面的简单重构,快速的使用上vue.js这当红的界面开发javascript组件。vue.js有诸多优势,笔者使用中感触最多的就是数据的双向绑定!通过组件双向绑定,当ajax刷新后台数据了,页面会自动重新渲染刷新数据;UI input控件value值被人机交互更新了,数据也会自动的同步到model,这样省去了早些年编程的get一遍赋值操作,保存时又一遍赋值操作。这个双向赋值一直是笔者从业以来觉得需要除去的“面条代码”,尤其是model属性值非常多的时候,变更经常让我们在某个环节少了某个属性的赋值操作引入bug,直到遇到vue组件... 

  以下面的代码就是早期的前端jquery脚本代码,提交数据的时候赋值获取空框的值,这个contractBill涉及一个大表,字段非常的多,光赋值代码就可以刷屏了。 

...
if (gContractBill == null) { if (gEnableLargeNumberOfCustomers) { contractBill.CustomerId = $('#txtCustomer').attr("data-WarehouseCustomerId"); contractBill.CustomerName = $('#txtCustomer').attr("data-CustomerName"); contractBill.CustomerGradeId = $('#txtCustomer').attr("data-CustomerGradeId"); contractBill.PublicCustomerId = $('#txtCustomer').attr("data-PublicCustomerId"); contractBill.PinYin = $('#txtCustomer').attr("data-PinYin"); contractBill.CustomerStationId = $('#txtCustomer').attr("data-WarehouseCustomerStationId"); contractBill.StationName = $('#txtCustomer').attr("data-StationName"); } else { contractBill.CustomerId = $('#selCustomerName').find("option:selected").attr("data-CustomerId"); contractBill.CustomerName = $('#selCustomerName').find("option:selected").attr("data-CustomerName"); contractBill.CustomerGradeId = $('#selCustomerName').find("option:selected").attr("data-CustomerGradeId"); contractBill.PublicCustomerId = $('#selCustomerName').find("option:selected").attr("data-PublicCustomerId"); contractBill.PinYin = $('#selCustomerName').find("option:selected").attr("data-PinYin"); contractBill.CustomerStationId = $('#selCustomerName').val(); contractBill.StationName = $('#selCustomerName').find('option:selected').text(); } contractBill.DepartmentId = gLogonData.TeamBranchs[0].BranchId; contractBill.DepartmentName = gLogonData.TeamBranchs[0].BranchName;
...

  上面这个代码只是提交的时候赋值操作片段的,ajax get过来刷新组件显示还得赋值一遍!

  1.1. JQueryVue

  现在我们改造监控界面来快速的演示使用vue.js。前章节的例子我们通过ajax刷新界面数据是通过jquery操作div id来实现的更新显示值,这个小节我们将重构这个ui端代码,采用vue来小试一下数据的双向绑定,实现数据的自动刷新。从而对比两种方式ui编码的不同,vue是笔者使用过的非常值得赞叹的组件之一。

  根据vue的规则,我们把原来的显示值修改成{{overheadFlow}}数据变量,由于“{{}}”与django的模板“{{}}”冲突,这里我们把vue的修改成“[[]]”才行。vue的数据双向绑定编码的时候我们只关注model的属性值即可,界面的输入控件值发生时,不需要的提交的时候重新把控件的值再重新赋值给model。当我们的表单修改的model属性太多的时候,这个功能非常非常实用 

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title>Tank 4C9</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.bootcss.com/jquery/3.4.1/jquery.slim.min.js"></script>-->
    <script src="https://cdn.bootcss.com/twitter-bootstrap/4.4.1/js/bootstrap.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

    <style type="text/css">
        .bg {
            background: url(../../static/img/tank4C9-1.png) no-repeat left;
            background-size: contain;
        }
    </style>


</head>
<body >
    <div id="content-main" class="container-fluid bg"  style="height:455px;background:url(../../static/img/tank4C9-1.png) no-repeat left;background-size:contain;">
        <div class="row">&nbsp;</div>
        <div class="row">&nbsp;</div>
        <div class="row">
            <div class="col-sm"></div>

            <div class="col-sm" ><strong class="text-warning" id="OverheadFlow">[[model.OverheadFlow]]</strong><strong> mm/sΛ2</strong></div>
            <div class="col-sm"></div>

        </div>
        <div class="row">&nbsp;</div>
        <div class="row">&nbsp;</div>
        <div class="row">&nbsp;</div>
        <div class="row">
            <div class="col-sm"></div>

            <div class="col-sm-2"> <strong class="text-success" id="Power">[[model.Power]]</strong><strong> kWh</strong></div>
            <div class="col-sm-9"></div>

        </div>


        <div class="row">&nbsp;</div>
        <div class="row">&nbsp;</div>
        <div class="row">&nbsp;</div>
        <div class="row">&nbsp;</div>
        <div class="row">&nbsp;</div>
        <div class="row">&nbsp;</div>
        <div class="row">&nbsp;</div>
        <div class="row">&nbsp;</div>
        <div class="row">&nbsp;</div>
        <div class="row">&nbsp;</div>

        <div class="row">
            <div class="col-sm-5"></div>

            <div class="col-sm-2"><strong class="text-danger" id="ButtomsFlow">[[model.ButtomsFlow]]</strong><strong>  mm/sΛ2</strong></div>
            <div class="col-sm-5"></div>

        </div>

    </div>

    <script>

       ////JQuery 代码入口
       // $(document).ready(function(){
 
       //     setInterval("getData()",1000);
 
       // });

       // function getData() {
       //     //模拟异步从后台获得值
       //     $.ajax({
       //         url: "/getTank4C9Data/", success: function (result) {
       //             data = JSON.parse(result);

       //             $("#OverheadFlow").html(data.OverheadFlow);
       //             $("#ButtomsFlow").html(data.ButtomsFlow);
       //             $("#Power").html(data.Power);
       //     }});
       // }



   var vm=  new Vue({
       el: '#content-main',
        data: {
            overheadFlow: 10,
            power: 20,
            buttomsFlow: 30,
            timer:'',            
       },
       delimiters: ['[[', ']]'], //
       mounted() {
           this.timer = setInterval(this.getData, 1000);
       },

        // 在 `methods` 对象中定义方法
        methods: {

            getData: function (event) {
                _this = this

                $.ajax({
                    url: "/getTank4C9Data/", success: function (result) {
                        data = JSON.parse(result);
                        //
                        _this.overheadFlow = data.OverheadFlow
                        _this.buttomsFlow = data.ButtomsFlow
                        _this.power = data.Power

                    }
                });
            }


       },
        beforeDestroy() {
           clearInterval(this.timer);
       }

    });</script>

</body>
</html>

  标注①:注意这里修改与django冲突的模板标识符号。

  标注②:ajax 调用返回数据后,只更新data里面定义的属性即可。

  现在运行这个页面,在功能不变的情况下,整个前端页面的渲染就使用上了vue.js。对比上面两段代码,你发现两者的差别不是很大,只是vue有一个data用来定义需要刷新的数据项,然后在html定义好对应的模板变量[[overheadFlow]]等,后面数据的刷新就交由vue.js来执行了,标注①的代码ajax 调用返回数据后,只更新data里面定义的属性即可,监控页面的数据就自动的刷新了,无须关注html控件。

1.2. 进一步重构代码

  通过上述小节,我们实现了原有的实时刷新数据功能,现在我们功能不变的情况下,进一步优化代码结构,在vuedata里直接定义一个标准返回的数据结构。

var vm=  new Vue({
    el: '#content-main',
    data: {  //①
        model: {
            OverheadFlow: 10,
            Power: 20,
            ButtomsFlow: 30,
        },
        timer: '',
       },
       delimiters: ['[[', ']]'], 
       mounted() {
           this.timer = setInterval(this.getData, 1000);
       },

        // 在 `methods` 对象中定义方法
        methods: {

            getData: function (event) {
                _this = this

                $.ajax({
                    url: "/getTank4C9Data/", success: function (result) {
                        //②
                        _this.model = JSON.parse(result);

                    }
                });
            }


       },
        beforeDestroy() {
           clearInterval(this.timer);
       }

    });

  ①:定义与ajax获取的model一样的数据结构格式

  ②:优化成直接更新vue里的model 对象,这样代码就显得更加简单了!

  同时记得把模板里的[[model.Power]] 变量改成model的属性,在功能不变代的前提下,这个重构让代码更简洁了。

  运行结果如下图:

1.3. 小结

  从上面的代码可以看出,完成data属性与组件的绑定后后面编码无须再关注控件id或者class,所有的代码只关注data属性值即可,这一分层逻辑带了极大的好处,编写业务的时候把精力集中关注业务即可,不用再担心是否哪儿少了一个赋值操作语句,页面的布局与css等则可以放到另外的时间去完成。Vue.js前端页面的处理模式给企业开发方面带来了实质性的“一大步”。

posted on 2021-03-17 10:03  wuch  阅读(404)  评论(0编辑  收藏  举报

导航