kendo-ui的MVVM模式

简介: kendo-ui的MVVM模式

摘要:


  

MVVM(Model View ViewModel)是一种帮助开发者将数据从模型分离的设计模式。MVVM的ViewModel负责将数据对象从模型中分离出来,通过这种方式数据就很容易控制数据如何显示在视图上。


创建View-Model对象:


  

首先我们需要创建一个View-Model对象,他是控制你的数据显示在视图上。


创建对象


var viewModel = kendo.observable({
    name: "John Doe",
    displayGreeting: function() {
        var name = this.get("name");
        alert("Hello, " + name + "!!!");
    }
});


创建视图


<div id="view">
    <input data-bind="value: name" />
    <button data-bind="click: displayGreeting">Display Greeting</button>
</div>


然后将对象绑定到视图上


kendo.bind($("#view"), viewModel);


如何工作呢?

  

input元素的value值是通过data-bind属性绑定到viewModel的name字段,这个绑定是双向的,当改变viewModel的name字段值,视图上input的value值也会被改变。当改变视图上input元素的value值,viewModel的name字段也会被改变。


绑定:

  

元素通过data-bind属性绑定到viewModel,当你想通过一个对象绑定到视图上,你可以像下面这样定义视图模型


<div data-bind="text: person.name">
</div>
<script>
var viewModel = kendo.observable({
    person: {
        name: "John Doe"
    }
});
kendo.bind($("div"), viewModel);
</script>


data-bind还支持的属性有source, html, attr, visible, enabled等,支持多个属性,以逗号分隔。


注意:

  

绑定不是javascript,像下面这样的绑定就是不对的


<div data-bind="text: person.name.toLowerCase()"></div>

 

ObservableObject:


  

kendo.data.ObservableObject是MVVM模式中非常重要的一部分,它支持跟踪变化和通知用户发生变化,所有的视图模型对象都继承它。


创建ObservableObject


var viewModel1 = new kendo.data.ObservableObject( {
  field1: "value1",
  field2: "value2"
});
var viewModel2 = kendo.observable( {
  field1: "value1",
  field2: "value2"
});


上面两种方式都可以创建ObservableObject


注意:视图模型必须在定义ObservableObject之后使用,否则无效。


设置与获取属性值:

  

我们可以通过viewModel对象来获取属性值,如下:


var viewModel = kendo.observable({
    name: "John Doe"
});
viewModel.set("name", "Jane Doe"); //set the "name" field to "Jane Doe"
var name = viewModel.get("name");
alert(name); // shows "Jane Doe"


关键字this:

  

我们可以通过this来获取视图模型的其他属性值,如下:


<span data-bind="text: fullName"></span>
<script>
var viewModel = kendo.observable({
    firstName: "John",
    lastName: "Doe",
    fullName: function() {
        return this.get("firstName") + " " + this.get("lastName");
    }
});
kendo.bind($("span"), viewModel);
</script>


data-bind属性:


attr:

  

attr可以用来绑定DOM元素的属性,例如:href、title等,对于多个属性我们可以用对象来绑定,如下:


<img id="logo" data-bind="attr: { src: imageSource, alt: imageAlt }" />
<script>
var viewModel = kendo.observable({
    imageSource: "http://www.telerik.com/image/kendo-logo.png",
    imageAlt: "Kendo Logo"
});
kendo.bind($("#logo"), viewModel);
</script>


显示到视图上就会变成如下:


<img id="logo" src="http://www.telerik.com/image/kendo-logo.png" alt="Kendo Logo"" />


checked:

  

checked属性使用来选择复选框或者单选框,属性值为true或false,如下:


<input type="checkbox" data-bind="checked: isChecked" />
<script
var viewModel = kendo.observable({
    isChecked: false
});
kendo.bind($("input"), viewModel);
</script>


对于多个复选框,根据value值来决定选中哪一个复选框,属性值是一个数组,如下:


<input type="checkbox" value="Red"   data-bind="checked: colors" />
<input type="checkbox" value="Green" data-bind="checked: colors" />
<input type="checkbox" value="Blue"  data-bind="checked: colors" />
<script>
var viewModel = kendo.observable({
    colors: ["Red"]
});
kendo.bind($("input"), viewModel);
</script>


单选框,如下:


<input type="radio" value="Red"   name="color" data-bind="checked: selectedColor" />
<input type="radio" value="Green" name="color" data-bind="checked: selectedColor" />
<input type="radio" value="Blue"  name="color" data-bind="checked: selectedColor" />
<script>
var viewModel = kendo.observable({
    selectedColor: "Green"
});
kendo.bind($("input"), viewModel);
</script>


注意:单选框应该有相同的name值,checked只适合可以勾选的元素。


click:


  

click属性将绑定一个方法到视图模型上,当点击这个DOM元素该方法将会被调用。


<div id="view">
<span data-bind="click: showDescription">Show description</span>
<span data-bind="visible: isDescriptionShown, text: description"></span>
<script>
var viewModel = kendo.observable({
    description: "Description",
    isDescriptionShown: false,
    showDescription: function(e) {
        // show the span by setting isDescriptionShown to true
        this.set("isDescriptionShown", true);
    }
});
kendo.bind($("#view"), viewModel);
</script>
 </div>


我们也可以通过events属性来绑定click事件,如下:


<span data-bind="click: clickHandler"></span>

 

<span data-bind="events: { click: clickHandler }"></span>


阻止事件冒泡

  

我们可以使用stopPropagation来阻止click事件冒泡,如下:


<span data-bind="click: click">Click</span>
<script>
var viewModel = kendo.observable({
    click: function(e) {
        e.stopPropagation();
    }
});
kendo.bind($("span"), viewModel);
</script>


阻止默认事件

  

使用preventDefault方法来阻止浏览器默认行为。


<a href="http://example.com" data-bind="click: click">Click</span>
<script>
var viewModel = kendo.observable({
    click: function(e) {
        // stop the browser from navigating to http://example.com
        e.preventDefault();
    }
});
kendo.bind($("a"), viewModel);
</script>


custom:


  

kendo MVVM提供自定义绑定属性,这有利于我们自己做一些扩展。我们可以通过kendo.data.Binder来注册一个属性。


单项绑定

  

这种自定义属性当视图模型的属性值改变时,DOM元素将被更新,但是当DOM元素改变时并不会更新视图模型属性值。如下:


<script>
    kendo.data.binders.slide = kendo.data.Binder.extend({
        refresh: function() {
            var value = this.bindings["slide"].get();
            if (value) {
                $(this.element).slideDown();
            } else {
                $(this.element).slideUp();
            }
        }
    });
    var viewModel = kendo.observable({
        slideValue: true
    });
    kendo.bind(document.body, viewModel);
</script>
<div id="target" data-bind="slide: slideValue">
    One Big Orange Square.
</div>


 

双向绑定

  

这种自定义的属性支持双向绑定,即当DOM元素改变时会触发视图模型的改变,当视图模型属性值改变时会触发DOM元素的改变。如下:


<script>
    kendo.data.binders.numericValue = kendo.data.Binder.extend({
        init: function(element, bindings, options) {
            //call the base constructor
            kendo.data.Binder.fn.init.call(this, element, bindings, options);
            var that = this;
            //listen for the change event of the element
            $(that.element).on("change", function() {
                that.change(); //call the change function
            });
        },
        refresh: function() {
            var that = this,
                value = that.bindings["numericValue"].get(); //get the value from the View-Model
            $(that.element).val(value); //update the HTML input element
        },
        change: function() {
            var value = this.element.value;
            //in this example the View-Model will be updated only if the value of the input is a number
            if (!isNaN(value)) {
                this.bindings["numericValue"].set(value); //update the View-Model
            }
        }
    });
    //View-Model source
    var viewModel = kendo.observable({
        number: 10
    });
    kendo.bind(document.body, viewModel);
</script>
<!-- View source -->
<input data-bind="numericValue: number" />
Input value: <span data-bind="text: number" />


组件绑定

  

这种自定义属性支持当视图模型属性值改变时会触发组件的改变。如下:


//the following example demonstrates how to bind the max value of a NumericTextBox widget
kendo.data.binders.widget.max = kendo.data.Binder.extend({
    init: function(widget, bindings, options) {
        //call the base constructor
        kendo.data.Binder.fn.init.call(this, widget.element[0], bindings, options);
    },
    refresh: function() {
        var that = this,
        value = that.bindings["max"].get(); //get the value from the View-Model
        $(that.element).data("kendoNumericTextBox").max(value); //update the widget
    }
});
<!-- View source -->
<input data-role="numerictextbox" id="numeric" data-bind="value: value, max: max" />


自定义属性的方法讲解


init

 

init类似于构造函数,如果这个函数被重写了,其基本构造函数首先被显示调用。


refresh

 

refresh负责更新DOM元素。当视图模型的属性值改变时,它会被执行。

change

   

change负责更新视图模型的属性值。DOM元素发生变化时,它会被执行。


disabled:


  

disabled是禁用DOM元素,属性值为true或false。适合的DOM元素为:input、select、textarea。当DOM元素的disabled属性值被设置为true时,则他的value值不能被改变。


<div id="view">
<input type="text" data-bind="value: name, disabled: isNameDisabled" />
<button data-bind="click: disableInput">Disable</button>
<script>
var viewModel = kendo.observable({
    isNameDisabled: false,
    name: "John Doe",
    disableInput: function() {
        this.set("isNameDisabled", true);
    }
});
kendo.bind($("#view"), viewModel);
</script>
 </div>


注意:0, null, undefined,"",''都会被当成false。


enable:



与disabled相同,功能相反。


events:



events将视图模型定义的方法绑定到DOM元素上,当对应事件在DOM元素发生时,该方法会被执行。如下:


<div id="view">
    <span data-bind="events: { mouseover: showDescription, mouseout: hideDescription }">Show description</span>
    <span data-bind="visible: isDescriptionShown, text: description"></span>
</div>
<script>
    var viewModel = kendo.observable({
        description: "Description",
        isDescriptionShown: false,
        showDescription: function(e) {
            // show the span by setting isDescriptionShown to true
            this.set("isDescriptionShown", true);
        },
        hideDescription: function(e) {
            // hide the span by setting isDescriptionShown to false
            this.set("isDescriptionShown", false);
        }
    });
    kendo.bind($("#view"), viewModel);
</script>


html:

  

html是将视图模型定义的值以html的形式插入到DOM元素内。如下:


<span data-bind="html: name"></span>
<script>
var viewModel = kendo.observable({
    name: "<strong>John Doe</strong>"
});
kendo.bind($("span"), viewModel);
</script>


结果为


<span><strong>John Doe</strong></span>


注意:并不是所有DOM元素都支持html属性,比如table。他只适合内部没有固定结构的html元素。


invisible:


  

invisible控制DOM元素是否显示。属性值true或false,当设置为true时,DOM元素将被隐藏,对应css的display属性将被设置为none。如下:


<div id="view">
    <div data-bind="invisible: isInvisible">some content
    </div>
    <button data-bind="click: show">Show</button>
</div>
<script>
var viewModel = kendo.observable({
    isInvisible: true,
    show: function() {
        this.set("isInvisible", false);
    }
});
kendo.bind($("#view"), viewModel);
</script>


初始div元素是隐藏的,因为isInvisible设置为true,当点击按钮时,isInvisible被设置为false,div元素显示。


source:


  

source用来渲染DOM元素的模板,模板是通过data-template属性来指定,属性值为模板的id,如果未指定则会根据元素的name值。如果视图模型中的属性值为数组时,会自动循环每一项并渲染模板到DOM元素内。


<ul data-template="ul-template" data-bind="source: products">
</ul>
<script id="ul-template" type="text/x-kendo-template">
    <li>
        id: <span data-bind="text: id"></span>
        name: <span data-bind="text: name"></span>
    </li>
</script>
<script>
var viewModel = kendo.observable({
    products: [
        { id: 1, name: "Coffee" },
        { id: 2, name: "Tea" },
        { id: 3, name: "Juice" }
    ]
});
kendo.bind($("ul"), viewModel);
</script>


结果为


<ul>
    <li>
        id: <span>1</span>
        name: <span>Coffee</span>
    </li>
    <li>
        id: <span>2</span>
        name: <span>Tea</span>
    </li>
    <li>
        id: <span>3</span>
        name: <span>Juice</span>
    </li>
</ul>


如果数组中不全是对象,则可以使用this代替当前属性值,如下:


<ul data-template="ul-template" data-bind="source: products">
</ul>
<script id="ul-template" type="text/x-kendo-template">
    <li data-bind="text: this"></li>
</script>
<script>
var viewModel = kendo.observable({
    products: [ "Coffee", "Tea", "Juice" ]
});
kendo.bind($("ul"), viewModel);
</script>


结果为


<ul>
    <li>Coffee</li>
    <li>Tea</li>
    <li>Juice</li>
</ul>


给select元素设置source属性:


<select data-text-field="name" data-value-field="id"
       data-bind="source: products"></select>
<script>
var viewModel = kendo.observable({
    products: [
        { id: 1, name: "Coffee" },
        { id: 2, name: "Tea" },
        { id: 3, name: "Juice" }
    ]
});
kendo.bind($("select"), viewModel);
</script>


显示在视图上为


<select>
    <option value="1">Coffee</option>
    <option value="2">Tea</option>
    <option value="3">Juice</option>
</select>


style:


  

style属性用来设置DOM元素的样式,如下:


<span data-bind="style: {color: priceColor, fontWeight: priceFontWeight},
             text: price"></span>
<script>
var viewModel = kendo.observable({
    price: 42,
    priceColor: function() {
        var price = this.get("price");
        if (price <= 42) {
            return "#00ff00";
        } else {
            return "#ff0000";
        }
    },
    priceFontWeight: function() {
        var price = this.get("price");
        if (price <= 42) {
            return "bold";
        } else {
            return ""; //will reset the font weight to its default value
        }
    }
});
kendo.bind($("span"), viewModel);
</script>


结果为


<span style="color: #00ff00; font-weight: bold">42</span>


注意:对于这种font-weight, font-size, background-color应该使用驼峰格式。


text:


  

text用来设置元素文本内容,如下:


<span data-bind="text: name"></span>
<script>
var viewModel = kendo.observable({
    name: "John Doe"
});
kendo.bind($("span"), viewModel);
</script>


结果为


<span>John Doe</span>

 

value:


  

value属性用来设置DOM元素的value值,所以他只适合带有value属性的DOM元素,比如input, textarea和select。此属性是双向绑定的,即任何一方改变都会触发另一方的改变。如下:


<div id="view">
    <input data-bind="value: inputValue" />
    <textarea data-bind="value: textareaValue"></textarea>
</div>
<script>
var viewModel = kendo.observable({
    inputValue: "Input value",
    textareaValue: "Textarea value"
});
kendo.bind($("#view"), viewModel);
</script>


注意:如果DOM元素改变并不是实时触发视图模型的属性值改变,而是当DOM元素变换结束之后。


我们可以通过data-value-update属性控制什么时候更新视图模型,如下:


<div id="view">
    <input data-value-update="keyup" data-bind="value: inputValue" />
</div>
<script>
var viewModel = kendo.observable({
    inputValue: "InputValue"
});
kendo.bind($("#view"), viewModel);
</script>


上面的代码是当我们在输入框松开键盘之后就更新视图模型。


对于下拉选择,我们可以像下面这样


<select data-role="dropdownlist" data-option-label="Select product..." data-value-primitive="true"
  data-value-field="id" data-text-field="name" data-bind="value: selectedProductId, source: products">
</select>
<script>
var viewModel = kendo.observable({
    selectedProductId: null,
    products: [
        { id: 1, name: "Coffee" },
        { id: 2, name: "Tea" },
        { id: 3, name: "Juice" }
    ]
});
kendo.bind($("select"), viewModel);
</script>


visible:


  

与invisible类似,功能相反。

 

 

相关文章
|
关系型数据库 MySQL 数据库
基于Flink CDC 开发,支持Web-UI的实时KingBase 连接器,三大模式无缝切换,效率翻倍!
TIS 是一款基于Web-UI的开源大数据集成工具,通过与人大金仓Kingbase的深度整合,提供高效、灵活的实时数据集成方案。它支持增量数据监听和实时写入,兼容MySQL、PostgreSQL和Oracle模式,无需编写复杂脚本,操作简单直观,特别适合非专业开发人员使用。TIS率先实现了Kingbase CDC连接器的整合,成为业界首个开箱即用的Kingbase CDC数据同步解决方案,助力企业数字化转型。
3258 5
基于Flink CDC 开发,支持Web-UI的实时KingBase 连接器,三大模式无缝切换,效率翻倍!
|
设计模式 编解码 API
Flutter UI设计模式与实现:深入探索与实践
【7月更文挑战第20天】Flutter以其独特的声明式UI模式和丰富的UI组件库,为移动应用开发提供了强大的支持。通过深入理解Flutter的UI设计模式和实现技巧,开发者可以构建出高性能、可维护性强的UI界面。同时,随着Flutter生态的不断完善和发展,相信未来Flutter将在移动应用开发领域发挥更加重要的作用。
|
XML 存储 设计模式
Jetpack 系列(5)—— Android UI 架构演进:从 MVC 到 MVP、MVVM、MVI
Jetpack 系列(5)—— Android UI 架构演进:从 MVC 到 MVP、MVVM、MVI
1102 10
Jetpack 系列(5)—— Android UI 架构演进:从 MVC 到 MVP、MVVM、MVI
HMI-34-【运动模式】实现运动模式的UI上电逻辑控制
今天这界面上没有实际的增加,仅仅是实把运动模式UI上电控制逻辑实现了一下,其实到这个模块的时候,就会发现之前在写舒适模式的时候的一些问题了,有好内容可以抽象出来了,不用每次都实现一遍了。不过现在还比较懒,还是先以实现为主,和面的内容放在优化里面。废话不多说,开始搞事情。不过为了吸你们开下去,现在把目前进度放在了。
|
存储 设计模式 测试技术
浅谈UI自动化必备的PO模式
PO模式的全名叫做page Object:页面-对象模式。简单的说就是:一个页面是一个类,元素在页面中,所以每个元素的定位信息是这个类中的一个变量;这个页面的常规业务操作是这个类中的一个个成员方法。PO模式是自动化测试框架中很重要的一种设计模式。
2104 1
浅谈UI自动化必备的PO模式
|
Web App开发 测试技术
Chrome-headless 模式,没有UI界面的自动化UI测试
Chrome-headless 模式,没有UI界面的自动化UI测试
Chrome-headless 模式,没有UI界面的自动化UI测试
|
XML 前端开发 定位技术
Android MVVM框架使用(十三)UI更新 (App启动白屏优化、适配Android10.0深色模式)
Android MVVM框架使用(十三)UI更新 (App启动白屏优化、适配Android10.0深色模式)
744 0
Android MVVM框架使用(十三)UI更新 (App启动白屏优化、适配Android10.0深色模式)
|
设计模式 搜索推荐 数据安全/隐私保护
移动应用UI设计模式摘录汇总
版权声明:本文为半吊子子全栈工匠(wireless_com,同公众号)原创文章,未经允许不得转载。
993 0
|
开发框架 前端开发 JavaScript
【HarmonyOS Next之旅】基于ArkTS开发(二) -> UI开发一
本文介绍了方舟开发框架(ArkUI)及其两种开发范式:基于ArkTS的声明式开发范式和类Web开发范式。ArkUI是用于构建HarmonyOS应用界面的UI框架,提供极简UI语法和基础设施。声明式开发范式使用ArkTS语言,以组件、动画和状态管理为核心,适合复杂团队协作;类Web开发范式采用HML、CSS、JavaScript三段式开发,适用于简单界面应用,贴近Web开发者习惯。文中还概述了两者的架构和基础能力,帮助开发者选择合适的范式进行高效开发。
475 15

热门文章

最新文章