SAPUI5 (06) - MVC 基础

MVC 是一种架构模式,SAPUI5 对 MVC 提供了良好的支持。

什么是 MVC?

MVC 是 Model、View、Controller 的简称,用于将程序的数据、界面展示和用户交互分离,通过这种分离,可以简化开发,以及让某部分变动的时候,不需要影响其他部分,从而降低耦合。

  • Model: 模型 - 代表应用程序的数据
  • View: 通过界面展示应用程序的数据和其它界面元素
  • Controller: 处理应用程序的数据,以及处理用户的交互。

下面的图示来自 SAPUI5 SDK,清晰地说明了三个概念之间的关系:

图片来自SAPUI5 SDK
  • Model 和 View 之间的关系:OpenUI5 有单向绑定或者双向绑定两种绑定模式,通过绑定,当 model 变更时, UI 自动更新。
  • Controller 和 View 之间的关系:View 通知 Controller,或者 Controller使用 API 来修改 View。
  • Controller 和 Model 的关系:Model 通知 Controller,或者 Controller 修改 Model。

我们用一个实例来演示 MVC 。我们要实现的一个非常简单的功能:在页面上放一个 Button,当用户点击的时候,显示 "Hlello"。对,前面 Hello World 程序已经实现过。我们先不用 MVC,将代码写在一个地方,为了和之前代码相比有点新东西,我们将 JavaScript 的 alert() 替换成sap.m.MessageBox.information(),OpenUI5 风格的对话框。先介绍一下 sap.m.MessageBox:

sap.m.MessageBox 对象

sap.m.MessageBox 是 OpenUI5 提供的对话框,可以显示信息、警告、错误等等。MessageBox 类是静态类,在使用之前必须执行

jQuery.sap.require("sap.m.MessageBox");

语句。OpenUI5 带有 jQuery 包,jQuery.sap.require(vModuleName) 方法的作用是加载指定的模块并且执行,这样 MessageBox才被加载, show() 方法才能运行。

sap.m.MessageBox 有如下方法:

  • alert: 对话框显示一个消息,有一个 OK 按钮(注意在中文环境中 OK 被翻译为确定),没有图标 (icon)
  • confirm: 确认对话框,询问是否确认,有一个 OK 按钮和 Cancel 按钮,一个问号的图标
  • information:消息对话框,带有 INFO 图标和 OK 按钮;
  • error:显示错误对话框,带有错误图标和关闭按钮 (Displays an error dialog with the given message, an ERROR icon, a CLOSE button)
  • success:显示成功对话框,带有 SUCCESS 图标和 OK 按钮
  • warning:显示警告消息,带有 WARNING 图标和 OK 按钮
  • show:显示一个对话框,类型为sap.m.DialogType.Message,图标和按钮由开发人员自行定义,提供更大的灵活性

语法基本相同:

sap.m.MessageBox.some_method(vMessage, mOptions?)

不使用 MVC 实现功能

OK,我们先把代码都写在 index.html 中:

<!DOCTYPE HTML>
<html>
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta http-equiv='Content-Type' content='text/html;charset=UTF-8'/>

        <script src="resources/sap-ui-core.js"
                id="sap-ui-bootstrap"
                data-sap-ui-libs="sap.m"
                data-sap-ui-theme="sap_bluecrystal">
        </script>
        
        <!-- Application area -->
        <script>
            function display() {
                var oButton = new sap.m.Button({text: "Click me."});
                
                oButton.attachPress(function() {
                    jQuery.sap.require("sap.m.MessageBox");
                    sap.m.MessageBox.information("Hello SAPUI5!", {                     
                        title: "SAPUI5 button test"
                    });
                });
                
                oButton.placeAt("content");
            }
            
            sap.ui.getCore().attachInit(display);
        </script>

    </head>
    <body class="sapUiBody" role="application">
        <div id="content"></div>
    </body>
</html>

使用 MVC 实现

本示例只有点击 Button,并没有数据,所以只涉及 view 和 controller。首先我们介绍一下 OpenUI5 的 View 有哪些类型。

SAPUI5 有哪些类型的 View?

SAPUI5 提供了JSView, XMLView, JSONViewHTMLView 等几种类型。SAPUI5 的示例代码主要采用 XMLView,这个也是现代开发语言的趋势。而对开发人员来说,JSView 也可能感觉比较舒适,所以建议重点掌握这两个类型就可以了,并且学会在两种风格的代码之间进行翻译。

Eclipse 中如何创建 View?

当在 Eclipse 中新建一个SAPUI5 Application Project 类型的项目时,Eclipse 会提示是否创建 initial view,如果勾选,Eclipse 会创建 MVC 分离的代码框架。另外,开发人员也随时可以创建 View。我们先来看第一种方式:

新建一个 SAPUI5 Application Project,project name 为zsapui5_butto_mvc,勾选 Create an Initial View:

点击 Next,选择 JavaScript View,把 View 命名为 master:

点击 Finish,代码框架创建完成。来探索一下代码:

代码说明

index.html 文件

首先还是 index.html (在 WebContent 文件夹下),我们注意到,Application area 的代码发生了变化,这个是另一个常用的模式。

<script>
        sap.ui.localResources("zsapui5_button_mvc");
        var app = new sap.m.App({initialPage:"idmaster1"});
        var page = sap.ui.view({
            id:"idmaster1", 
            viewName:"zsapui5_button_mvc.master", 
            type:sap.ui.core.mvc.ViewType.JS});
        app.addPage(page);
        app.placeAt("content");
</script
  • sap.ui.localResources("zsapui5_button_mvc"); : 作用是将当前目录下的 zsapui5_button_mvc 文件夹注册为当前文件夹,程序会在这个文件夹下查找 view 的代码和 controller 的代码。我们刚才把 view 命名为 master,所以 OpenUI5 在 ./zsapui5_button_mvc 文件夹下查找master.view.js,把这个文件作为存放 view 的代码文件。同理,在这个文件夹下查找 master.controller.js,把这个文件作为存放 controller 的代码文件。后面我们会专门介绍文件位置如何处理的问题,暂且不表。

  • new sap.m.App: 创建一个 sap.m.App 对象,sap.m.App 对象是
    SAP 移动 app 的根元素 (root element),它提供导航的功能,并且将一些
    header 标签加到 HTML 页,这些 header 标签对移动 app 有某些作用。

  • sap.ui.view: 定义一个 view,设定 id, view name 和 type,这个 view
    赋值给 page 并添加到 app 中。app 的初始页需要用到 view 的 id,而view 的 name 则和上面 sap.ui.localResources("zsapui5_button_mvc");
    语句一起,确定了代码文件的位置。

  • app.placeAt("content"): app 放在 DIV 中,UI 就可以显示。

View 文件

View 文件为 WebContent/zsapui5_button_mvc/master.view.js。代码如下:

sap.ui.jsview("zsapui5_button_mvc.master", {

    /** Specifies the Controller belonging to this View. 
    * In the case that it is not implemented, or that "null" is returned, this View does not have a Controller.
    * @memberOf zsapui5_button_mvc.master
    */ 
    getControllerName : function() {
        return "zsapui5_button_mvc.master";
    },

    /** Is initially called once after the Controller has been instantiated. It is the place where the UI is constructed. 
    * Since the Controller is given to this method, its event handlers can be attached right away. 
    * @memberOf zsapui5_button_mvc.master
    */ 
    createContent : function(oController) {
        return new sap.m.Page({
            title: "Title",
            content: [
            
            ]
        });
    }
});

里面有两个函数,getControllerName 函数用于返回 controller name,createContent 函数用于返回页面上要显示的元素,比如我们现在要返回的是一个 Button,我们将这个函数改写为:

    createContent : function(oController) {
        var oButton = new sap.m.Button({
            text: "Click me",
            press: oController.onButtonPressed
        });
        
        return oButton;
    }

点击的时候,调用 controller 中的 onButtonPressed 方法。

控制器代码文件

控制器代码文件为 WebContent/zsapui5_button_mvc/master.controller.js。在Eclipse 中创建的 Controller, 起始代码如下:

sap.ui.controller("zsapui5_button_mvc.master", {

/**
* Called when a controller is instantiated and its View controls (if available) are already created.
* Can be used to modify the View before it is displayed, to bind event handlers and do other one-time initialization.
* @memberOf zsapui5_button_mvc.master
*/
//  onInit: function() {
//
//  },

/**
* Similar to onAfterRendering, but this hook is invoked before the controller's View is re-rendered
* (NOT before the first rendering! onInit() is used for that one!).
* @memberOf zsapui5_button_mvc.master
*/
//  onBeforeRendering: function() {
//
//  },

/**
* Called when the View has been rendered (so its HTML is part of the document). Post-rendering manipulations of the HTML could be done here.
* This hook is the same one that SAPUI5 controls get after being rendered.
* @memberOf zsapui5_button_mvc.master
*/
//  onAfterRendering: function() {
//
//  },

/**
* Called when the Controller is destroyed. Use this one to free resources and finalize activities.
* @memberOf zsapui5_button_mvc.master
*/
//  onExit: function() {
//
//  }

});

我们看到,这些函数都被注释掉了,它们是 controller 生命周期中很重要的方法,我们后面再介绍,目前我们只需要加上 onButtonPressed() 方法。我把它写在最前面,后面的代码保持不动。当然,你也可以删除。

sap.ui.controller("zsapui5_button_mvc.master", {
    onButtonPressed: function() {
        jQuery.sap.require("sap.m.MessageBox");
        sap.m.MessageBox.information("Hello from MVC.", {
            title: "SAPUI5 MVC test"
        });
    }

/**
* Called when a controller is instantiated and its View controls (if available) are already created.
* Can be used to modify the View before it is displayed, to bind event handlers and do other one-time initialization.
* @memberOf zsapui5_button_mvc.master
*/
//  onInit: function() {
//
//  },

/**
* Similar to onAfterRendering, but this hook is invoked before the controller's View is re-rendered
* (NOT before the first rendering! onInit() is used for that one!).
* @memberOf zsapui5_button_mvc.master
*/
//  onBeforeRendering: function() {
//
//  },

/**
* Called when the View has been rendered (so its HTML is part of the document). Post-rendering manipulations of the HTML could be done here.
* This hook is the same one that SAPUI5 controls get after being rendered.
* @memberOf zsapui5_button_mvc.master
*/
//  onAfterRendering: function() {
//
//  },

/**
* Called when the Controller is destroyed. Use this one to free resources and finalize activities.
* @memberOf zsapui5_button_mvc.master
*/
//  onExit: function() {
//
//  }

});

这样,就用 MVC 方式实现了和前面一样的功能。需要说明的时,Eclipse 的 Controller 代码是一种老式的代码。因为 SAP 已经停止对 Eclipse 开发插件的支持,所以也不会再更新。后面我们经常用的是 sap.ui.define 方法定义的 controller 代码。后续介绍。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 229,362评论 6 537
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 99,013评论 3 423
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 177,346评论 0 382
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 63,421评论 1 316
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 72,146评论 6 410
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 55,534评论 1 325
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 43,585评论 3 444
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 42,767评论 0 289
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 49,318评论 1 335
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 41,074评论 3 356
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 43,258评论 1 371
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 38,828评论 5 362
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 44,486评论 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 34,916评论 0 28
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 36,156评论 1 290
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 51,993评论 3 395
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 48,234评论 2 375

推荐阅读更多精彩内容