当前位置: 首页 > 工具软件 > AWTK-MVVM > 使用案例 >

AWTK-MVVM:数据与命令的绑定

翟嘉志
2023-12-01

MVVM

MVVMModel-View-ViewModel,它是MVC的改进版。
MVVM优点:

  1. 低耦合。视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的View上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
  2. 可重用性。你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑。
  3. 独立开发。开发人员可以专注于业务逻辑和数据的开发(ViewModel)。
  4. 可测试。界面素来是比较难于测试的,测试可以针对ViewModel来写。

AWTK-MVVM

AWTK-MVVM 是一套用C语言开发的,专门为嵌入式平台优化的 MVVM 框架。它实现了数据绑定、命令绑定和窗口导航等基本功能,使用 AWTK-MVVM 开发应用程序,无需学习 AWTK 本身的 API ,只需学习绑定规则和模型的实现方式即可。
AWTK-MVVM无需手动编写和更新ViewModel的代码,它提供一个主动代码产生器,只需在编写 Model的代码时,按照固定的规则来编写注释(详细注释规则请点击查看model.md),就会根据Model的代码自动生成更新ViewModel

AWTK-MVVM 仓库:github.com/zlgopen/awtk-mvvm

前置步骤

一、编写Model

编写 Model的代码,并按照model.md的规则来编写注释。
books_manager_model.h:

/**
 * @class books_manager_model_t
 * 
 * @annotation ["model"]
 * 图书管理者模型。
 * 
 */
typedef struct _books_manager_model_t {
  /**
   * @property {int32_t} find_type
   * @annotation ["readable", "writable"]
   * 当前查找书籍方式。
   */
  int32_t find_type;
  
  /* private */
  books_manager_t* books_manager;
} books_manager_model_t;

/**
 * @method books_manager_model_create
 * 创建books_manager_model对象。
 *
 * @annotation ["constructor"]
 * @return {books_manager_model_t*} 返回books_manager_model对象。
 */
books_manager_model_t* books_manager_model_create(void);

/**
 * @method books_manager_model_destroy
 * 销毁books_manager_model对象。
 *
 * @annotation ["destructor"]
 * @param {books_manager_model_t*} model books_manager_model对象。
 * 
 * @return {ret_t} 返回RET_OK表示成功,否则表示失败。
 */
ret_t books_manager_model_destroy(books_manager_model_t* model);

二、利用工具生成ViewModel

请查看model.md的9.3小节:代码生成器。

三、注册ViewModel并通过导航器打开View

ret_t application_init(void) {
  mvvm_init();
  
  /* 其他初始化设置 */
  /* ... */
  
  /* 注册ViewModel,ViewModel名称为"books_manager_model" */
  view_model_factory_register("books_manager_model", books_manager_model_view_model_create);

  return navigator_to("home_page");  /* 通过导航器打开View */
}

四、绑定View与ViewModel

home_page.xml:

<window name="home_page" v-model="books_manager_model">
  <!-- 省略... -->
</window>

数据绑定

基本数据绑定

  • v-data 表示该属性是一个数据绑定规则。
  • 第二部分(如示例中的value)是控件属性的名称,表示对该控件的哪个属性进行绑定。
  • 属性的值放在’{‘和’}'之间,里面是 Model 中变量的名称。
```xml
<window name="home_page" v-model="books_manager_model">
  <combo_box_ex name="cmb_find" x="610" y="234" w="180" h="28" v-data:value="{find_type}"/>
  <!-- 省略... -->
</window>

按条件进行数据绑定

通过嵌入表达式实现简单的逻辑判断。
当find_type等于4时,date_picker可见:

<window name="home_page" v-model="books_manager_model">
  <date_picker name="date_picker" x="606" y="272" w="188" h="201" v-data:visible="{find_type == 4}">
    <!-- 省略... -->
  </date_picker>
  <!-- 省略... -->
</window>

当find_type等于1时,edit_data控件的input_type等于2,否则等于0:

<window name="home_page" v-model="books_manager_model">
  <edit name="edit_data" x="620" y="338" w="160" h="28" v-data:input_type='{if(find_type == 1, 2, 0)}'>
  </edit>
  <!-- 省略... -->
</window>

由于表达式中<>"等字符对于 XML 来说是特殊字符,需要转换成对应的实体 (entity),但是转换之后表达式不太直观,此时可以把属性提出来,放在 property 标签中,并用 CDATA 把它的值包起来。

当find_type大于0且小于4时,edit_data可见:


<window name="home_page" v-model="books_manager_model">
  <edit name="edit_data" x="620" y="338" w="160" h="28">
    <property name="v-data:visible"><![CDATA[ {(find_type > 0 && find_type < 4) ? true : false} ]]></property>
  </edit>
  <!-- 省略... -->
</window>

详细内容请参考:
数据绑定:data_binding.md
高级用法:advance_usages.md

命令绑定

命令绑定规则也是一个控件属性:
属性的名称由两部分组成,两者之间用英文冒号分隔。

  • v-on 表示该属性是一个命令绑定规则。
  • 第二部分是控件事件的名称,表示对该事件触发时,自动执行指定的命令。
    命令的名称放在’{‘和’}'之间,命令对应 Model 中的函数。

在view中关联"btn_add"控件的点击事件和add命令:

<window name="home_page" v-model="books_manager_model">
  <button name="btn_add" x="610" y="115" w="180" h="36" tr_text="add" v-on:click="{add}"/>
  <!-- 省略... -->
</window>

在model中添加add命令函数(注意:每次修改model都需要使用工具更新ViewModel代码!):

/**
 * @method books_manager_model_add
 * 添加图书。
 *
 * @annotation ["command:add"]
 * @param {books_manager_model_t*} model books_manager_model对象。
 *
 * @return {ret_t} 返回RET_OK表示成功,否则表示失败。
 */
ret_t books_manager_model_add(books_manager_model_t* model);

目前支持的事件有(以后更加需要增加):

事件
click点击事件
pointer_down指针按下事件
pointer_up指针松开事件
key_down按键按下事件
key_long_press按键长按事件
key_up按键松开事件
global_key_down全局按键按下事件
global_key_long_press全局按键长按事件
global_key_up全局按键松开事件
value_changed值改变事件
value_changed_by_ui值(通过 UI 修改)改变事件

详细内容请参考:
命令绑定:command_binding.md

 类似资料: