• Abp mvc angular 添加视图


    在LawAndRegulation项目中添加导航路由(Abp添加菜单)对应的客户端页面。

    创建文件

    客户端页面在Abp模板项目中默认存放在Abp/Main/views文件夹下,在项目中我们创建属于字典管理的新文件夹,名字命名为DictionaryManger。

    在文件夹中创建文件index.cshtml和同名的js文件index.js。

    创建的index.cshtml文件中只需要编写页面内容部分,idnex.js中编写当前页面逻辑。

    创建index.cshtml需要注意:

    • 创建时选择“带有布局的MVC5视图页”选项,选择合适的母版(Views/Shared/_Layout.cshtml);
    • 删除原有内容;

    同样添加index.js文件。

    编辑index.cshtml

    在视图页面中编写你的html内容,在Abp母版项目中已经引入了Bootstrap,项目DictionaryManager在编写页面内容时,使用Bootstrap作为前端开发框架。

    在项目的Bundle.config文件中已经通过文件夹引入的方式引入了/App/Main文件夹下所有css文件所以页面编写需要编写的css可以直接在index.cshtml项目所在目录下创建文件添加,在本项目中我们添加了dicCommon.css文件。

    页面中使用Bootstrap模态框,想要详细学习模态框,请移步这里,有详细的使用介绍。

    css文件中定义了很多自定义样式,这些样式中的单位存在px和em,存在这样的问题是因为部分内容继承自原有代码,还没有时间进行统一更改,单位之间换算参考链接,这部分内容还没有进行验证。按照文中介绍,默认情况下1em=16px,但em是相对单位所以如果父元素定义font-size字段那么1em=父元素定义的大小。

    添加html,代码如下:

    <form id="dicForm" runat="server"  ng-controller="app.views.dictionarymanager.index as vm">
        <div class="row">
            <div class="col-xs-12 dic_header" id="dicHeaderBtn">
                <button type="button" class="btn btn-primary  pull-left" id="btnAddDicCategory" ng-disabled="btnAddDicCategoryDisabled">
                    新增字典分类
                </button>
                <button type="button" class="btn btn-primary pull-left" id="btnAddDic" ng-disabled="btnAddDicDisabled" ng-click="AddDictinary()">
                    新增字典
                </button>
                <button type="button" class="btn btn-primary pull-left" id="btnEditDic" ng-disabled="btnEditDicDisabled">
                    编辑
                </button>
                <button type="button" class="btn btn-primary pull-left" id="btnDeleteDic" ng-disabled="btnDeleteDicDisabled">
                    删除
                </button>
                <button type="button" class="btn btn-primary pull-left" id="btnExport" ng-disabled="btnExportDisabled">
                    导出
                </button>
                <button type="button" class="btn btn-primary pull-left" id="btnImport">
                    导入
                </button>
            </div>
            <div class="col-xs-12 d-p-l">
                <div class="col-sm-4 col-lg-3 dic_noderow" id="dicNodeRow">
                    <div id="dicTree">
                    </div>
                </div>
                <div class="col-sm-8 col-lg-9 d-p-l" id="divDetail">
                    <iframe id="showInfomation" ng-src="{{srcValue}}" name="iframeSelf"></iframe>
                </div>
            </div>
        </div>
    </form>

    上面代码为bootstrap(css/html开源框架),其中dic-header、d-p-l、dic-noderow为自定义css其他为bootstrap原生要素及属性,如果想进一步学习bootstrap使用可以查看链接。上面代码除了使用布局及按钮之外,还使用了模态框,关于模态框菜鸟有介绍,移步链接。class内包含col-sm-12等col开头的样式,这些样式为bootstrap的网格系统,网格系统的具体介绍请查看上面bootstrap链接。

    视图中涉及到的样式

    bootstrap默认样式介绍:

    • btn:原始按钮样式;
    • btn-primary:基本按钮样式;
    • pull-left:整体左滑动;类似于左对齐,比如页面中控件隐藏,则右侧控件像左侧滑动;
    • col-xm-12在小型设备上的布局,视图总计为12,class中存在这个预定义类的要素相当于充满整个屏幕;
    • col-lg-3为在大型设备上布局,结合上面的col-xm-使用就可以达到响应式(一个站点适应多个终端)的布局;

    这些默认样式具体定义了什么可以查看bootstrap-theme.css(可以通过下载bootstrap框架得到这个文件)中源码进行查看。

    自定义样式:

    .r-p-l {
        padding-left: 10px;
    }
    div.col-xs-12.dic_header {
        padding-top: 10px;
        margin-left: 15px;
        padding-bottom: 50px;
    }
    div.dic_noderow, #dicTree {
        overflow-x: hidden;
        overflow-y: auto;
        max-width: 500px;
    }

    自定义样式中我们定义了以下属性:

    • padding-left、padding-top、padding-bottom:盒子模型的内边距;
    • margin-left:盒子模型的外边距;
    • overflow-x、overflow-y:内容溢出是否裁剪;

    视图中涉及的标签

    • button:按钮标签;
    • form:负责数据采集的一组标签;
    • div:将视图划分为不同区域;

    还有其他bootstrap自定义样式,这里不再详细介绍,如果有时间开设专门的博客介绍bootstrap。

    要素包含ng-字符的属性属于angular,这些属性大部分把ng-去掉即为要素原生属性,我们在视图中添加这些属性,就可以在控制器中直接对这些属性进行赋值,下一节我们详细介绍这些属性的使用。

    编辑index.js

    立即执行函数-如果已经掌握跳过

    首先在inde.js文件中编写一个立即执行函数,立即执行函数就是在函数定义的地方直接执行这个函数。作用及好处可以归纳为隔离作用域,在私有作用域内变量及函数不会被污染,相当于起到命名空间的作用。

    编写方式有以下几种(详细了解参考链接):

    //user () operational character
    (function(){})();
    (function(){}());
    //user ! operational character
    !(function(){})();
    //uer + operational character
    +(function(){})();
    //uer + operational character
    -(function(){})();
    //uer + operational character
    var temp=(function(){})();

    在我们的js文件中我们使用了第一种方式编写以及执行函数。

    angular模块module

    在js文件的立即执行函数中,我们首先定义一个模块,在angularjs中模块是应用程序中不同部分的容器,在这些容器中我们可以添加controllers(控制器)、services(服务)、filters(过滤器)、directives(指令)等内容。

    angular中模块通过angular.mudole(name,requires,configfn)方法创建:

    • name:模块的名称,与视图中html标签的ng-app属性相关联;
    • requires:模块的依赖关系,如果在调用方法时没有设置此参数,那么方法默认为获取这个模块;如果创建新模块并确定没有依赖关系,那么需要设置这个参数为[]数组;
    • configfn:负责在模块初始化时做一些配置,参数是方法或者数组,这个参数是数组,那么最后一个参数必须是方法。
    angular控制器controller

    控制器是对视图的数据和时间处理函数进行挂载,同时进行一定的业务功能的底层封装和处理,起到的作用就是增强视图,在视图的作用于中增加额外的功能,我们用它来给作用于对象设置初始化状态,添加自定义行为。

    创建完成angular模块后,调用模块方法controller创建控制器,controller的参数组成为:

    • controllerName:控制器名称,控制器名称和ag-controller属性值相对应;
    • controllerConstructor:第二个参数为一个回调函数,用于执行构造函数初始化内容;
    angular作用域scope

    在项目代码中,controller的参数是一个scope对象,scope是视图与控制器之间的纽带,scope是一个javascript对象,scope可以定义属性和方法,这些属性和方法可以在视图和控制器之间使用。

    调用标签事件

    通用事件

    //angular
    angular.element("#id").click();
    //jquery
    $("#id").click();
    //原生
    document.getElementById("#id").trigger("click");

    标签特定事件

    //angular
    angular.element("#id").on("eventName",function(event,data){});
    //jquery
    $("#id").on("eventName",function(event,data){});
    基于bootstrap的jQuery多级列表树插件

    装载及初始化插件:

                //初始化treeview
                angular.element("#dicTree").treeview({
                    data: getDictinary(),
                    levels: 2,
                    color: '#000000',
                    backColor: '#FFFFFF',
                    href:'#node-1'
                });
    function getDictinary() {
                var tree = [
                    {
                        text: "Parent 1",
                        nodes: [{text: "Child 1",nodes: [{text: "Grandchild 1"}]}]
                    }
                ];
                return tree;
            }

    以上为最简单结构,还有其他扩展属性可以查看链接,节点属性一节中有详细的介绍。

    添加treeview控件的节点选择事件:

                angular.element("#dicTree").on('nodeSelected', function (event, data) {
                    alert(data.text);
                });

    当节点被选择后可以触发事件调用该方法,在本项目中为了显示节点的详细信息。

    持久化当前选择节点内容

    所谓的持久化内容,也就是在当前视图的生命周期内保存视图中需要的内容。

    在节点选择事件中对视图中form表单的隐藏标签赋值,首先添加隐藏标签到index.cshtml中:

        <input type="hidden" id="currentNodeText" />
        <input type="hidden" id="currentNodeId" />
        <input type="hidden" id="currentHref" />

    在节点改变事件绑定的方法中赋值:

                angular.element("#dicTree").on('nodeSelected', function (event, data) {
                    angular.element("#currentNodeText").val(data.text);
                    angular.element("#currentNodeId").val(data.id);
                });

    存储当前选择的节点是为了在视图作用域内持久化节点内容。

    组件化模块(angular component)

    解耦复杂系统时将多个功能模块拆分、重组的过程就叫做模块化,其中有多个属性、状态描述其内部特性。

    组件化与传统的编写方式相比较,有什么优势呢,或者叫解决了什么问题,根据园内CooMark的总结如下:

    • app中的某个部分如何重用(在这里我们可以叫做,视图内的某个模块如何重用);
    • app中的scope作用域不是隔离的,变量和方法存在污染的可能;
    • 解决了传统模式不能重用的问题;
    • 简化了视图中的标签,便于维护;
    • 组件间是隔离的,互不影响;
    • 可以独立测试组件;

    使用component:

    • 文件名建议包含.component.js
    • component命名采用驼峰式命名法,在视图中使用时采用“-”进行分割;
    • template使用controller的实例$ctrl替代scope访问数据,别名可以使用controllerAs进行自定义;
    • component内的controller可以通过controller方法进行定义;
    • templateUrl定义时需要注意,根目录为当前视图目录(如果是mvc项目,那么根目录就是母版目录_Layout.cshtml);

    定义模块:

        var controllerId = 'app.views.dictionarymanager.index';
        var myModule = angular.module("app");

    注册组件到模块:

    • template:元素组件本身;
    • templateUrl:通过文件方式定义元素;
    • controller:定义组件controller,这样组件内就可以通过默认的$ctrl方式调用数据;
    • bingdings:绑定数据到元素,其中<为单向绑定,父作用域的变化影响子作用域;
    • scope:组件内单独的作用域;
    • controllerAs:重命名控制器;
    • restrict:字符型,E 表示该指令是一个element; A 表示该指令是attribute; C 表示该指令是class; M 表示该指令是注视;
        myModule.component('myComp', {
            //template: '<div>My name is {{$ctrl.text}}</div>',
            templateUrl:'././App/Main/views/dictionarymanager/dicItem.html',
            controller: function () {
                this.name = 'shahar';
            },
            bindings: {
                text:'<'
            }

     其中注册组件可以通过两种方式引入模板,第一种通过直接编写的方式,也就是代码中template的内容,也可以通过文件引入的方式,如图中templateUrl的方式。

    视图中引入组件,视图中通过-分割驼峰式命名法的组件,并定义绑定的属性,绑定的属性可以通过controller的别名调用父scope内的数据进行绑定:

    <my-comp text="vm.dicMainInfo"></my-comp>

    父组件向组件传递数据:

    myModule.controller(controllerId, ['$scope', function ($scope) {
            this.dicMainInfo = 'hello';
        }]);

    indes.js代码如下:

    (function () {
        var controllerId = 'app.views.dictionarymanager.index';
        angular.module("app").controller(controllerId, ['$scope', function ($scope) {
            $scope.AddDictinary = function () {
                alert("hello");
                $scope.btnADCDis = false;
            };
            function initialize() {
                $scope.srcValue = "";
                $scope.btnAddDicCategoryDisabled = true;
                $scope.btnAddDicDisabled = true;
                $scope.btnEditDicDisabled = true;
                $scope.btnDeleteDicDisabled = true;
                $scope.btnExportDisabled = true;
            }
            initialize();
        }]);
    })();

    在上面的代码中实践了以上介绍的知识点,首先定义controllerId变量,窗体与视图中ag-controller属性相同的值,通过module定义模块,因为在mvc项目中app的div也就是区域已经在模板视图中定义,所以在定义模块时统一都是用app名称进行定义,再通过调用模块的controller方法创建控制器,控制器中传递scope参数,在回调函数中编写初始化代码及逻辑代码,作用域(scopde)中定义的属性及方法与视图中的属性及事件相关联,这样即实现了初始化属性又装载了事件方法。

    错误处理

    TypeError: $.fn.bootstrapTable is undefined, bootstrap-table-zh-CN.js文件加载错误是因为加载顺序造成的,加载顺序遵循首先加载bootstrap.js文件,然后加载bootstrap-table.js文件,最后加载 bootstrap-table-zh-CN.js文件。

  • 相关阅读:
    一点一点学写Makefile(3)-增加第三方库和头文件
    一点一点学写Makefile(2)-自动搜所当前目录下的所有源文件
    一点一点学写Makefile-1
    linux下使用libxml2实现对xml文件的读取及查询
    struts2 谷歌浏览器保存date类型数据时报错
    复习
    day31
    day30
    作业29
    day29
  • 原文地址:https://www.cnblogs.com/GiserPage/p/10430183.html
Copyright © 2020-2023  润新知