• 【Knockout】二、监控属性Observables


    MVVM和viewModel

    Knockout是建立在以下三大核心功能之上的:

    1. 监控属性和依赖跟踪(Observables and dependency tracking)
    2. 声明式绑定(Declarative bindings)
    3. 模板(Templating)

    首先让我们先来了解下MVVM模式,和viewModel的概念。

    MVVM(model、view、viewModel)是一种创建用户界面的设计模式,他旨在将一个复杂的UI简单的分割为三个部分:

    • model : 在你的应用用作存储数据;
    • view : 一个可见的、交互的UI来展现viewModel的状态;
    • viewModel : 用纯净的代码来展现ui的数据和操作,可是任意的javascript对象

    首先创建一个viewModel,仅仅需要声明一个任意的javascript对象,例如:

    var viewModel = {
      name : 'knockout'
    };

    然后为viewModel创建一个声明式的绑定view,例如:

    <div id="myview" data-bind="text : name"></div>

    最后激活knockout,例如

    ko.applyBindings(viewModel,document.getElementById('myview'));

    data-bind属性毕竟不是原生的html属性,即使它能够完美的工作,但是浏览器不认识它,你需要激活knockout使它生效。

    这样就把一个最简单的viewModel和view绑定到了一起,能够在view里显示viewModel的属性name了,但是,view却不能再viewModel改变的时候自动更新,viewModel也不能再view改变是自动更新!

    Observables

    knockout的一个重要功能observable(监控属性)就是能够自动自动探测相关的依赖与通知订阅者(automatic dependency detection and notification triggering),即在建立绑定关系的view和

    viewModel之间能够在一方改变的时候更新另一方的值。

    我们将viewModel稍作修改:

     var viewModel = {
       name : ko.observable("knockout")
     };

    现在他就能监控到变化,view就能够自动更新了。

    监控属性的读写操作:

        1.读取监控属性的值:

    viewModel.name();

        2.写一个新值到监控属性中:

    viewModel.name("new value");

    Observable Arrays

    如果你想探测并响应一个对象的变化,使用observables,但是,如果你想探测并响应一系列集合的变化,你应该使用observableArray。

    当你需要重复的增加或者删除时需要显示或者隐藏一些UI的区域时,observableArray能够派上大用场。

    var myObservableArray = ko.observableArray();    // Initially an empty array
    myObservableArray.push('Some value');            // Adds the value and notifies observers

    注:observableArray跟踪的是数组中的对象,而不是对象的状态。单纯的push一个对象到observableArray中,这个对象的属性并不是observable的,observableArray仅仅跟踪它所拥有的对象,并当有对象从数组中添加或删除时通知监听者。

    也可以像这样初始化一个observableArray:

    // This observable array initially contains three objects
    var anotherObservableArray = ko.observableArray([
        { name: "Bungle", type: "Bear" },
        { name: "George", type: "Hippo" },
        { name: "Zippy", type: "Unknown" }
    ]);

    Computed Observables (依赖监控属性)

    如果你有一个observable的firstname和一个observable的lastname,你想显示fullname怎么办?computed observables派上用场了,它是一个依赖于其他一个或者多个observables的函数,并在任意一个依赖的observable更新时它能够自动更新。

    例如:有这样一个viewModel:

    function AppViewModel() {
        this.firstName = ko.observable('Bob');
        this.lastName = ko.observable('Smith');
    }

    你可以添加一个computed observable来得到fullname:

    function AppViewModel() {
        // ... leave firstName and lastName unchanged ...
     
        this.fullName = ko.computed(function() {
            return this.firstName() + " " + this.lastName();
        }, this);
    }

    绑定UI元素:

    The name is <span data-bind="text: fullName"></span>

    当firstname或者lastname改变时fullname能够自动更新。

    可以这样使用:

    • 监控属性items表示items的集合;
    • 监控属性selectedIndexes存储当前选中的items的index集合;
    • 依赖监控属性selectedItems表示当前选中的items集合;

    改变items或者selectedIndexes都能够使依赖监控属性(selectedItems)更新,以达到更新相应的UI元素的目的。

     管理this : 

    ko.computed的第二个参数决定了this的值当我们计算依赖监控属性的值的时候,如果不传它,将不能够引用到this.firstname()或者this.lastname().

    你也可以这样做,更加方便:

    function AppViewModel() {
        var self = this;
     
        self.firstName = ko.observable('Bob');
        self.lastName = ko.observable('Smith');
        self.fullName = ko.computed(function() {
            return self.firstName() + " " + self.lastName();
        });
    }

    self能够在funciton的闭包中被捕获到,在它任何的内嵌的function中任然是可用的。

    判断一个属性是否为依赖监控属性(computed observable)

    for (var prop in myObject) {
        if (myObject.hasOwnProperty(prop) && !ko.isComputed(myObject[prop])) {
            result[prop] = myObject[prop];
        }
    }

    另外,ko提供了一些函数能够操作监控属性和依赖监控属性:

    • ko.isObservable : 对于所有的observable,observable array,computed observable将返回true;
    • ko.isWritableObservable : 对于所有的observable,observable array,writable computed observable返回true;

     使用peek控制依赖关系:

    正常情况下,ko的自动依赖跟踪能够完成你所期望的工作,但是,你也许希望控制哪个observable来更新或者不更新你的computed observable,peek()函数能够使你的observable或者computed不创建依赖关系。

    例如:

    ko.computed(function() {
        var params = {
            page: this.pageIndex(),
            selected: this.selectedItem.peek()
        };
        $.getJSON('/Some/Json/Service', params, this.currentPageData);
    }, this);

    在这个例子中,一个computed observable依赖其他两个observable使用ajax获取数据,当pageIndex改变的时候,computed observable就会更新,重新获取数据,但是computed observable会忽略掉selectedItem的改变,

    因为它使用了peek()。在这种情况下,用户也许只希望使用selectedItem的值仅仅作为跟踪目的当一个新的数据集合下载完成以后。

    构造computed observable

    一个computed observable可以使用以下方式构造:

    1.ko.computed( evaluator [, targetObject, options] )

      • evaluator : 一个用来计算当前依赖监控属性的值的函数。
      • targetObject : 可选,如果定义了,它将作为ko激活你的回调函数时候的this值。
      • options : 可选,备用。

    2.ko.computed(options),options包含以下属性:

      • read : 必须的。用来计算当前依赖监控属性的值的函数。
      • write : 可选的。使依赖监控属性writable,这个函数接收一个value参数以用来write到computed observable中。
      • owner : 可选的。如果定义了,它将作为回调函数的this值。
      • pure : 可选的。如果为true,这个computed observable将被设置为pureComputed observable。
      • deferEvaluation : 可选的。不常用
      • disposeWhen : 可选的。不常用
      • disposeWhenNodeIsRemoved : 可选的。不常用。

    computed observable的使用

    • dispose() : 手动管理依赖监控属性,清楚所有依赖的订阅关系,这个函数非常有用,当你想停止computed observable的更新或者清除内存的时候
    • extend(exteners) : 扩展方法。
    • getDependenciesCount() : 返回当前computed observable的依赖数量。
    • getSubScriptionsCount() : 
    • isActive() : 返回computed observable是否会更新在将来的某个时候,一个没有任何依赖的computed observable是不会被激活的
    • peek() : 返回computed observable中没有创建依赖关系的值。
    • subscribe(callback,[callbackTarget,event]) : 注册一个手动的订阅来接收computed observable改变的通知。
     
  • 相关阅读:
    Ubuntu16.04编译Android6.0/cm13.0教程及相关错误解决办法
    TWRP基于omnirom 6.0.1编译教程
    教你一招:解决Win 10安装软件时提示:文件系统错误 (-1073740940)
    红米3 TWRP-3.0.2(android_6.0.1_r72分支)中文版Recovery更新于20161018
    C# Note32: 查漏补缺
    postgreSQL使用杂谈
    Granfana+PostgreSQL
    WIndows下使用Grafana+InfluxDB打造监控系统
    【译】历史上的名人如何利用不同的思维方式成就自己
    【译】Focused and Diffuse Modes(专注与发散模式)
  • 原文地址:https://www.cnblogs.com/baicj/p/5075910.html
Copyright © 2020-2023  润新知